10.07.2015 Views

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

D.3. HIERARCHICAL RCU CODE WALKTHROUGH 2151 static void __cpuinit rcu_online_cpu(int cpu)2 {3 #ifdef CONFIG_NO_HZ4 struct rcu_dynticks *rdtp;56 rdtp = &per_cpu(rcu_dynticks, cpu);7 rdtp->dynticks_nesting = 1;8 rdtp->dynticks |= 1;9 rdtp->dynticks_nmi = (rdtp->dynticks_nmi + 1) & ~0x1;10 #endif /* #ifdef CONFIG_NO_HZ */11 rcu_init_percpu_data(cpu, &rcu_state);12 rcu_init_percpu_data(cpu, &rcu_bh_state);13 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);14 }Figure D.31: rcu online cpu() Codeit can run process-level code). Line 8 forces the->dynticks field to an odd value that is at leastas large as the last value it had when previouslyonline, again reflecting the fact that newly onlinedCPUsarenotindynticks-idlemode, andline9forcesthe ->dynticks_nmi field to an even value that isat least as large as the last value it had when previouslyonline, reflecting the fact that this CPU is notcurrently executing in an NMI handler.Lines 11-13 are executed regardless of the valueof the CONFIG_NO_HZ kernel parameter. Line 11 initializesthe specified CPU’s rcu_data structure for“rcu”, and line 12 does so for “rcu bh”. Finally,line 13 registers the rcu_process_callbacks() tobe invoked by subsequent raise_softirq() invocationson this CPU.D.3.4.3 rcu offline cpu()Figure D.32 shows the code for __rcu_offline_cpu() and its wrapper function, rcu_offline_cpu(). Thepurposeofthiswrapperfunction(shownin lines 43-47 of the figure) is simply to invoke__rcu_offline_cpu() twice, once for “rcu” andagain for “rcu bh”. The purpose of the __rcu_offline_cpu() function is to prevent future graceperiods from waiting on the CPU being offlined, tonote the extended quiescent state, and to find a newhome for any RCU callbacks in process on this CPU.Turning to __rcu_offline_cpu(), shown onlines 1-41 of the figure, line 12 acquires the specifiedrcu_state structure’s ->onofflock, excludinggrace-period initialization for multi-rcu_node hierarchies.Quick Quiz D.37: But what if the rcu_nodehierarchy has only a single structure, as it would ona small system? <strong>What</strong> prevents concurrent graceperiodinitialization in that case, given the code inFigure D.32?Line 13 picks up a pointer to the leaf rcu_nodestructure corresponding to this CPU, using the ->1 static void2 __rcu_offline_cpu(int cpu, struct rcu_state *rsp)3 {4 int i;5 unsigned long flags;6 long lastcomp;7 unsigned long mask;8 struct rcu_data *rdp = rsp->rda[cpu];9 struct rcu_data *rdp_me;10 struct rcu_node *rnp;1112 spin_lock_irqsave(&rsp->onofflock, flags);13 rnp = rdp->mynode;14 mask = rdp->grpmask;15 do {16 spin_lock(&rnp->lock);17 rnp->qsmaskinit &= ~mask;18 if (rnp->qsmaskinit != 0) {19 spin_unlock(&rnp->lock);20 break;21 }22 mask = rnp->grpmask;23 spin_unlock(&rnp->lock);24 rnp = rnp->parent;25 } while (rnp != NULL);26 lastcomp = rsp->completed;27 spin_unlock(&rsp->onofflock);28 cpu_quiet(cpu, rsp, rdp, lastcomp);29 rdp_me = rsp->rda[smp_processor_id()];30 if (rdp->nxtlist != NULL) {31 *rdp_me->nxttail[RCU_NEXT_TAIL] = rdp->nxtlist;32 rdp_me->nxttail[RCU_NEXT_TAIL] =33 rdp->nxttail[RCU_NEXT_TAIL];34 rdp->nxtlist = NULL;35 for (i = 0; i < RCU_NEXT_SIZE; i++)36 rdp->nxttail[i] = &rdp->nxtlist;37 rdp_me->qlen += rdp->qlen;38 rdp->qlen = 0;39 }40 local_irq_restore(flags);41 }4243 static void rcu_offline_cpu(int cpu)44 {45 __rcu_offline_cpu(cpu, &rcu_state);46 __rcu_offline_cpu(cpu, &rcu_bh_state);47 }Figure D.32: rcu offline cpu() Code

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!