Figure
shows rcu_nmi_enter() and rcu_nmi_exit(), which handle
NMI entry and exit, respectively.
It is important to keep in mind that entering an NMI handler
exits dyntick-idle mode and vice versa, in other words, RCU must
pay attention to CPUs that claim to be in dyntick-idle mode while
they are executing NMI handlers, due to the fact that NMI handlers
can contain RCU read-side critical sections.
This reversal of roles can be quite confusing: you have been warned.
Line 5 of rcu_nmi_enter() obtains a pointer to this CPU's rcu_dynticks structure, and line 6 checks to see if this CPU is already under scrutiny by 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 ensure that the prior increment of ->dynticks_nmi is see by all CPUs to happen before any subsequent RCU read-side critical section.
Line 16 of rcu_nmi_exit() again fetches a pointer to this CPU's rcu_dynticks structure, and line 17 checks to see if RCU would be paying attention to this CPU even if it were not in an NMI, with line 18 silently returning if so. Otherwise, line 19 executes a memory barrier to ensure that any RCU read-side critical sections within the handler are seen by all CPUs to happen before the increment of the ->dynticks_nmi field on line 20. The new value of this field must now be even.
Quick Quiz D.51:
But how does the code in
Figure
handle nested NMIs?
End Quick Quiz
Paul E. McKenney 2011-12-16