mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 06:47:29 +00:00
## 中断子系统拆分(用户按 OS 中断语义三次裁定的最终边界) 中断类比 OS:只提供中断优先级、中断队列、现场保护、中断屏蔽。 调度器建立在其之上——它问"中断侧该出谁",然后执行那个任务。 新增 internal/agent/core/interrupt.go(303 行),承载: - 中断队列(interruptQueues[5] + immediate 单槽) - 中断栈(suspendStack)—— **唯一操作者** - 中断屏蔽(critical,对应关中断) - 让位信号原语(preemptArmed/preemptLevel) 留在 scheduler.go 的是**策略**: - 任务优先级语义(Level / effectiveLevel / canPreempt / clampPluginLevel) - 恢复决策(nextInterruptSelection:栈顶 vs 中断队列比较) - 就绪队列 / 停止配额 / 背压 ### 关键设计:中断栈只有中断管理器能操作 调度器通过 stackTopLocked() **只读查询**栈顶做比较, 真正的弹栈由 restoreTopLocked() 在中断管理器内完成。 这条不变量在类型层面无法绕过。 ### 解耦机制:stackNotify 钩子 中断栈变化时通告调度器,调度器据此唤醒调度循环重新求值。 中断管理器不知道调度器会怎么选,调度器也不碰栈内部 ⇒ 将来给中断子系统加向量表或换多栈策略,不必改调度器。 ### 测试 新增 interrupt_invariant_test.go:I1–I7 共 11 条**不变量**判据 (区别于既有的行为测试)。两条经变异验证确认会变红: - canPreempt 改成恒 true → L4 不抢 L4 判据红 - maxInterruptFrames 改成 99 → 上界判据红 - 去掉 notifyStackLocked → 钩子判据红(且判据本身带超时,缺判据是"红"不是"挂") ## 修两处真实数据竞争(阻塞 CI,非本次引入) -race 实测:internal/agent/core 原有 30 个测试失败,整包被判红。 根因(ab27d1a 上已存在,与拆分无关): - core/stages.go:withExecuteCtx 往调用方共享的 tc.Arguments 原地写 ctx - io/channel.go:bindExecCtx 同样原地写设备 args 原注释称"args 每次调用独立、天然一 goroutine 一份",但代码改的是调用方那份。 工具在自己的 goroutine 里跑,超时/取消路径下主 goroutine 仍在读同一份 args。 修法:复制 map 而非原地写。变异验证:退回原地写后 TestPreempt_DeferredDuringToolExec 立刻报 DATA RACE。 ## 验证 - go build ./... 通过 - go test -p 1 ./... 全仓无失败 - -race 三关键包(core/io/proc)全绿,core 从 30 红归零 - CI 门禁自检 / 启动图判据 / 版本一致性 本地通过 ## 遗留(不在本次) - 中断向量表(计划 §7 已设计,按 §7.6 应在拆分后单独做) - maxQueue 仍约束中断队列:OS 语义上说不通,但改它是行为变更,单独立项