-
Wanlin Liu authored
抢占式的关键是「保证中断只从 U 态打进来」,而不是加个时钟中断: 这个内核的 __alltraps 是单 sscratch 交换,只对'从 U 态 trap 进来'成立; 内核态被定时器打断时 sscratch 里是用户 sp,交换后会把寄存器保存到用户栈上。 做法: - 内核态全程 sstatus.SIE=0(从 trap 进入到 sret 都不开) - 只开 sie.STIE,U 态 sret 后 SIE 由 SPIE 置 1 才会真正响应 - preempt_start() 只在 sys_agent_spawn 里调用 —— 只有跑 Agent 演示时才开; 崩溃路径与 init 退出时 preempt_stop() 关掉并 set_timer(MAX) - trap_handler 先判 scause 最高位,code==5 走 preempt_tick -> switch_to_next(tf,false) (skip_ecall=false,中断不是 ecall,sepc 指向被打断的指令,不能 +4) 一个隐蔽的坑:sleep_until() 结尾的 set_timer(u64::MAX) 会把时间片也冲掉, 抢占会静默失效。改成「保存 sie -> 开 STIE -> wfi -> 恢复 sie」+ 返回后 preempt_rearm()。 证明:演示里加了一个从不 yield、只烧 CPU 的 hog Agent —— [hog] 第 1 轮 / 第 2 轮 -> [main] 第 2 轮 -> [hog] 第 3 轮 -> [main] 第 3 轮 hog 全程没让出,主 Agent 仍能穿插执行,即时间片抢占生效。 回归: - 官方判分盘(无演示):85/102 Accept,END 31,trap 6 —— 与改动前完全一致 - 演示盘:用户态 29 项断言全 PASS,basic 组同样 85/102 - make all 双架构通过 另新增 docs/demo-script.md:15~20 分钟演示视频的分镜、命令与讲解要点 (构建 / basic 跑分 / 内核自测 / 用户态演示 / 设计取舍 / 局限)。
e0e14ffe