深入理解RCU实现
static void __cpuinit rcu_online_cpu(int cpu)
l rcu_init_percpu_data
static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) 重要数据结构说明:下列数据结构只列出了主要成员。 struct rcu_ctrlblk { long cur; long completed; cpumask_t cpumask; }; struct rcu_ctrlblk的主要作用就是定义上节提到的全局变量rcu_ctlblk,这个变量在系统中是唯一的。另外说明一下,为了记录方便,内核将从启动开始的每个grace period对应一个数字表示。 这里的cpumask是为了标识当前系统中的所有cpu,以便标记哪些cpu发生过上下文切换(经历过一个quiescent state)。而cur,completed,则用来同步。我们可以这样理解,cur和completed是系统级别的记录信息,也即系统实时经历的grace编号,一般情况下,新开一个graceperiod等待周期的话,cur会加1,当graceperiod结束后,会将completed置为cur,所以通常情况下,都是completed追着cur跑。那么我们可能会猜测,是不是如果complete= curr -1 的时候,就表示系统中graceperiod还没有结束?当completed= curr的时候,就表示系统中不存在graceperiod等待周期了?我们姑且这么理解,实际上有些许差别,但设计思想都是一样的。 struct rcu_data { long quiescbatch; int passed_quiesc; long batch; struct rcu_head *nxtlist; struct rcu_head **nxttail; struct rcu_head *curlist; struct rcu_head **curtail; struct rcu_head *donelist; struct rcu_head **donetail; }; 上面的结构,要达到的作用是,跟踪单个CPU上的RCU事务。 (1) passed_quiesc:这是一个flag标志,表示当前cpu是否已经发生过抢占了(经历过一个quiescent state),0表示为未发送过切换,1表示发生过切换; 说明:我们一直强调发生过一次cpu抢占就是经历过一个quiescent state,其实这是不严格的说法。为什么呢?因为自系统启动,各种进程频繁调度,肯定每个cpu都会发生过抢占。所以我们这里说的“发生过抢占”是指从某个特殊的时间点开始发生过抢占。那么这个特殊的时间点是什么时候呢?就是我们调用synchronize_rcu将rcu_head挂在每cpu变量上并挂起进程时,我们后面分析就会证实这一点。 (2) batch:表示一个grace periodid,表示本次被阻塞的写者,需要在哪个graceperiod之后被激活; (3) quiescbatch:表示一个grace periodid,用来比较当前cpu是否处于等待进程切换完成。 (编辑:淮北站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |