关注了就能看到更多这么棒的文章哦~
The search for the correct amount of split-lock misery
By Jonathan Corbet
October 19, 2022
DeepL assisted translation
https://lwn.net/Articles/911219/
X86 与许多其他架构不同,它能支持那些会影响超过一个 cache line 的原子操作(atomic operation)。但是,这种支持也带来了代价,不尽包括整个系统的性能方面的代价,甚至在安全性方面也有代价。在过去的几年里,内核开发人员一直在努力阻止使用这种 "split-lock" 操作。但是,现在,有一群用户感到有点太受伤了,于是就引出了一个讨论,使用有问题、但在架构上是合法的操作的用户,应该得到多大程度的不便。
跨越 cache line 边界的原子操作存在的问题是,系统总线必须要采取特殊措施来确保两个 cache line 都在受到保护,不会被多方并发同时访问到(concurrent access)。在实践中,这就意味着在操作过程中要锁住总线(locking the bus),这可能会使得系统中的其他处理器都无法继续执行。只有有一个恶意的程序来执行一个紧凑的会导致 split-lock 操作循环,就可以破坏整个系统的性能。由于这个原因,split-lock 操作长期以来一直不被人看好。
不幸的是,恶意软件(或只是写得不太好的软件)对于这些反对意见完全无动于衷。因此,从 2019 年开始,内核开发人员就在寻求更有说服力的方式来表达他们的观点。最初的工作是由 Fenghua Yu 完成的,但最后,Peter Zijlstra 的 patch 在 2020 年 1 月被合并到 5.7 内核版本中。它使内核有能力对 split-lock 操作引起的 trap 采取一些行动,并提供了三种选项,可由 split_lock_detect= 这个 kernel 命令行参数来选择:
off,内核的行为会跟以前一样;不检测 split-lock 操作,出现的时候不做任何事情。
warn(默认值),在检测到 split-lock 操作时在系统日志中发出 warning(warning 频率会有限制)。
fatal,让内核立即 kill(用 SIGBUS)这些试图进行 split-lock 的进程。
我们希望 warning 模式足以提醒用户注意这个问题,并让软件能得到正确的 fix,同时不影响任何人使用自己的系统。但是,到了今年早些时候的 5.19 开发周期,似乎对于去除 split-lock 操作并没有太大进展,,拒绝服务(denial-of-service)的问题还是跟以前一样现实存在。因此,人们决定采取更强硬的立场来克制 split-lock。
当然,选项之一是默认切换到 fatal 模式,但这会是一个非常严厉的解决方案。Tony Luck 采取了不同的方案,他写了一个 patch,标题是 "让分裂锁的人活得很痛苦(make life miserable for split lockers)"。这个 patch 中修改了 warning 模式,会对导致了 split-lock 的进程进行惩罚,但不会真正去 kill 它们。相反,在检测到 split-lock 时就会让它受到 10ms 级别的 delay,并且通过 semaphore 保证序列执行。当选择这种模式时,使用了 split-lock 的恶意程序仍然会拖慢自己执行的速度,但对整个系统不再有太大影响了。这一改动是在 5.19 合并窗口期间合入的。
9 月中旬,一个名为 "pibberflibbits" 的 GitHub 用户发布了一份 bug report,称 Linux 上的 God of War (战神)游戏的性能变得 "低得离谱"。参与讨论的人们花了一点时间,最终发现问题出在 split-lock 的这个额外惩罚上。显然,战神并不满足于仅使用普通的 lock,所以游戏中使用了许多 split locking。Luck 的 patch 确实达到了预期的目的,战神玩家现在是过得很痛苦。
不过,Guilherme G. Piccoli 并没有庆祝这场对战神的胜利;相反,他发布了一个 patch,认为 "不应该修改 default 配置选项,让旧的应用或者专有软件表现下降,尤其是原有的 config 选项能正常工作的情况下"。这个 patch 对 warn 模式恢复到了的旧的行为,并增加了一个新的 seq 模式,该模式会像现在的 warn 模式一样拖慢 split-lock 用户的速度。warn 模式仍然是默认的,这就解除了游戏界的苦难。
对这一改动的意见不太一致。Luck 指出,游戏玩家可以通过在内核命令行上用 split_lock_detect=off 重启,就能直接禁用 split-lock 检测。他说,如果要增加 seq 模式,那么也应该是默认的。他还建议向《战神》的发行商提交一个 bug,从而让其 fix 它自己的问题。
不过,其他人不同意。Joshua Ashton 认为这个问题是个普遍问题。"这不仅仅是《战神》的具体一个游戏的问题。有许多老的作品永远不会再更新了,也就无法 fix 这个问题。这些游戏以前能很好地运行,性能也很好"。其他人指出,许多游戏玩家不太可能做到去调整内核的命令行参数。Dave Hansen 观察到,造成痛苦的这个计划已经按计划运作,并将问题暴露出来了。但是他继续说道:
我的直觉告诉我,我们应该保留 warning,不再让人们痛苦了。那些能够 fix 这些 bug 的人可能也是会看 dmesg 的人,他们不需要经受这样的痛苦来得到额外的提示。那些运行 Windows 游戏的人不看 dmesg,只想在没有痛苦的情况下玩他们的游戏。
不过,Luck 认为,split-lock 会给其他进程(除了这个有责任的进程之外)制造了痛苦,而目前的模式 "在多用户系统上非常有效"。他建议,也许可以开发某种启发式方法,让这些折腾用户的行为就限制在多用户系统中。
不过,最终 Thomas Gleixner 给出了明确的答案,他指出,默认情况下拖慢 split-lock 的速度,这是发行版中可以做出的唯一选择;其他任何方案都会产生一个容易被利用的拒绝服务漏洞。所以拖慢速度的做法需要保留。"减少受攻击的暴露面,会比某个应用程序出现问题要更重要"。不过,他确实建议说,可以添加一个 sysctl 开关来控制 split-lock 的检测;这就可以让那些使用这种出现了的应用程序的用户能回到以前的性能,而不需要弄清楚如何改变 kernel 命令行参数,也不需要重启他们的系统。
这就是 Piccoli 为解决这个问题所提交的第二个版本中采取的方法。新增了 kernel.split_lock_mitigate 开关,如果设置为 0 的话将禁用对使用 split-lock 的进程所进行的惩罚(同时保留发送到 system log 的 warning)。默认情况是保留这个减速的行为。这个 patch 似乎让每个人都很满意,而且看起来很可能会进入 6.2 版内核。受影响的玩家将不得不去相应设置新的开关,也就是说要想成为真正的战神,得先知道要调整系统中的哪些 sysctl。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~