具有 PI 支持的 RT-mutex 子系统

具有优先级继承(PI)的 RT-mutex 用于支持 PI-futex,它启用了 pthread_mutex_t 的优先级继承属性(PTHREAD_PRIO_INHERIT)。[有关 PI-futex 的更多详细信息,请参阅轻量级 PI-futex。]

这项技术是在 -rt 树中开发的,并为 pthread_mutex 支持进行了精简。

基本原理:

RT-mutex 通过优先级继承协议扩展了简单互斥锁的语义。

RT-mutex 的低优先级所有者会继承高优先级等待者的优先级,直到 RT-mutex 被释放。如果这个被临时提升优先级的持有者自身阻塞在另一个 RT-mutex 上,它会将优先级提升传播给该 RT-mutex 的持有者。一旦 RT-mutex 解锁,优先级提升就会立即被移除。

这种方法使我们能够缩短高优先级任务在保护共享资源的互斥锁上的阻塞时间。优先级继承并不是解决设计糟糕的应用程序的灵丹妙药,但它允许设计良好的应用程序在无需损失确定性的情况下,在优先级线程的关键部分使用用户空间锁。

等待者进入 RT-mutex 等待者树的过程是按优先级顺序进行的。对于相同优先级,选择 FIFO(先进先出)顺序。对于每个 RT-mutex,只有最高优先级的等待者会被加入到所有者的优先级等待者树中。这棵树也按优先级顺序排队。每当任务的最高优先级等待者发生变化时(例如超时或收到信号),所有者任务的优先级就会被重新调整。优先级入队由 “pi_waiters” 处理。

RT-mutex 针对快速路径(fastpath)操作进行了优化,在锁定无竞争的互斥锁或解锁没有等待者的互斥锁时,没有内部锁开销。优化的快速路径操作需要 cmpxchg 支持。[如果没有该支持,则使用 RT-mutex 内部的自旋锁]

RT-mutex 的状态是通过 RT-mutex 结构中的 owner 字段来跟踪的

lock->owner 保存了所有者的 task_struct 指针。位 0 用于跟踪“锁有等待者”的状态

owner

bit0

注意

NULL

0

锁空闲(可以进行快速获取)

NULL

1

锁空闲且有等待者,且最高优先级的等待者即将获取该锁 [1]

任务指针

0

锁被持有(可以进行快速释放)

任务指针

1

锁被持有且有等待者 [2]

只有当 lock->owner 的第 0 位为 0 时,基于原子比较交换(compare exchange)的快速获取和释放才有可能。

顺便说一句,技术上仍然存在“待定所有者”(Pending Owner),只是不再这样称呼它了。待定所有者恰好是锁的 top_waiter(最高优先级等待者),该锁没有所有者且已被唤醒以获取该锁。