加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 运营中心 > 交互 > 正文

深入理解RCU实现

发布时间:2016-10-29 16:06:37 所属栏目:交互 来源:站长网
导读:副标题#e# 深入理解RCU实现 ——基于 内核2.6.21 RCU实现(lvyilong316) RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构, 读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝一个副本,然

1.2) 如果系统之前已经有写者在被rcu监控着,但还没来得及经过一个grace period,这个时候curlist不为空,nxtlist也不为空,写者会被加入nxtlist中。由于curlist不为空,说明上个rcu周期的写者还没有处理完,于是不会将本次阻塞的写者加入curlist,一直到上次的curlist里的rcu_head被处理完(都移动到了donelist),才会将后来的写者纳入RCU考虑(移动到curlist)(假如这个期间又来了多个写者,则多个写者的rcu_head共享下一个grace period,也就是下一个grace period结束后这多个写者都会被唤醒)。进入下一步。

2) rcu_process_callbacks调用每CPU函数rcu_check_quiescent_state开始监控,检测所有的CPU是否会经历一个进程切换。 这个函数是如何得知需要开始监控的? 答案在于quiescbatch与全局的rcp->cur比较。 初始化时rdp->quiescbatch =rcp->completed = rcp->cur。 由于1.1有新grace period开启,所以rcp->cur已经加1了,于是rdp->quiescbatch和rcp->curr不等,进而将此cpu的rdp->passed_quiesc设为0,表示这个周期开始,我要等待这个cpu经历一个进程切换,等待该CPU将passed_quiesc置为1。即与前面讲到的passed_quiesc标志置0的时机吻合。最后将rdp->quiescbatch置为 rcp->cur,以避免下次再进入软中断里将passed_quiesc重复置0。

void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,  

                    struct rcu_data *rdp)  

{  

    if (rdp->quiescbatch != rcp->cur) {  

        /* start new grace period: */  

        rdp->qs_pending = 1;  

        rdp->passed_quiesc = 0;  

        rdp->quiescbatch = rcp->cur;  

        return;  

    }  

}  

3) 本次软中断结束,下次软中断到来,再次进入rcu_check_quiescent_state进行检测,如果本CPU的rdp->passed_quiesc已经置1,则需要cpu_quiet将本CPU标志位从全局的rcp->cpumask中清除,如果cpumask为0了,则说明自上次RCU写者被挂起以来,所有CPU都已经历了一次进程切换,于是本次rcu等待周期结束,将rcp->completed置为rcp->cur,重置cpumask为全f,并尝试重新开启一个新的grace period。我们可以看到RCU用了如此多的同步标志,却少用spinlock锁,是多么巧妙的设计,不过这也提高了理解的难度。

void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,  

                    struct rcu_data *rdp)  

{  

    if (rdp->quiescbatch != rcp->cur) {  

        /* start new grace period: */  

        rdp->qs_pending = 1;  

        rdp->passed_quiesc = 0;  

        rdp->quiescbatch = rcp->cur;  

        return;  

    }  

  

    if (!rdp->passed_quiesc)  

        return;  

    /*this cpu has passed a quies state*/  

    if (likely(rdp->quiescbatch == rcp->cur)) {  

        cpu_clear(cpu, rcp->cpumask);  

        if (cpus_empty(rcp->cpumask))   

            rcp->completed = rcp->cur;  

    }  

}  

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读