几个月前,Linus Torvalds 在 Linux 5.9 版本中重写了 wait_on_page_bit_common() 相关逻辑,原因是为了解决页面锁竞争的公平性问题。
在这之前,页面锁持有者在执行 ”unlock_page()" 时仅会唤醒等待队列里的一个独占进程(FIFO,且该进程正在执行 “lock_page” ),但是该进程不一定正在运行,特别是在负载情况下,只有其获得 CPU 时间才能真正运行,与此同时,其它正在运行的没有进入等待队列的进程可以直接获得页面锁,这个过程虽然依然有效利用了页面,但会导致非常不公平的情况,被唤醒的等待进程运行后发现页面锁没有释放,于是重新进入等待队列,而且是最后一个,极端情况下,这个进程可能会重复该过程以至于等待数十秒。
因此 Linus Torvalds 修改为在唤醒等待进程时同时会把锁交给它,无论它是否正在运行。
然而,这并没有完全解决问题。自这之后,偶尔会发生 BUG_ON() ,因为上述 “wait-to-set” 的过程并非原子性的,所以被唤醒的进程仍有可能被“第三者插足”。如果要把 “wait-to-set” 这一过程修改为原子性操作,需要修改大约 50 个函数,因此,在上周,Linus Torvalds 把 wait_on_page_writeback () 函数中的 if 修改为 while 来解决这一问题。而这基本上又回到了最开始的情况,不过发生频率要低得多,因此仍然可控。
不过,据外国媒体报道,其在该版上的基准测试中, PostgreSQL 性能下降了 5%-10%,对此,Linus Torvalds 认为这种下降并非由该补丁引起,可能和其测试模型或机器性能有关。
Linux 5.11-rc3 现已发布,感兴趣的同学可以进行相关测试
更多详细内容查看以下 commit:
- mm: make wait_on_page_writeback() wait for multiple pending writebacks
- mm: rewrite wait_on_page_bit_common() logic
本文转自OSCHINA
本文标题:Linus Torvalds 再改页面锁逻辑,把 if 替换为 while
本文地址:https://www.oschina.net/news/126262/linus-torvalds-change-if-2-while