免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2656 | 回复: 2
打印 上一主题 下一主题

[内核同步] __call_rcu如何防止多核竞争 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-02-05 20:13 |只看该作者 |倒序浏览
__call_rcu只用了关中断来保护rcp,但是在SMP场景下有可能多个CPU同时把head链到rcp,而rcp又是全局变量rcu_sched_ctrlblk,这样就有可能产生冲突。系统是怎么保证不出问题的呢?

static void __call_rcu(struct rcu_head *head,
                       void (*func)(struct rcu_head *rcu),
                       struct rcu_ctrlblk *rcp)
{
        unsigned long flags;

        debug_rcu_head_queue(head);
        head->func = func;
        head->next = NULL;

        local_irq_save(flags);
        *rcp->curtail = head;
        rcp->curtail = &head->next;
        RCU_TRACE(rcp->qlen++);
        local_irq_restore(flags);
}

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
2 [报告]
发表于 2015-02-05 23:49 |只看该作者
回复 1# littlenewer


  你看的代码是rcutiny.c吧。那个是单核的版本,多核的版本应该是rcutree.c


static void
__call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
           struct rcu_state *rsp)
{
        unsigned long flags;
        struct rcu_data *rdp;

        head->func = func;
        head->next = NULL;

        smp_mb(); /* Ensure RCU update seen before callback registry. */

        /*
         * Opportunistically note grace-period endings and beginnings.
         * Note that we might see a beginning right after we see an
         * end, but never vice versa, since this CPU has to pass through
         * a quiescent state betweentimes.
         */
        local_irq_save(flags);
        rdp = rsp->rda[smp_processor_id()];
        rcu_process_gp_end(rsp, rdp);
        check_for_new_grace_period(rsp, rdp);

        /* Add the callback to our list. */
        *rdp->nxttail[RCU_NEXT_TAIL] = head;
        rdp->nxttail[RCU_NEXT_TAIL] = &head->next;

        /* Start a new grace period if one not already started. */
        if (!rcu_gp_in_progress(rsp)) {
                unsigned long nestflag;
                struct rcu_node *rnp_root = rcu_get_root(rsp);

                raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
                rcu_start_gp(rsp, nestflag);  /* releases rnp_root->lock. */
        }

        /*
         * Force the grace period if too many callbacks or too long waiting.
         * Enforce hysteresis, and don't invoke force_quiescent_state()
         * if some other CPU has recently done so.  Also, don't bother
         * invoking force_quiescent_state() if the newly enqueued callback
         * is the only one waiting for a grace period to complete.
         */
        if (unlikely(++rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
                rdp->blimit = LONG_MAX;
                if (rsp->n_force_qs == rdp->n_force_qs_snap &&
                    *rdp->nxttail[RCU_DONE_TAIL] != head)
                        force_quiescent_state(rsp, 0);
                rdp->n_force_qs_snap = rsp->n_force_qs;
                rdp->qlen_last_fqs_check = rdp->qlen;
        } else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies))
                force_quiescent_state(rsp, 1);
        local_irq_restore(flags);
}

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
3 [报告]
发表于 2015-02-05 23:50 |只看该作者
偶,要声明一下,我的代码是2.6.34.10的。3.x内核文件改名了,但结论不变。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP