由于当前进程可能被写入到阻塞任务链表,因此在退出临界区时先将嵌套层数写成负值,进行特殊处理,处理完成后上报QS状态。 QS如何上报 QS状态按照cpu->leaf->node->root->state的顺序逐级上报,RCU会在软中断中调用rcu_process_callbacks()->rcu_check_quiescent_state()检查QS的上报状态,如果有已经完成的GP,则找到等待...
rcu_start_gp()函数开始一个新的优雅周期。当一个CPU存在回调,而该回调需要等待优雅周期时,就需要调用此函数。 rcu_start_gp()函数更新rcu_state和rcu_data结构中的状态,以标识开始一个新的优雅周期,获取->onoff 锁 (并关中断) 以防止任何并发的CPU热插拨操作,在所有的rcu_node结构中设置位,以标识所有CPU (...
rcu_start_gp()函数更新rcu_state和rcu_data结构中的状态,以标识开始一个新的优雅周期,获取->onoff 锁 (并关中断) 以防止任何并发的CPU热插拨操作,在所有的rcu_node结构中设置位,以标识所有CPU (包括当前CPU) 必须经历一次静止状态,最后释放->onoff 锁。 设置位操作分两个阶段进行。首先,在没有持有任何锁的...
user其实在调用中真实的传入是user_tick,值为1指用户时间,0指系统时间,由于RCU必须在内核态执行,因此user为1说明必然不处于lock~unlock的时段,很有可能已经发生过rcu_read,因此发送一个RCU_SOFTIRQ软中断,调用rcu_process_callbacks。 synchronize_rcu的核心是wait_rcu_gp函数。 该函数通过注册一个func为wakeme_after...
此外,在调用kfree()释放节点之前,多了一个synchronize_rcu()函数。synchronize就是「同步」,那它在和谁同步呢?就是前面说的那些“引用旧数据区的reader”啦,因为此时它们可能还在引用指针p。这相当于给了这些reader一个优雅退出的宽限区,因此这段同步等待的时间被称为Grace Period(简称GP)。
rcu的callback通常是在sychronize_rcu中添加的wakeme_after_rcu,也就是唤醒synchronize_rcu的进程,它正在等待GP的结束。 callbacks的处理同样在软中断RCU_SOFTIRQ中完成 rcu_process_callbacks -> __rcu_process_callbacks -> invoke_rcu_callbacks -> rcu_do_batch ...
srcu_read_lock返回了idx,并做为参数传递给srcu_read_unlock函数,告知GP相关信息,具体后面会进行描述。synchronize_srcu和synchronize_rcu行为类似,都是阻塞当前进程,直到渡过GP之后才会继续执行,不同的是,synchronize_srcu需要struct srcu_struct参数来指明是哪一个子系统的SRCU。
RCU的一个最关键的特性在于,它能够保证数据能安全的被读取(原文用的是scan这个词,我把它翻译成读取貌似比较好?),即便数据被并发地更新。为了能够并发地插入数据,RCU使用了发布-订阅机制。举个例子,全局指针gp,指向一段新的已分配的空间并初始化,如下:
srcu_read_lock返回了idx,并做为参数传递给srcu_read_unlock函数,告知GP相关信息,具体后面会进行描述。synchronize_srcu和synchronize_rcu行为类似,都是阻塞当前进程,直到渡过GP之后才会继续执行,不同的是,synchronize_srcu需要struct srcu_struct参数来指明是哪一个子系统的SRCU。
发起一个GP时,rsp->gpnum++;结束一个GP时,rsp->completed = rsp->gpnum。 1.4 rcu callbacks处理 rcu的callback通常是在sychronize_rcu中添加的wakeme_after_rcu,也就是唤醒synchronize_rcu的进程,它正在等待GP的结束。 callbacks的处理同样在软中断RCU_SOFTIRQ中完成 ...