[PATCH 14/25] Docs: kernel-hacking: Rewrite local_irq_{disable,enable,save,restore}

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This section has been greatly expanded and clarified.

Signed-off-by: Michael Witten <mfwitten@xxxxxxxxx>
---
 Documentation/DocBook/kernel-hacking.tmpl |  111 +++++++++++++++++++++++++++--
 1 files changed, 105 insertions(+), 6 deletions(-)

diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 2ddc79a..f995e7f 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -679,12 +679,111 @@
    </title>
 
-   <para>
-    These routines disable hard[ware] interrupts on the local CPU, and
-    restore them.  They are reentrant; saving the previous state in
-    their one <varname>unsigned long flags</varname> argument.  If you
-    know that interrupts are enabled, you can simply use
-    <function>local_irq_disable()</function> and
-    <function>local_irq_enable()</function>.
-   </para>
+   <para>
+    With respect to a CPU instruction, a <firstterm>local CPU</firstterm> is
+    a CPU that is executing that instruction.
+   </para>
+
+   <para>
+    Often, it is important to be able to execute a sequence of instructions
+    with the assurance that the corresponding local CPU won't be interrupted
+    until it has completed executing that sequence of instructions; under
+    these needs, such a sequence of instructions is considered as a whole to
+    be <firstterm>atomic</firstterm> (that is, 'indivisible'). The routines
+    discussed here are helpful in creating such
+    <firstterm>atomicity</firstterm>.
+   </para>
+
+   <para>
+    The main purpose of these routines is to affect how a
+    local CPU treats hard[ware] interrupts: By executing
+    <function>local_irq_disable()</function>, a local CPU is instructed
+    to ignore hard interrupts; by executing
+    <function>local_irq_enable()</function>, a local CPU is instructed
+    to respond to hard interrupts. Consequently, in the simplest case,
+    a block of code can be rendered atomic by placing
+    <function>local_irq_disable()</function> before the block and
+    <function>local_irq_enable()</function> after the block.
+   </para>
+
+   <para>
+    However, what if one such atomic block calls a function that runs
+    another such atomic block? In that case, this latter atomic block
+    might run <function>local_irq_enable()</function>
+    before the first atomic block finishes, thereby ruining the atomicity
+    of the first block.
+   </para>
+
+   <para>
+    This problem can be solved by noting whether a local CPU is already
+    ignoring hard interrupts when entering an atomic block and then restoring
+    that same status upon exiting the atomic block, all of which
+    can be achieved by replacing
+    <function>local_irq_{disable,enable}()</function> with
+    <function>local_irq_{save,restore}(<varname>flags</varname>)</function>
+    macros, where <varname>flags</varname> is a user-supplied stack-allocated
+    variable of type <emphasis>unsigned long</emphasis>
+    (note: it's <emphasis>not</emphasis> a pointer type).
+   </para>
+
+   <para>
+    The <function>local_irq_save(<varname>flags</varname>)</function> macro
+    exands around the <varname>flags</varname> variable to perform 2 tasks
+    on a local CPU:
+   </para>
+
+   <itemizedlist>
+    <listitem>
+     <para>
+      The local CPU's relevant processor-state bits (including
+      <emphasis>at least</emphasis> those that affect hard interrupts) are
+      stored in <varname>flags</varname>.
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      The local CPU is instructed to ignore hard interrupts; essentially
+      a call to <function>local_irq_disable()</function> is made.
+     </para>
+    </listitem>
+   </itemizedlist>
+
+   <para>
+    The <function>local_irq_restore(<varname>flags</varname>)</function> macro
+    exands to instruct a local CPU to use as its relevant processor-state bits
+    the values stored in the <varname>flags</varname> variable.
+   </para>
+
+   <para>
+    Hence, if a local CPU is already ignoring hard interrupts when
+    <function>local_irq_save(<varname>flags</varname>)</function> is used,
+    then that local CPU will continue to ignore hard interrupts when the
+    corresponding
+    <function>local_irq_restore(<varname>flags</varname>)</function> is
+    used, thereby allowing for the nesting of atomic blocks. However,
+    if a local CPU is responding to hard interrupts when
+    <function>local_irq_save(<varname>flags</varname>)</function> is used,
+    then that local CPU will once again respond to hard interrupts when
+    the corresponding
+    <function>local_irq_restore(<varname>flags</varname>)</function>
+    is used, as if a call to <function>local_irq_enable()</function>
+    has been made.
+   </para>
+
+   <para>
+    Of course,
+    <function>local_irq_{save,restore}(<varname>flags</varname>)</function>
+    are more expensive in time and space than are
+    <function>local_irq_{disable,enable}()</function>. Consequently,
+    the latter should be used when it makes sense to do so.
+   </para>
+
+   <para>
+    These macros/functions are reentrant.
+   </para>
+
+   <para>
+    There are also other means by which kernel code can achieve synchronization
+    and atomicity through locking mechanisms.
+   </para>
   </sect1>
 
-- 
1.7.0.94.gf7311

--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux