内核线程与 worker¶
include/reliefnt/kthread.h 提供 ReliefNT 的内核内部线程接口。线程具有
独立 64 KiB 栈和保留的 SysV x86-64 调用现场,可在让出、睡眠和安全的
定时器返回后继续原来的函数,而不是重新调用一次入口。此接口参考 Linux
的线程式工作队列机制,但不承诺 Linux 内部 kthread API/二进制兼容;
不新增或修改用户态 Linux/POSIX ABI。
创建和调度¶
kthread_create 创建停止的线程;kthread_wake 发布就绪状态。
线程固定到创建时指定的已发现 CPU,不迁移保留的栈或驱动执行事务令牌。
CPU 启动失败时其线程不运行,仍可停止并回收;目前不提供 CPU 热插拔。
外部 sched_setaffinity 对这些固定 CPU 内核任务返回 EINVAL,
sched_getaffinity 继续报告其真实绑定,不接受只改掩码却不迁移的操作。
线程由独立的每 CPU 就绪 FIFO 派发。用户任务继续使用现有 EEVDF 队列, 调度边界每次最多派发一个内核线程执行轮次。 一个轮次结束后,用户返回路径至少留出至下一 tick 的用户运行窗口,避免 连续缺页/系统调用返回反复运行后台线程而饿住用户程序。该窗口使用现有 调度器时钟限制为最多一个 tick(当前 10 ms),不因 BSP/PIT 中断延后而 无限延长其他 CPU 的后台等待。空闲及显式 join 排空路径直接推进就绪线程,不受此用户运行窗口限制。worker 必须在 init 已取得 PID 1 后创建,保留 Linux 启动进程和孤儿回收的 PID 1 语义。
派发时保存原调用任务的 CPU 预留,切换到内核页表并发布真实的内核线程 任务身份;返回时恢复预留和页表。这样,睡眠中的用户返回栈不会被其他 CPU 并发使用或回收,驱动也不会误用被中断用户的 PID、文件描述符或地址空间。 CPU 时间计入当前内核线程的 system ticks,用户的公平调度间隔在其间暂停。 内核仍使用 general-regs-only 编译;线程不可使用用户的浮点/TLS 状态。
抢占与临界区¶
PIT、AP 定时器及调度 IPI 完成中断确认后,可切走正在独立栈上执行的内核 线程。只接受原中断允许 IRQ、没有执行 writer、没有 plain 自旋锁的 CPL0 线程栈;普通 syscall、空闲、异常、NMI、IST 及外借服务栈不走此返回切换。 IRQ-save 自旋锁和 reader 事务保留原来的关中断规则。
普通自旋锁在等待和持锁期间禁止线程调度。工作函数调用
kthread_yield、kthread_sleep_until 前也必须释放执行事务及所有锁,
并保持任务中断开启。旧驱动可保留原来的执行事务 suspend/resume 等待协议;
暂停状态在其固定 CPU 上恢复。这里不启用所有内核代码的任意位置抢占,
长时间持锁的代码仍需单独缩短临界区。
睡眠、停止和所有权¶
kthread_sleep_until 使用绝对单调 tick;UINT64_MAX 表示只等待事件。
唤醒合并且保留 sleep 之前发布的事件,调用方始终循环检查实际条件。
kthread_join 等待最后一次函数返回;kthread_stop 发布停止请求、
唤醒线程并 join。函数应检查 kthread_should_stop,停止不会强行丢弃仍有
锁、DMA 或模块调用的栈。尚未运行的线程可直接停止,返回 -EINTR。
同一线程等待自身得到 -EDEADLK。
同步 join/取消允许临时释放深度一的执行事务。在本 CPU 等待的普通任务可 推进内核线程调度;内核线程等待者则睡眠,让其他线程和用户任务继续运行。 这只用于显式等待,不把维护重新放回普通 syscall 入口。
模块在 COMING 阶段可创建线程,但首次 wake 只接受 LIVE owner。从首次
获准唤醒到函数最终返回、独立栈离开 CPU,核心持续持有模块执行 pin。
模块清理账本先关闭准入、请求停止并 join,最后才释放线程栈和模块代码。
kthread_destroy 对模块线程只禁用并停止它,存储保留到最终账本释放。
永久代码的调用者先停止全部外部唤醒源,再销毁自己持有的句柄。
存储和工作队列¶
后台上下文使用同步存储标志,不继承用户 syscall 的可重试状态;退出调度
轮次后恢复原调用者的确切标志。已有异步 DMA 命令的 PID 所有权仍保留,
后台 I/O 遇到另一任务的 pending owner 返回 EAGAIN,不会复用它的命令。
这不扩大存储并行范围,也不取代已有设备和执行锁。
kworker/N:0 消费已有工作项的四回调/2 ms 批次。批次结束后让出或睡眠,
单次队列通知只唤醒一个在线 worker,轮换 CPU;空闲 worker 只等待事件,
延迟工作的到期通知统一由队列 timer 发布,避免所有 CPU 为同一项工作
同时争用执行锁。
回调本身继续遵守其原有锁和模块所有权规则。队列按线程身份判断自等待,
同 CPU 的其他任务可以等待一个暂停的回调;实际回调等待自身仍被拒绝。
USB 注销在 host 回调仍 active 时返回 EBUSY,不设置不可重试的 closing
状态,也不持执行事务等待暂停的 worker。模块保留 GOING 资源,回调完成后
可重试清理。PCM 最终关闭遇到正在断开或使用中的 stream 返回 EAGAIN,
由既有释放队列保留 lease/code/DMA 后重试,避免同 CPU 关闭路径阻挡 worker。
验证入口¶
tools/test_kthread.py 使用实际汇编切换、实际线程引擎和执行锁,验证
栈保留、让出、延时、提前唤醒、停止、模块 pin 和同 CPU 回调取消;另用
实际存储上下文实现验证重试标志及竞争 pending owner 的隔离。
tools/tests/kmodules/kthread_probe/ 是独立外部测试模块,以不主动让出的
CPU 0 线程验证定时器抢占、同 CPU 用户进展、睡眠唤醒和实际卸载排空。
测试模块不属于 defconfig 或正式镜像。