Sophie

Sophie

distrib > Mandriva > 9.0 > i586 > by-pkgid > 98e91bc877e03cf3582cd163550eb7e3 > files > 648

kernel-doc-html-2.4.19-16mdk.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML
><HEAD
><TITLE
>Avoiding Locks: Read And Write Ordering</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="Unreliable Guide To Locking"
HREF="book1.html"><LINK
REL="UP"
TITLE="Common Techniques"
HREF="c196.html"><LINK
REL="PREVIOUS"
TITLE="Big Reader Locks"
HREF="x256.html"><LINK
REL="NEXT"
TITLE="Avoiding Locks: Atomic Operations"
HREF="x286.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Unreliable Guide To Locking</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="x256.html"
ACCESSKEY="P"
>&#60;&#60;&#60; Previous</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Common Techniques</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="x286.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="LOCK-AVOIDANCE-RW"
></A
>Avoiding Locks: Read And Write Ordering</H1
><P
>      Sometimes it is possible to avoid locking.  Consider the
      following case from the 2.2 firewall code, which inserted an
      element into a single linked list in user context:
    </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>        new-&#62;next = i-&#62;next;
        i-&#62;next = new;
    </PRE
></TD
></TR
></TABLE
><P
>      Here the author (Alan Cox, who knows what he's doing) assumes
      that the pointer assignments are atomic.  This is important,
      because networking packets would traverse this list on bottom
      halves without a lock.  Depending on their exact timing, they
      would either see the new element in the list with a valid 
      <TT
CLASS="STRUCTFIELD"
><I
>next</I
></TT
> pointer, or it would not be in the 
      list yet.  A lock is still required against other CPUs inserting
      or deleting from the list, of course.
    </P
><P
>      Of course, the writes <I
CLASS="EMPHASIS"
>must</I
> be in this
      order, otherwise the new element appears in the list with an
      invalid <TT
CLASS="STRUCTFIELD"
><I
>next</I
></TT
> pointer, and any other 
      CPU iterating at the wrong time will jump through it into garbage.  
      Because modern CPUs reorder, Alan's code actually read as follows:
    </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>        new-&#62;next = i-&#62;next;
        wmb();
        i-&#62;next = new;
    </PRE
></TD
></TR
></TABLE
><P
>      The <TT
CLASS="FUNCTION"
>wmb()</TT
> is a write memory barrier 
      (<TT
CLASS="FILENAME"
>include/asm/system.h</TT
>): neither 
      the compiler nor the CPU will allow any writes to memory after the 
      <TT
CLASS="FUNCTION"
>wmb()</TT
> to be visible to other hardware
      before any of the writes before the <TT
CLASS="FUNCTION"
>wmb()</TT
>.
    </P
><P
>      As i386 does not do write reordering, this bug would never
      show up on that platform.  On other SMP platforms, however, it
      will.
    </P
><P
>      There is also <TT
CLASS="FUNCTION"
>rmb()</TT
> for read ordering: to ensure 
      any previous variable reads occur before following reads.  The simple
      <TT
CLASS="FUNCTION"
>mb()</TT
> macro combines both 
      <TT
CLASS="FUNCTION"
>rmb()</TT
> and <TT
CLASS="FUNCTION"
>wmb()</TT
>.
    </P
><P
>      Some atomic operations are defined to act as a memory barrier
      (ie. as per the <TT
CLASS="FUNCTION"
>mb()</TT
> macro, but if in
      doubt, be explicit.
      
      Also,
      spinlock operations act as partial barriers: operations after
      gaining a spinlock will never be moved to precede the
      <TT
CLASS="FUNCTION"
>spin_lock()</TT
> call, and operations before
      releasing a spinlock will never be moved after the
      <TT
CLASS="FUNCTION"
>spin_unlock()</TT
> call.
      
    </P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x256.html"
ACCESSKEY="P"
>&#60;&#60;&#60; Previous</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="x286.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Big Reader Locks</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c196.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Avoiding Locks: Atomic Operations</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>