pi-futex-1——内核文档翻译-pi-futex.rst
一、pi-futex.rst
翻译:kernel-5.10\Documentation\locking\pi-futex.rst
======================
轻量级 PI-futex
======================
我们称它们为轻量级的原因有 3 个:
- 在用户空间快速路径中,启用 PI 的 futex 根本不涉及内核工作(或任何其他 PI 复杂操作)。 没有注册,没有额外的内核调用 - 只是用户空间中的纯快速原子操作。
- 即使在慢速路径中,系统调用和调度模式也与普通的 futex 非常相似。
- 内核 PI 实现围绕互斥锁抽象进行了简化,严格的规则使实现相对简单:只有一个所有者可以拥有锁(即不支持读写锁),只有所有者可以解锁锁, 没有递归锁定等。
优先继承——为什么?
--------------------------
简短回复:用户空间 PI 有助于实现/改进用户空间应用程序的确定性。 在最好的情况下,它可以帮助实现确定性和良好的延迟。 即使在最坏的情况下,PI 也会改善与锁定相关的应用程序延迟的统计分布。
较长的回复
------------------
首先,在多个任务之间共享锁是一种常见的编程技术,通常无法用无锁算法代替。 正如我们在内核中看到的那样[这本身就是一个相当复杂的程序],无锁结构与其说是常态,倒不如说是一种例外 —— 目前共享数据结构的无锁代码与有锁代码的比率介于 1:10 和 1:100 之间 。 无锁很难,无锁算法的复杂性通常会危及对所述代码进行稳健审查的能力。 IE。 关键 RT 应用程序通常选择锁结构来保护关键数据结构,而不是无锁算法。 此外,在某些情况下(如共享硬件或其他资源限制),无锁访问在数学上是不可能的。
媒体播放器(如 Jack)是合理的应用程序设计的一个例子,多个任务(具有多个优先级)共享短期锁:例如,高优先级音频播放线程与中等优先级构造音频数据线程和低优先级显示颜色线程相结合。 将视频和解码添加到组合中,我们获得了更多的优先级。
因此,一旦我们接受同步对象(锁)是生活中不可避免的事实,并且一旦我们接受多任务用户空间应用程序对能够使用锁有非常公平的期望,我们就必须考虑如何提供用户空间的确定性锁定实现选项。
大多数反对优先级继承的技术的反驳仅适用于内核空间锁。 但是用户空间锁不同,我们不能在关键部分禁用中断或使任务不可抢占,因此'使用自旋锁'参数不适用(用户空间自旋锁与其他用户空间自旋锁具有相同的优先级反转问题- 空间锁定结构)。 事实上,目前几乎唯一能够为用户空间锁(例如基于 futex 的 pthread 互斥锁)提供良好确定性的技术是优先级继承:
目前(没有 PI),如果一个高优先级任务和一个低优先级任务共享一个锁 [这对于大多数重要的 RT 应用程序来说是一个很常见的场景],即使所有关键部分都被仔细编码为确定性的(即所有临界区的持续时间很短并且只执行有限数量的指令),内核不能保证高优先级任务的任何确定性执行:任何中优先级任务都可以在低优先级任务持有共享锁并执行关键部分时抢占低优先级任务,并可能无限期地延迟它。
执行
--------------
如前所述,启用 PI 的 pthread 互斥体的用户空间快速路径根本不涉及内核工作——它们的行为与普通的基于 futex 的锁非常相似:0 值表示解锁,value==TID 表示锁定。 (这与基于列表的 robust futex 使用的方法相同。)用户空间使用原子操作来锁定/解锁这些互斥锁,而无需进入内核。
为了处理慢速路径,我们添加了两个新的 futex 操作:
- FUTEX_LOCK_PI
- FUTEX_UNLOCK_PI
如果锁定获取快速路径失败,[即 从 0 到 TID 的原子转换失败],然后调用 FUTEX_LOCK_PI, 内核完成所有剩余的工作:如果还没有 futex 队列附加到 futex 地址,那么代码查找拥有 futex 的任务[它已将自己的 TID 放入 futex 值],并附加一个 'PI state' 结构到 futex 队列。 pi_state 包括一个 rt-mutex,它是一个 PI 感知的、基于内核的同步对象。 “其他”任务成为 rt-mutex 的所有者,FUTEX_WAITERS 位自动设置在 futex 值中。 然后这个任务会尝试锁定它阻塞的 rt-mutex。 一旦它返回,它就获得了互斥锁,并将 futex 值设置为它自己的 TID 并返回。 用户空间没有其他工作可执行 - 它现在拥有锁,并且 futex 值包含 FUTEX_WAITERS|TID。
如果解锁侧的快速路径成功,[即 用户空间设法完成 futex 值的 TID -> 0 原子转换],就不会触发任何内核工作。
如果解锁快速路径失败(因为设置了 FUTEX_WAITERS 位),则调用 FUTEX_UNLOCK_PI,内核代表用户空间解锁 futex - 它还解锁附加的 pi_state->rt_mutex,从而唤醒任何潜在的等待者。
请注意,在这种方法下,与以前的 PI-futex 方法相反,没有 PI-futex 的事先“注册”。 [由于 pthread 互斥锁的现有 ABI 属性,无论如何,这不太可能。]
此外,在该方案下,'robustness' 和 'PI' 是 futex 的两个正交属性,并且所有四种组合都是可能的:futex、robust-futex、PI-futex、robust+PI-futex。
有关优先级继承的更多详细信息,请参见 Documentation/locking/rt-mutex.rst。
二、rt-mutex.rst
见: https://www.cnblogs.com/hellokitty2/p/17004118.html
posted on 2025-05-15 10:50 Hello-World3 阅读(31) 评论(0) 收藏 举报