延后工作队列

include/reliefnt/workqueue.h 提供 ReliefNT 自有内核内部接口,参考 Linux 工作项的投递、合并和取消机制,不是 Linux 内部 work_struct 的二进制或 源码兼容层,也不改变 Linux/POSIX 用户态 ABI。

执行与边界

队列使用单独的短自旋锁保护链表和状态;投递可来自 IRQ 或任务上下文, 不分配内存、不执行回调。即时工作和按单调 tick 延时的工作共享按截止时间 排列的队列,同一时刻的顺序保持 FIFO。重复投递合并;正在运行的工作可以 再投递一代,但同一工作不会并发执行。

定时器只在截止时间到达时请求调度,不在 IRQ 中执行工作。调度和空闲路径 从每 CPU 的服务栈派发独立的 kworker/N:0 内核线程,由线程保留的栈 消费工作。默认每批最多四个回调,在回调之间检查 2 ms 预算,处理前后检查 输入。worker 无工作时睡眠;延时截止或新投递唤醒它,没有就绪线程时不切换 派发栈。

批次预算不会强制中断持有执行事务的回调。回调释放执行事务并允许中断后, 其独立栈可以在安全的定时器返回处被抢占;仍不提供硬实时延迟上限。 线程执行与临界区约束见 内核线程与 worker。

执行者持有深度一的执行事务,队列锁不跨回调。回调只操作自己保留的内核 对象,不借用触发任务的用户缓冲区、描述符或重试状态。等待驱动的回调继续 使用原来的 manager admission、模块 pin 和执行事务 suspend/resume 协议; 调用者不得持有回调需要的锁。同一执行上下文等待自身回调返回会得到 EDEADLK。同 CPU 的其他任务可通过调度进展等待该回调退出, 不会仅因 CPU 相同而被误判为自等待。

取消、排空与模块

kernel_work_cancel_sync 关闭本次取消期间的投递,移除待执行代并等待当前 回调退出。永久释放上下文之前,调用者还必须停止外部生产者;取消返回后 新的独立投递仍可发生。kernel_work_flush 等待调用时观察到的那一代, 显式提前执行仍在延时队列中的工作,后来再次投递的代不在等待范围内。 两者只能在无回调依赖锁的任务上下文调用,必要时暂时释放深度一执行事务。

静态工作用 KERNEL_WORK_INIT 初始化,存储和上下文必须保持有效。 模块使用 kernel_work_create 分配由核心持有的工作,并登记模块清理义务。 每个获准投递的代持有执行 pin,取消或回调返回时才释放;模块进入 GOING 后 拒绝新投递。卸载先禁用/取消,再排空执行引用,最后才释放工作存储和模块 代码。显式销毁模块工作只禁用它,存储留到模块清理账本最终释放。

系统维护接入

普通系统调用入口不再同步调用下列维护函数:

  • USB 端口服务由 host 请求触发;manager 忙或仍有待办时延后一 tick 重试。

  • 失败的 detached mount finish 由保留该 mount/provider 的 FIFO 触发重试。

  • 图形回收在 provider 存在期间按 tick 处理 fence 和原有小批次;COMING 时保留轮询,实际回调仍只接纳 LIVE owner,detach 后停止。

  • 音频 IRQ tick 保持原有有界完成处理,将任务上下文工作投递到队列。

  • 网络保留每 tick 的协议维护心跳,继续使用原来的 pending 检查、包预算和 tick gate,保障 poll-only NIC、TCP 重传和 IPv6 邻居发现不依赖普通 syscall。

这些永久派发器不对可选 provider 持有队列期间的永久引用;实际进入 provider 时重新取得现有服务与代码 pin。用户返回前的输入、信号和重新调度检查保留。

验证

tools/test_workqueue.py 检查实际队列、执行锁、合并、延时、运行中重投递、 取消等待及模块 pin。用户返回夹具检查普通 syscall 不再运行维护,并验证 纯 CPU 和空闲入口的服务栈。外部测试模块 tools/tests/kmodules/workqueue_probe/ 在实际模块加载后从 IRQ 投递工作, 开放短暂的执行事务释放窗口,供来宾检查运行中卸载及代码引用排空。