这篇文章主要了classic rcu 在2.6.31的实现,以及classic rcu 在kmemleak 的应用。
1. Classic RCU 实现
RCU(Read-copy Update) 是 在 2002年10月引入Linux 2.5 内核,到现在最新的5.6 Linux 内核,已经由Classic RCU, 发展出了 Tiny RCU, Hierarchy RCU, Preemptable RCU, Sleepable RCU, 这里 主要介绍 Classic RCU, 在内核2.6.31 里面的实现,也就是最后一个实现了Classic RCU 的内核版本。RCU 最基本的API 包括:
- rcu_read_lock
- rcu_read_unlock
- synchronize_rcu/call_rcu
- rcu_assign_pointer
- rcu_deference
其最核心的原理也比较直观,就是如何安全的实现对内存资源的回收
现在直接分析对应的内核代码对于 2.6.31 内核版本的代码主要是
/include/linux/rcuclassic.h
/include/linux/rcuupdate.h
/kernel/rcuclassic.c
/kernel/rcuupdate.c
首先看 最核心api 的实现
rcu_read_lock/rcu_read_unlock
可以看到kernel 里面对于 尤其是对于none-preemptable的内核而言,读端的负载基本是0(zero overhead),对于 preemptable 的场景,只需要禁掉抢占并且 保证 基本 acquire/release 的语义, 这里实现 acquire/release 利用了编译器 提供的 __context__的函数, 本质上 preempt_disable/preempt_enable 已经提供了memory barrier.
rcu_deference
只是加了一些linux 内存模型的原语,保证了读写的顺序,smp_read_barrier_depends 这个语句只在alpha CPU 模型上有意义,其他cpu 都提供了cache coherence 的保证
rcu_assign_pointer
smp_wmb 这里的作用主要利用了 B-Cumulative