将 .py 和 .pyi 后缀名改为了 .vp 和 .vpi 后缀名
This commit is contained in:
202
VKernel/Kernel/sched/coroutine.vp
Normal file
202
VKernel/Kernel/sched/coroutine.vp
Normal file
@@ -0,0 +1,202 @@
|
||||
import mm
|
||||
import drivers.serial.uart.serial as serial
|
||||
import asm
|
||||
import t, c
|
||||
|
||||
CORO_READY: t.CDefine = 0
|
||||
CORO_RUNNING: t.CDefine = 1
|
||||
CORO_YIELDED: t.CDefine = 2
|
||||
CORO_DONE: t.CDefine = 3
|
||||
MAX_COROUTINES: t.CDefine = 32
|
||||
CORO_STACK_SIZE: t.CDefine = 8192
|
||||
|
||||
|
||||
@t.Object
|
||||
class Coroutine:
|
||||
rsp: t.CUInt64T
|
||||
stack: t.CVoid | t.CPtr
|
||||
stack_size: t.CUInt64T
|
||||
func: t.CVoid | t.CPtr
|
||||
arg: t.CVoid | t.CPtr
|
||||
state: t.CInt
|
||||
cid: t.CInt
|
||||
caller_rsp: t.CUInt64T
|
||||
ret_val: t.CInt
|
||||
|
||||
def resume(self) -> t.CInt:
|
||||
global _coro_old_rsp, _coro_new_rsp
|
||||
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
|
||||
if self.state == CORO_DONE: return self.ret_val
|
||||
if self.state != CORO_READY and self.state != CORO_YIELDED: return -1
|
||||
prev_cid: t.CInt = m.current_cid
|
||||
m.current_cid = self.cid
|
||||
self.state = CORO_RUNNING
|
||||
_coro_old_rsp = c.Addr(m.coroutines[prev_cid].rsp)
|
||||
_coro_new_rsp = c.Addr(self.rsp)
|
||||
self.caller_rsp = t.CUInt64T(_coro_old_rsp)
|
||||
_coro_switch()
|
||||
if self.state == CORO_DONE:
|
||||
return self.ret_val
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def _yield():
|
||||
global _coro_old_rsp, _coro_new_rsp
|
||||
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
|
||||
cid: t.CInt = m.current_cid
|
||||
if cid < 0: return
|
||||
m.coroutines[cid].state = CORO_YIELDED
|
||||
prev_cid: t.CInt = -1
|
||||
i: t.CInt
|
||||
for i in range(m.count):
|
||||
if m.coroutines[i].state == CORO_RUNNING and m.coroutines[i].caller_rsp != 0:
|
||||
prev_cid = i
|
||||
break
|
||||
if prev_cid < 0: return
|
||||
m.current_cid = prev_cid
|
||||
_coro_old_rsp = c.Addr(m.coroutines[cid].rsp)
|
||||
_coro_new_rsp = c.Addr(m.coroutines[prev_cid].rsp)
|
||||
_coro_switch()
|
||||
|
||||
@property
|
||||
def is_done(self) -> t.CInt:
|
||||
if self.state == CORO_DONE:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@property
|
||||
def is_yielded(self) -> t.CInt:
|
||||
if self.state == CORO_YIELDED:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@property
|
||||
def retval(self) -> t.CInt:
|
||||
return self.ret_val
|
||||
|
||||
|
||||
@t.Object
|
||||
class CoroutineManager:
|
||||
coroutines: t.CArray[Coroutine, MAX_COROUTINES]
|
||||
current_cid: t.CInt
|
||||
count: t.CInt
|
||||
|
||||
def __init__():
|
||||
global _coro_mgr_ptr
|
||||
_coro_mgr_ptr = c.Addr(_coro_mgr)
|
||||
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
|
||||
m.current_cid = 0
|
||||
m.count = 1
|
||||
m.coroutines[0].state = CORO_RUNNING
|
||||
m.coroutines[0].cid = 0
|
||||
m.coroutines[0].caller_rsp = 0
|
||||
m.coroutines[0].ret_val = 0
|
||||
m.coroutines[0].rsp = 0
|
||||
m.coroutines[0].stack = None
|
||||
m.coroutines[0].stack_size = 0
|
||||
m.coroutines[0].func = None
|
||||
m.coroutines[0].arg = None
|
||||
main_rsp_ptr: t.CVoid | t.CPtr = c.Addr(m.coroutines[0].rsp)
|
||||
c.Asm(f"""mov qword ptr [{c.AsmInp(main_rsp_ptr, t.ASM_DESCR.REG_ANY)}], rsp""",
|
||||
op=[t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
|
||||
@staticmethod
|
||||
def current() -> Coroutine | t.CPtr:
|
||||
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
|
||||
return c.Addr(m.coroutines[m.current_cid])
|
||||
|
||||
@staticmethod
|
||||
def get_coroutine(cid: t.CInt) -> Coroutine | t.CPtr:
|
||||
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
|
||||
if cid < 0 or cid >= m.count: return None
|
||||
return c.Addr(m.coroutines[cid])
|
||||
|
||||
@staticmethod
|
||||
def create(func: t.CVoid | t.CPtr, arg: t.CVoid | t.CPtr) -> Coroutine | t.CPtr:
|
||||
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
|
||||
if m.count >= MAX_COROUTINES: return None
|
||||
cid: t.CInt = m.count
|
||||
m.count += 1
|
||||
co: Coroutine | t.CPtr = c.Addr(m.coroutines[cid])
|
||||
co.state = CORO_READY
|
||||
co.cid = cid
|
||||
co.func = func
|
||||
co.arg = arg
|
||||
co.caller_rsp = 0
|
||||
co.ret_val = 0
|
||||
stack_ptr: t.CVoid | t.CPtr = mm.malloc(CORO_STACK_SIZE)
|
||||
if not stack_ptr: return None
|
||||
co.stack = stack_ptr
|
||||
co.stack_size = CORO_STACK_SIZE
|
||||
stack_top: t.CUInt64T = t.CUInt64T(stack_ptr) + CORO_STACK_SIZE - 16
|
||||
stack_top = stack_top & ~t.CUInt64T(0xF)
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(c.Addr(_coro_entry))
|
||||
sp: t.CPtr = t.CPtr(stack_top)
|
||||
c.Asm(f"""mov rax, {c.AsmInp(sp, t.ASM_DESCR.REG_ANY)}
|
||||
mov qword ptr [rax - 56], 0
|
||||
mov qword ptr [rax - 48], 0
|
||||
mov qword ptr [rax - 40], 0
|
||||
mov qword ptr [rax - 32], 0
|
||||
mov qword ptr [rax - 24], 0
|
||||
mov qword ptr [rax - 16], 0
|
||||
mov qword ptr [rax - 8], 0
|
||||
mov qword ptr [rax], {c.AsmInp(entry_addr, t.ASM_DESCR.REG_ANY)}""",
|
||||
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
|
||||
stack_top = stack_top - 56
|
||||
co.rsp = stack_top
|
||||
return co
|
||||
|
||||
|
||||
_coro_mgr: CoroutineManager = CoroutineManager()
|
||||
_coro_mgr_ptr: CoroutineManager | t.CPtr = c.Addr(_coro_mgr)
|
||||
_coro_old_rsp: t.CVoid | t.CPtr
|
||||
_coro_new_rsp: t.CVoid | t.CPtr
|
||||
|
||||
@c.Attribute(t.attr.naked)
|
||||
def _coro_switch():
|
||||
c.Asm(f"""push rax
|
||||
push rbx
|
||||
push rbp
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
mov rax, qword ptr [rip + _coro_old_rsp]
|
||||
mov qword ptr [rax], rsp
|
||||
mov rax, qword ptr [rip + _coro_new_rsp]
|
||||
mov rsp, qword ptr [rax]
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbp
|
||||
pop rbx
|
||||
pop rax
|
||||
ret""",
|
||||
op=[t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
|
||||
@c.Attribute(t.attr.naked)
|
||||
def _coro_entry():
|
||||
c.Asm(f"""sub rsp, 8
|
||||
mov rax, qword ptr [rip + _coro_mgr_ptr]
|
||||
mov ecx, dword ptr [rax + 1056]
|
||||
movsxd rcx, ecx
|
||||
shl rcx, 5
|
||||
mov rdi, qword ptr [rax + rcx + 24]
|
||||
mov rax, qword ptr [rax + rcx + 16]
|
||||
call rax
|
||||
mov rax, qword ptr [rip + _coro_mgr_ptr]
|
||||
mov ecx, dword ptr [rax + 1056]
|
||||
movsxd rcx, ecx
|
||||
shl rcx, 5
|
||||
mov dword ptr [rax + rcx + 32], 3
|
||||
mov dword ptr [rax + rcx + 48], eax
|
||||
add rsp, 8""",
|
||||
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
|
||||
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
|
||||
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
|
||||
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
|
||||
Coroutine._yield()
|
||||
while True:
|
||||
asm.sti()
|
||||
asm.hlt()
|
||||
Reference in New Issue
Block a user