doc: Update dyntick-idle design documentation for NMI/irq consolidation

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
Paul E. McKenney 2017-10-06 13:48:14 -07:00
parent e68bbb266d
commit 3af3999b9a
1 changed files with 32 additions and 14 deletions

View File

@ -1182,8 +1182,8 @@ CPU (and from tracing) unless otherwise stated.
Its fields are as follows: Its fields are as follows:
<pre> <pre>
1 int dynticks_nesting; 1 long dynticks_nesting;
2 int dynticks_nmi_nesting; 2 long dynticks_nmi_nesting;
3 atomic_t dynticks; 3 atomic_t dynticks;
4 bool rcu_need_heavy_qs; 4 bool rcu_need_heavy_qs;
5 unsigned long rcu_qs_ctr; 5 unsigned long rcu_qs_ctr;
@ -1191,15 +1191,31 @@ Its fields are as follows:
</pre> </pre>
<p>The <tt>-&gt;dynticks_nesting</tt> field counts the <p>The <tt>-&gt;dynticks_nesting</tt> field counts the
nesting depth of normal interrupts. nesting depth of process execution, so that in normal circumstances
In addition, this counter is incremented when exiting dyntick-idle this counter has value zero or one.
mode and decremented when entering it. NMIs, irqs, and tracers are counted by the <tt>-&gt;dynticks_nmi_nesting</tt>
field.
Because NMIs cannot be masked, changes to this variable have to be
undertaken carefully using an algorithm provided by Andy Lutomirski.
The initial transition from idle adds one, and nested transitions
add two, so that a nesting level of five is represented by a
<tt>-&gt;dynticks_nmi_nesting</tt> value of nine.
This counter can therefore be thought of as counting the number This counter can therefore be thought of as counting the number
of reasons why this CPU cannot be permitted to enter dyntick-idle of reasons why this CPU cannot be permitted to enter dyntick-idle
mode, aside from non-maskable interrupts (NMIs). mode, aside from process-level transitions.
NMIs are counted by the <tt>-&gt;dynticks_nmi_nesting</tt>
field, except that NMIs that interrupt non-dyntick-idle execution <p>However, it turns out that when running in non-idle kernel context,
are not counted. the Linux kernel is fully capable of entering interrupt handlers that
never exit and perhaps also vice versa.
Therefore, whenever the <tt>-&gt;dynticks_nesting</tt> field is
incremented up from zero, the <tt>-&gt;dynticks_nmi_nesting</tt> field
is set to a large positive number, and whenever the
<tt>-&gt;dynticks_nesting</tt> field is decremented down to zero,
the the <tt>-&gt;dynticks_nmi_nesting</tt> field is set to zero.
Assuming that the number of misnested interrupts is not sufficient
to overflow the counter, this approach corrects the
<tt>-&gt;dynticks_nmi_nesting</tt> field every time the corresponding
CPU enters the idle loop from process context.
</p><p>The <tt>-&gt;dynticks</tt> field counts the corresponding </p><p>The <tt>-&gt;dynticks</tt> field counts the corresponding
CPU's transitions to and from dyntick-idle mode, so that this counter CPU's transitions to and from dyntick-idle mode, so that this counter
@ -1231,14 +1247,16 @@ in response.
<tr><th>&nbsp;</th></tr> <tr><th>&nbsp;</th></tr>
<tr><th align="left">Quick Quiz:</th></tr> <tr><th align="left">Quick Quiz:</th></tr>
<tr><td> <tr><td>
Why not just count all NMIs? Why not simply combine the <tt>-&gt;dynticks_nesting</tt>
Wouldn't that be simpler and less error prone? and <tt>-&gt;dynticks_nmi_nesting</tt> counters into a
single counter that just counts the number of reasons that
the corresponding CPU is non-idle?
</td></tr> </td></tr>
<tr><th align="left">Answer:</th></tr> <tr><th align="left">Answer:</th></tr>
<tr><td bgcolor="#ffffff"><font color="ffffff"> <tr><td bgcolor="#ffffff"><font color="ffffff">
It seems simpler only until you think hard about how to go about Because this would fail in the presence of interrupts whose
updating the <tt>rcu_dynticks</tt> structure's handlers never return and of handlers that manage to return
<tt>-&gt;dynticks</tt> field. from a made-up interrupt.
</font></td></tr> </font></td></tr>
<tr><td>&nbsp;</td></tr> <tr><td>&nbsp;</td></tr>
</table> </table>