【问题标题】:How RCU reader section is protected from preemption?如何保护 RCU 阅读器部分免受抢占?
【发布时间】:2015-08-27 22:25:08
【问题描述】:

(来自LWN的一篇文章)

 1 rcu_read_lock();
 2 list_for_each_entry_rcu(p, head, list) {
 3   do_something_with(p->a, p->b, p->c);
 4 }
 5 rcu_read_unlock();

RCU 更新操作将执行 synchronize_rcu() 以断言每个 CPU 切换了上下文,因此每个 RCU 读取器都完成了它的工作。但是 RCU 必须依赖于 reader 不被抢占。确实,LWN 接下来说:

虽然这种简单的方法适用于抢占的内核 跨 RCU 读取端临界区禁用,换句话说,对于 非 CONFIG_PREEMPT 和 CONFIG_PREEMPT 内核,它不适用于 CONFIG_PREEMPT_RT 实时 (-rt) 内核。

我知道非 CONFIG_PREEMPT 内核禁用了抢占,但为什么 CONFIG_PREEMPT 内核也可以?

【问题讨论】:

    标签: c algorithm linux-kernel preemption rcu


    【解决方案1】:

    在 CONFIG_PREEMPT 内核上是可以的,因为在任务被抢占之前要注意完成 rcu 读取临界区。调度程序检查当前任务是否在 rcu 读取临界区中,如果是,则提高其优先级以完成临界区。更多详情请看这篇文章:http://lwn.net/Articles/220677/

    【讨论】:

      【解决方案2】:

      我们需要用于 CONFIG_PREEMPT 内核的 RCU。如果没有抢占或阻塞,那么我们就不会陷入这种同步混乱。有两种类型的 RCU 实现:

      1) Non-preemptible RCU implementation
      2) Preemptible RCU implementation
      

      当在一个 CPU 上调用 synchronize_rcu() 而其他 CPU 位于 RCU 读取端临界区中,则 synchronize_rcu() 保证阻塞,直到所有其他 CPU 退出其临界区。同样,如果调用 call_rcu() 在一个 CPU 上,而其他 CPU 在 RCU 读取端关键 部分,相应的 RCU 回调的调用被延迟 直到所有其他 CPU 退出其临界区。

      在非抢占式 RCU 实现中,在 RCU 读取端临界区中阻塞是非法的。 在 CONFIG_PREEMPT 中的抢占式 RCU 实现 (PREEMPT_RCU) 内核构建,RCU 读取端临界区可能被抢占, 但显式阻塞是非法的。最后,在抢占式 RCU 实时实现(使用 -rt 补丁集)内核构建,RCU 读端临界区可能被抢占,也可能阻塞,但 仅在获取受优先级继承约束的自旋锁时。

      【讨论】:

      • 那么为什么引用说“这种简单的方法适用于跨 RCU 读取端临界区禁用抢占的内核,换句话说,适用于非 CONFIG_PREEMPT 和 CONFIG_PREEMPT 内核”。当内核为 CONFIG_PREEMPT 时,这种方法会起作用吗?为什么这句话说 CONFIG_PREEMPT 内核禁用抢占?
      猜你喜欢
      • 2013-11-13
      • 1970-01-01
      • 2019-12-14
      • 2017-12-04
      • 2011-10-02
      • 1970-01-01
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多