同步原语 (Synchronization)
Proka 内核提供了一套高性能的同步原语,专为微内核架构下的高频 IPC 和多核竞争场景优化。
设计目标
- 去内存分配化:同步对象在运行过程中不触发任何堆内存分配(如
Vec)。 - 高性能 IPC:支持自适应自旋,降低短时间锁竞争的上下文切换开销。
- 多核公平性:底层自旋锁采用 Ticket Lock 算法,确保 CPU 核心间的公平竞争。
核心组件
1. Mutex (优先级继承互斥锁)
用于保护独占资源。
- 快速路径 (Fast-path):在无竞争情况下,通过一次原子操作即可完成加锁。
- 自适应自旋 (Adaptive Spinning):在进入阻塞状态前,线程会先尝试短时间自旋。如果锁被很快释放,则避免了昂贵的调度开销。
- 优先级继承 (Priority Inheritance):自动提升持有锁的低优先级线程,防止优先级反转。
- 无分配等待队列:利用调度器的
block_sync机制,将线程阻塞在对象地址上,彻底移除Vec<Tid>。
2. RwLock (读写锁)
支持多个读者或单个写者。
- 写者优先 (Writer-Preferring):引入
WRITE_PENDING标志位。当有写者等待时,新的读者将被强制阻塞,防止写者饥饿。 - 公平性:写者在释放锁后,会通过
unblock_sync唤醒所有等待者。
3. SpinLock (公平自旋锁)
用于内核底层、中断上下文等无法阻塞的场景。
- Ticket Lock 实现:
- 每个加锁请求都会领取一个序号。
- 只有当前序号与服务序号匹配时才能获取锁。
- 优点:严格保证了 FIFO 顺序,彻底解决了传统自旋锁导致的 CPU 核心饥饿问题。
4. Semaphore & Condvar
- Semaphore:计数信号量,用于限流或资源计数。
- Condvar:条件变量,允许线程在特定条件满足前挂起。
- 实现原理:均已重构为基于调度器同步 ID 的机制。
调度器集成
同步原语通过以下接口与调度器深度绑定:
#![allow(unused)]
fn main() {
// 阻塞在特定同步 ID 上(通常是对象的内存地址)
scheduler::block_sync(sync_id: u64);
// 唤醒所有阻塞在特定同步 ID 上的线程
scheduler::unblock_sync(sync_id: u64);
}
这种设计使得同步原语本身变得非常“薄”,核心逻辑(如等待者调度)完全由调度器中心化管理。