抢占式 RCU 通过维护一个 per-CPU 计算器来检测宽限期。rcu_read_lock() 会导致计数器增加,而 rcu_read_unlock() 会导致计数器减小。对于单核计算机而言,一旦计数器归零,就代表宽限期结束。但是由于临界区可能发生抢占,rcu_read_unlock() 可能会在另一个 CPU 上执行,从而可能有的 CPU 计数器多加了好几次,有的 CPU 计数器多减了好几次。但是无论如何,一旦所有 per-CPU 变量之和为零,就代表宽限期已经结束。

考虑到在一个时间段中可能会不断有任务进入读端临界区,从而导致 per-CPU 之和几乎不可能为零,因此使用单个计数器是不够的。

通过引入两个计数器,其中 current 代表当前宽限期,last 代表上次宽限期。在进入新的临界区的时候只会增加 current,从而确保 last 一定有可能递减到零。这时一个宽限期就结束了。

在简单抢占式 RCU 中,每个临界区进入和退出之前都会执行内存屏障,其结构如图:

Wasted Memory Barriers

wasted memory barriers

其中 MB 意味着宽限期。粗体部分代表了实际需要的 MB。在上图中有很多不是必要的内存屏障,我们可用对其进行优化,只在必须的时候才执行内存屏障。

Grace Period Memory Barriers

grace period memory barriers

这样内存屏障只用于检测宽限期。

要实现这一点,就需要添加一个 pre-CPU flag 来指示宽限期检测正在进行,当所有 CPU 执行完内存屏障后,就意味着一个宽限期已经结束了。

宽限期状态机

Diagram
Last moify: 2025-03-23 15:05:20
Build time:2025-07-18 09:41:42
Powered By asphinx