Sophie

Sophie

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

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML
><HEAD
><TITLE
>Protecting A Collection of Objects: Reference Counts</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="Avoiding Locks: Atomic Operations"
HREF="x286.html"><LINK
REL="NEXT"
TITLE="Things Which Sleep"
HREF="x315.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="x286.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="x315.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="REF-COUNTS"
></A
>Protecting A Collection of Objects: Reference Counts</H1
><P
>      Locking a collection of objects is fairly easy: you get a
      single spinlock, and you make sure you grab it before
      searching, adding or deleting an object.
    </P
><P
>      The purpose of this lock is not to protect the individual
      objects: you might have a separate lock inside each one for
      that.  It is to protect the <I
CLASS="EMPHASIS"
>data structure
      containing the objects</I
> from race conditions.  Often
      the same lock is used to protect the contents of all the
      objects as well, for simplicity, but they are inherently
      orthogonal (and many other big words designed to confuse).
    </P
><P
>      Changing this to a read-write lock will often help markedly if
      reads are far more common that writes.  If not, there is
      another approach you can use to reduce the time the lock is
      held: reference counts.
    </P
><P
>      In this approach, an object has an owner, who sets the
      reference count to one.  Whenever you get a pointer to the
      object, you increment the reference count (a `get' operation).
      Whenever you relinquish a pointer, you decrement the reference
      count (a `put' operation).  When the owner wants to destroy
      it, they mark it dead, and do a put.
    </P
><P
>      Whoever drops the reference count to zero (usually implemented
      with <TT
CLASS="FUNCTION"
>atomic_dec_and_test()</TT
>) actually cleans 
      up and frees the object.
    </P
><P
>      This means that you are guaranteed that the object won't
      vanish underneath you, even though you no longer have a lock
      for the collection.
    </P
><P
>      Here's some skeleton code:
    </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>        void create_foo(struct foo *x)
        {
                atomic_set(&#38;x-&#62;use, 1);
                spin_lock_bh(&#38;list_lock);
                ... insert in list ...
                spin_unlock_bh(&#38;list_lock);
        }

        struct foo *get_foo(int desc)
        {
                struct foo *ret;

                spin_lock_bh(&#38;list_lock);
                ... find in list ...
                if (ret) atomic_inc(&#38;ret-&#62;use);
                spin_unlock_bh(&#38;list_lock);

                return ret;
        }

        void put_foo(struct foo *x)
        {
                if (atomic_dec_and_test(&#38;x-&#62;use))
                        kfree(foo);
        }

        void destroy_foo(struct foo *x)
        {
                spin_lock_bh(&#38;list_lock);
                ... remove from list ...
                spin_unlock_bh(&#38;list_lock);

                put_foo(x);
        }
    </PRE
></TD
></TR
></TABLE
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="HELPFUL-MACROS"
></A
>Macros To Help You</H2
><P
>       There are a set of debugging macros tucked inside
       <TT
CLASS="FILENAME"
>include/linux/netfilter_ipv4/lockhelp.h</TT
>
       and <TT
CLASS="FILENAME"
>listhelp.h</TT
>: these are very
       useful for ensuring that locks are held in the right places to protect
       infrastructure.
     </P
></DIV
></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="x286.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="x315.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Avoiding Locks: Atomic Operations</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c196.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Things Which Sleep</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>