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.

224 APPENDIX D. READ-COPY UPDATE IMPLEMENTATIONS1 void rcu_nmi_enter(void)2 {3 struct rcu_dynticks *rdtp;45 rdtp = &__get_cpu_var(rcu_dynticks);6 if (rdtp->dynticks & 0x1)7 return;8 rdtp->dynticks_nmi++;9 smp_mb();10 }1112 void rcu_nmi_exit(void)13 {14 struct rcu_dynticks *rdtp;1516 rdtp = &__get_cpu_var(rcu_dynticks);17 if (rdtp->dynticks & 0x1)18 return;19 smp_mb();20 rdtp->dynticks_nmi++;Figure D.45: NM<strong>Is</strong> from Dyntick-Idle Mode1 void rcu_irq_enter(void)2 {3 struct rcu_dynticks *rdtp;45 rdtp = &__get_cpu_var(rcu_dynticks);6 if (rdtp->dynticks_nesting++)7 return;8 rdtp->dynticks++;9 smp_mb();10 }1112 void rcu_irq_exit(void)13 {14 struct rcu_dynticks *rdtp;1516 rdtp = &__get_cpu_var(rcu_dynticks);17 if (--rdtp->dynticks_nesting)18 return;19 smp_mb();20 rdtp->dynticks++;21 if (__get_cpu_var(rcu_data).nxtlist ||22 __get_cpu_var(rcu_bh_data).nxtlist)23 set_need_resched();24 }indicate that this CPU may be ignored), and finallyline 10 decrements the ->dynticks_nesting field(which now must be zero to indicate that there is noreason to pay attention to this CPU).Lines 19 and 23 of rcu_exit_nohz() disableand re-enable interrupts, again to avoid interference.Line 20 obtains a pointer to this CPU’srcu_dynticks structure, line 21 increments the->dynticks field (which now must be odd in orderto indicate that RCU must once again pay attentionto this CPU), and line 22 increments the->dynticks_nesting field (which now must havethe value 1 to indicate that there is one reason topay attention to this CPU).D.3.7.2 NM<strong>Is</strong> from Dyntick-Idle ModeFigure D.45 shows rcu_nmi_enter() and rcu_nmi_exit(), which handle NMI entry and exit, respectively.<strong>It</strong> is important to keep in mind that enteringan NMI handler exits dyntick-idle mode and viceversa, in other words, RCU must pay attention toCPUs that claim to be in dyntick-idle mode whilethey are executing NMI handlers, due to the factthat NMI handlers can contain RCU read-side criticalsections. This reversal of roles can be quite confusing:you have been warned.Line 5 of rcu_nmi_enter() obtains a pointerto this CPU’s rcu_dynticks structure, and line 6checks to see if this CPU is already under scrutinyby RCU, with line 7 silently returning if so. Otherwise,line 8 increments the ->dynticks_nmi field,which must now have an odd-numbered value. Finally,line 9 executes a memory barrier to ensurethat the prior increment of ->dynticks_nmi is seeby all CPUs to happen before any subsequent RCUread-side critical section.Figure D.46: Interrupts from Dyntick-Idle ModeLine16ofrcu_nmi_exit()againfetchesapointerto this CPU’s rcu_dynticks structure, and line 17checks to see if RCU would be paying attentionto this CPU even if it were not in an NMI, withline 18 silently returning if so. Otherwise, line 19executes a memory barrier to ensure that any RCUread-sidecriticalsectionswithinthehandlerareseenby all CPUs to happen before the increment of the->dynticks_nmi field on line 20. The new value ofthis field must now be even.Quick Quiz D.51: But how does the code inFigure D.45 handle nested NM<strong>Is</strong>?D.3.7.3 Interrupts from Dyntick-Idle ModeFigure D.46 shows rcu_irq_enter() and rcu_irq_exit(), which handle interrupt entry and exit, respectively.As with NM<strong>Is</strong>, it is important to notethat entering an interrupt handler exits dyntick-idlemode and vice versa, due to the fact that RCU readsidecritical sections can appear in interrupt handlers.Line 5 of rcu_irq_enter() once again acquires areference to the current CPU’s rcu_dynticks structure.Line 6 increments the ->dynticks_nestingfield, and if the original value was already non-zero(in other words, RCU was already paying attentionto this CPU), line 7 silently returns. Otherwise,line 8 increments the ->dynticks field, which thenmust have an odd-numbered value. Finally, line 9executes a memory barrier so that this incrementis seen by all CPUs as happening before any RCUread-side critical sections that might be in the interrupthandler.

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

Saved successfully!

Ooh no, something went wrong!