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.

214 APPENDIX D. READ-COPY UPDATE IMPLEMENTATIONS1 static void2 rcu_init_percpu_data(int cpu, struct rcu_state *rsp)3 {4 unsigned long flags;5 int i;6 long lastcomp;7 unsigned long mask;8 struct rcu_data *rdp = rsp->rda[cpu];9 struct rcu_node *rnp = rcu_get_root(rsp);1011 spin_lock_irqsave(&rnp->lock, flags);12 lastcomp = rsp->completed;13 rdp->completed = lastcomp;14 rdp->gpnum = lastcomp;15 rdp->passed_quiesc = 0;16 rdp->qs_pending = 1;17 rdp->beenonline = 1;18 rdp->passed_quiesc_completed = lastcomp - 1;19 rdp->grpmask = 1UL mynode->grplo);20 rdp->nxtlist = NULL;21 for (i = 0; i < RCU_NEXT_SIZE; i++)22 rdp->nxttail[i] = &rdp->nxtlist;23 rdp->qlen = 0;24 rdp->blimit = blimit;25 #ifdef CONFIG_NO_HZ26 rdp->dynticks = &per_cpu(rcu_dynticks, cpu);27 #endif /* #ifdef CONFIG_NO_HZ */28 rdp->cpu = cpu;29 spin_unlock(&rnp->lock);30 spin_lock(&rsp->onofflock);31 rnp = rdp->mynode;32 mask = rdp->grpmask;33 do {34 spin_lock(&rnp->lock);35 rnp->qsmaskinit |= mask;36 mask = rnp->grpmask;37 spin_unlock(&rnp->lock);38 rnp = rnp->parent;39 } while (rnp != NULL && !(rnp->qsmaskinit & mask));40 spin_unlock(&rsp->onofflock);41 cpu_quiet(cpu, rsp, rdp, lastcomp);42 local_irq_restore(flags);43 }Figure D.30: rcu init percpu data() CodeLine 8 gets a pointer to this CPU’s rcu_datastructure, based on the specified rcu_state structure,and places this pointer into the local variablerdp. Line 9 gets a pointer to the root rcu_node structure for the specified rcu_state structure,placing it in local variable rnp.Lines 11-29 initialize the fields of the rcu_datastructure under the protection of the root rcu_nodestructure’s lock in order to ensure consistent values.Line 17 is important for tracing, due to thefact that many Linux distributions set NR_CPUS toa very large number, which could result in excessiveoutput when tracing rcu_data structures. The->beenonline field is used to solve this problem,as it will be set to the value one on any rcu_datastructurecorrespondingtoaCPUthathaseverbeenonline, and set to zero for all other rcu_data structures.This allows the tracing code to easily ignoreirrelevant CPUs.Lines 30-40 propagate the onlining CPU’s bit upthe rcu_node hierarchy, proceeding until either theroot rcu_node is reached or until the correspondingbit is already set, whichever comes first. This bitsettingis done under the protection of ->onofflockin order to exclude initialization of a new grace period,and, in addition, each rcu_node structure isinitialized under the protection of its lock. Line 41then invokes cpu_quiet() to signal RCU that thisCPU has been in an extended quiescent state, andfinally, line 42 re-enables irqs.Quick Quiz D.36: Why call cpu_quiet() online 41 of Figure D.30, given that we are excludinggrace periods with various locks, and given that anyearlier grace periods would not have been waiting onthis previously-offlined CPU?<strong>It</strong> is important to note that rcu_init_percpu_data() is invoked not only at boot time, but alsoevery time that a given CPU is brought online.D.3.4.2 rcu online cpu()Figure D.31 shows the code for rcu_online_cpu(),which informs RCU that the specified CPU is comingonline.When dynticks (CONFIG_NO_HZ) is enabled, line 6obtains a reference to the specified CPU’s rcu_dynticks structure, which is shared between the“rcu” and “rcu bh” implementations of RCU. Line 7sets the ->dynticks_nesting field to the value one,reflecting the fact that a newly onlined CPU is notin dynticks-idle mode (recall that the ->dynticks_nesting field tracks the number of reasons thatthe corresponding CPU needs to be tracked forRCU read-side critical sections, in this case because

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

Saved successfully!

Ooh no, something went wrong!