非抢占式RCU中关于grace period的处理(限于方法)

时间:2023-03-08 19:14:09

参考自:http://blog.****.net/junguo/article/details/8244530
             Documentation/RCU/*

TREE_RCU将所有的CPU组织成一颗树,通过层次结构来判别进程是否通过了宽限期,这种方式适用于多个CPU的系统               
TINY_RCU适用于单个CPU,尤其是嵌入式操作系统。

RCU实现的关键集中在宽限期的处理上,这个过程需要保证销毁对象前,当前系统中所有CPU上运行的进程都通过了静止状态(quiescent state)。

1, 程序调用call_rcu_sched,将要删除的对象保存起来。并标记或者开始一个宽限期(同一时间只能运行一个宽限期,所以当已经有宽限期在运行的时候,其它的宽限期必须等待)。

2, 在读取数据开始和结尾处增加 rcu_read_lock 和 rcu_read_unlock来标记读过程。为了保证删除过程知道读过程的结束,
在非抢占式RCU实现中是在rcu_read_lock开始处禁止进程抢占。这样做就可以保证再运行下一次进程切换的时候,读过程已经结束。其实系统也不会去统计各个CPU上是否存在过读线程,所以所有的CPU都会在进程切换的时候通知系统它处于进制状态。当所有的CPU都通过静止状态的时候,系统就会标记它通过了一个宽限期。

3,由于一个宽限期结束的时候,只有最后一个通过静止状态的CPU知道当前的宽限期已经结束,它并不会去通知其它CPU;同时
出于性能考虑,系统也不会在宽限期结束后,马上去执行销毁过程。所以每个CPU都有一个固定的函数去检测是否有等待执行的宽限
期,如果没有特别紧急的任务时,会去执行这些过程。

以下记录是探讨RCU如何实现的基本入口点,详细的实现会在后文做记录。

系统静态定义了

struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched_state);
DEFINE_PER_CPU(struct rcu_data, rcu_sched_data); struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);
DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);

系统初始化时会初始化RCU:

start_kernel()
|----->rcu_init()

系统会在时钟中断中,周期性地检查是否有RCU回调链表需要处理:

timer_tick()
|---->update_process_times(user_mode(get_irq_regs()));
|---->rcu_check_callbacks(cpu, user_tick);

进行进程切换时,也会进行相关的RCU处理

schedule()
|---->rcu_sched_qs(cpu)

写者:

#ifdef CONFIG_TREE_PREEMPT_RCU

//............

#else

#define synchronize_rcu synchronize_sched

#endif