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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

D.3. HIERARCHICAL RCU CODE WALKTHROUGH 2231 static void rcu_do_batch(struct rcu_data *rdp)2 {3 unsigned long flags;4 struct rcu_head *next, *list, **tail;5 int count;67 if (!cpu_has_callbacks_ready_to_invoke(rdp))8 return;9 local_irq_save(flags);10 list = rdp->nxtlist;11 rdp->nxtlist = *rdp->nxttail[RCU_DONE_TAIL];12 *rdp->nxttail[RCU_DONE_TAIL] = NULL;13 tail = rdp->nxttail[RCU_DONE_TAIL];14 for (count = RCU_NEXT_SIZE - 1; count >= 0; count--)15 if (rdp->nxttail[count] ==16 rdp->nxttail[RCU_DONE_TAIL])17 rdp->nxttail[count] = &rdp->nxtlist;18 local_irq_restore(flags);19 count = 0;20 while (list) {21 next = list->next;22 prefetch(next);23 list->func(list);24 list = next;25 if (++count >= rdp->blimit)26 break;27 }28 local_irq_save(flags);29 rdp->qlen -= count;30 if (list != NULL) {31 *tail = rdp->nxtlist;32 rdp->nxtlist = list;33 for (count = 0; count < RCU_NEXT_SIZE; count++)34 if (&rdp->nxtlist == rdp->nxttail[count])35 rdp->nxttail[count] = tail;36 else37 break;38 }39 if (rdp->blimit == LONG_MAX && rdp->qlen blimit = blimit;41 local_irq_restore(flags);42 if (cpu_has_callbacks_ready_to_invoke(rdp))43 raise_softirq(RCU_SOFTIRQ);44 }Figure D.43: Code for rcu do batch()1 void rcu_enter_nohz(void)2 {3 unsigned long flags;4 struct rcu_dynticks *rdtp;56 smp_mb();7 local_irq_save(flags);8 rdtp = &__get_cpu_var(rcu_dynticks);9 rdtp->dynticks++;10 rdtp->dynticks_nesting--;11 local_irq_restore(flags);12 }1314 void rcu_exit_nohz(void)15 {16 unsigned long flags;17 struct rcu_dynticks *rdtp;1819 local_irq_save(flags);20 rdtp = &__get_cpu_var(rcu_dynticks);21 rdtp->dynticks++;22 rdtp->dynticks_nesting++;23 local_irq_restore(flags);24 smp_mb();25 }Figure D.44: Entering and Exiting Dyntick-IdleModeThissetoffunctionsisgreatlysimplifiedfromthatused in preemptable RCU, see Section E.7 for a descriptionof the earlier more-complex model. ManfredSpraulputforththeideaforthissimplifedinterfacein one of his state-based RCU patches [Spr08b,Spr08a].Section D.3.7.1 describes the functions that enterand exit dynticks-idle mode from process context,Section D.3.7.2 describes the handling of NM<strong>Is</strong>from dynticks-idle mode, Section D.3.7.3 covers handlingofinterruptsfromdynticks-idlemode,andSectionD.3.7.4 presents functions that check whethersome other CPU is currently in dynticks-idle mode.D.3.7.1 Entering and Exiting Dyntick-IdleModeFigure D.44 shows the rcu_enter_nohz() and rcu_exit_nohz() functions that allow the scheduler totransition to and from dynticks-idle mode. Therefore,after rcu_enter_nohz() has been call, RCUwill ignore it, at least until the next rcu_exit_nohz(), the next interrupt, or the next NMI.Line 6 of rcu_enter_nohz() executes a memorybarrier to ensure that any preceding RCU readsidecritical sections are seen to have occured beforethe following code that tells RCU to ignorethis CPU. Lines 7 and 11 disable and restore interruptsin order to avoid interference with the statechange. Line 8 picks up a pointer to the runningCPU’s rcu_dynticks structure, line 9 incrementsthe ->dynticks field (which now must be even to

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

Saved successfully!

Ooh no, something went wrong!