feat(sched): 协作 + 时间片抢占(IRQ0 返回用户态时切换)
原先 timer_tick 只置 needs_reschedule,唯一消费点是 SPAWN 阻塞循环,纯计算线程永不被切走。① 抢占点:isr32_handler 在 timer_handler(含 pic.eoi(0)/apic.eoi)返回之后、且 from_user != 0(ISR 入口读 CS 低两位)时调用 try_reschedule;栈切换仍在 _do_switch。只对 Ring3 返回路径生效,内核临界区/syscall 中途不切。② 中断帧保留在被切线程内核栈上,靠 rsp 切换自然保存/恢复,不拷贝、不在切换中途 iretq。③ 修正全局 _isr_scratch 跨线程覆盖:ISR_SAVE_CLOBBERED 把 rax/rcx/r8-r11 存在全局 scratch,抢占后跨线程会互相覆盖;_do_switch 现按 tid 保存/恢复(_isr_scratch_tbl[16*6])。④ ISR 走中断门 IF=0,_if_saved=0,切回后不 sti,由 iretq 用用户 RFLAGS 恢复;_yield_lock 防嵌套。⑤ 单核前提(_sched_ptr/tick_count 非 per-CPU)。⑥ yield_now 语义、SCHED_QUANTUM=10、Gargantua 分块均未改。已知缺口:中断帧未保存 XMM/MXCSR,FP 密集 app 在异步抢占下有 XMM 被覆盖风险,待补 fxsave/fxrstor。
This commit is contained in:
1 parent
a3c1d221e6
commit
f2d8e771c2
3 files changed
+52
-3
No files matched your search
@@ -238,7 +238,11 @@ export def isr28_handler(): isrCommonhandler(28)
|
||||
export def isr29_handler(): isrCommonhandler(29)
|
||||
export def isr30_handler(): isrCommonhandler(30)
|
||||
export def isr31_handler(): isrCommonhandler(31)
|
||||
export def isr32_handler(): timer.timer_handler()
|
||||
export def isr32_handler(from_user: int):
|
||||
timer.timer_handler()
|
||||
# 定时 IRQ 已 EOI,处理完毕;仅在返回用户态时消费时间片,内核态不抢占。
|
||||
if from_user != 0:
|
||||
sched.Scheduler.try_reschedule()
|
||||
|
||||
export def isr33_handler():
|
||||
handler: irq_handler_t = irqGetHandler(1)
|
||||
|
||||
@@ -134,6 +134,8 @@ isr\num\()_frame_ready:
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
# is_user 作为第 1 个参数(rdi)传给处理函数,供其判断"返回用户态"时是否抢占
|
||||
mov rdi, rcx
|
||||
call isr\num\()_handler
|
||||
pop r15
|
||||
pop r14
|
||||
@@ -332,6 +334,8 @@ isr\num\()_frame_ready:
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
# is_user 作为第 1 个参数(rdi)传给处理函数,供其判断"返回用户态"时是否抢占
|
||||
mov rdi, rcx
|
||||
call isr\num\()_handler
|
||||
pop r15
|
||||
pop r14
|
||||
|
||||
@@ -16,6 +16,10 @@ define SCHED_QUANTUM = 10
|
||||
|
||||
_yield_cnt: uint32 = 0
|
||||
_yield_lock: int = 0
|
||||
# ISR scratch 是全局槽(isr.s);抢占后一个 ISR 会跨越其它线程的 ISR,故切换时按线程保存/恢复。
|
||||
export _isr_scratch_tbl: [MAX_THREADS * 6]uint64
|
||||
export _switch_old_tid: int = 0
|
||||
export _switch_new_tid: int = 0
|
||||
|
||||
|
||||
class Thread:
|
||||
@@ -92,7 +96,8 @@ class Scheduler:
|
||||
|
||||
@staticmethod
|
||||
def _yield():
|
||||
global _switch_old_rsp, _switch_new_rsp, _yield_cnt, _yield_lock
|
||||
global _switch_old_rsp, _switch_new_rsp, _yield_cnt, _yield_lock
|
||||
global _switch_old_tid, _switch_new_tid
|
||||
_if_saved: int = 0
|
||||
__asm__(f"""pushfq
|
||||
pop rax
|
||||
@@ -147,6 +152,8 @@ class Scheduler:
|
||||
if next_ks != 0:
|
||||
gdt.set_tss_rsp0(next_ks)
|
||||
cpu.set_kernel_rsp0(next_ks)
|
||||
_switch_old_tid = old_tid
|
||||
_switch_new_tid = next_tid
|
||||
_yield_lock = 0
|
||||
_do_switch()
|
||||
if _if_saved:
|
||||
@@ -304,10 +311,44 @@ def _do_switch():
|
||||
push r14
|
||||
push r15
|
||||
pushfq
|
||||
# 按线程保存 ISR scratch(被抢占的 ISR 会跨越其它线程的 ISR)
|
||||
mov eax, dword ptr [rip + _switch_old_tid]
|
||||
imul rax, rax, 48
|
||||
lea rdx, [rip + _isr_scratch_tbl]
|
||||
add rdx, rax
|
||||
mov rcx, qword ptr [rip + _isr_scratch]
|
||||
mov qword ptr [rdx], rcx
|
||||
mov rcx, qword ptr [rip + _isr_scratch + 8]
|
||||
mov qword ptr [rdx + 8], rcx
|
||||
mov rcx, qword ptr [rip + _isr_scratch + 16]
|
||||
mov qword ptr [rdx + 16], rcx
|
||||
mov rcx, qword ptr [rip + _isr_scratch + 24]
|
||||
mov qword ptr [rdx + 24], rcx
|
||||
mov rcx, qword ptr [rip + _isr_scratch + 32]
|
||||
mov qword ptr [rdx + 32], rcx
|
||||
mov rcx, qword ptr [rip + _isr_scratch + 40]
|
||||
mov qword ptr [rdx + 40], rcx
|
||||
mov rax, qword ptr [rip + _switch_old_rsp]
|
||||
mov qword ptr [rax], rsp
|
||||
mov rax, qword ptr [rip + _switch_new_rsp]
|
||||
mov rsp, qword ptr [rax]
|
||||
# 恢复切入线程的 scratch(不在 ISR 中时内容无意义,覆盖无害)
|
||||
mov eax, dword ptr [rip + _switch_new_tid]
|
||||
imul rax, rax, 48
|
||||
lea rdx, [rip + _isr_scratch_tbl]
|
||||
add rdx, rax
|
||||
mov rcx, qword ptr [rdx]
|
||||
mov qword ptr [rip + _isr_scratch], rcx
|
||||
mov rcx, qword ptr [rdx + 8]
|
||||
mov qword ptr [rip + _isr_scratch + 8], rcx
|
||||
mov rcx, qword ptr [rdx + 16]
|
||||
mov qword ptr [rip + _isr_scratch + 16], rcx
|
||||
mov rcx, qword ptr [rdx + 24]
|
||||
mov qword ptr [rip + _isr_scratch + 24], rcx
|
||||
mov rcx, qword ptr [rdx + 32]
|
||||
mov qword ptr [rip + _isr_scratch + 32], rcx
|
||||
mov rcx, qword ptr [rdx + 40]
|
||||
mov qword ptr [rip + _isr_scratch + 40], rcx
|
||||
popfq
|
||||
pop r15
|
||||
pop r14
|
||||
@@ -317,7 +358,7 @@ def _do_switch():
|
||||
pop rbx
|
||||
pop rax
|
||||
ret""",
|
||||
op=[ASM_DESCR.CLOBBER_MEMORY])
|
||||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
|
||||
|
||||
# Thread 布局:rsp0/stack8/stack_size16/func24/arg32/state40/tid44/pid48/kern_stack56
|
||||
# ⇒ sizeof(Thread) = 64,Scheduler.threads[16] 占 1024 字节 ⇒ current_tid 在 +1024。
|
||||
|
||||
Reference in new issue
Block a user