(来自关于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必须依靠读者不被抢先一步。事实上,LWN接着说:
虽然这种简单的方法适用于抢占的内核 在RCU读取关键部分禁用,换句话说,对于 非CONFIG_PREEMPT和CONFIG_PREEMPT内核,它不起作用 CONFIG_PREEMPT_RT实时(-rt)内核。
我理解非CONFIG_PREEMPT内核禁用抢占,但为什么 CONFIG_PREEMPT 内核也可以使用?
答案 0 :(得分:5)
在CONFIG_PREEMPT内核上没问题,因为在任务被抢占之前需要注意完成rcu read critical部分。调度程序检查当前任务是否在rcu读取临界区中,如果是,则增强其优先级以使其完成临界区。有关详细信息,请参阅此文章:http://lwn.net/Articles/220677/
答案 1 :(得分:1)
我们需要RCU用于CONFIG_PREEMPT内核。如果没有先发制人或阻止,那么我们就不会陷入同步混乱。有两种类型的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实现 读取端关键部分可能被抢占,它们也可能被阻止,但是 只有在获得优先继承的自旋锁时。