Sophie

Sophie

distrib > CentOS > 6 > i386 > by-pkgid > 2c51d8eb79f8810ada971ee8c30ce1e5 > files > 2207

kernel-doc-2.6.32-71.14.1.el6.noarch.rpm

<?xml version="1.0" encoding="ANSI_X3.4-1968" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968" /><title>Chapter&#160;7.&#160;Common Examples</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /><link rel="home" href="index.html" title="Unreliable Guide To Locking" /><link rel="up" href="index.html" title="Unreliable Guide To Locking" /><link rel="prev" href="ch06.html" title="Chapter&#160;6.&#160;The trylock Functions" /><link rel="next" href="ch07s02.html" title="Accessing From Interrupt Context" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter&#160;7.&#160;Common Examples</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch06.html">Prev</a>&#160;</td><th width="60%" align="center">&#160;</th><td width="20%" align="right">&#160;<a accesskey="n" href="ch07s02.html">Next</a></td></tr></table><hr /></div><div class="chapter" title="Chapter&#160;7.&#160;Common Examples"><div class="titlepage"><div><div><h2 class="title"><a id="Examples"></a>Chapter&#160;7.&#160;Common Examples</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="ch07.html#examples-usercontext">All In User Context</a></span></dt><dt><span class="sect1"><a href="ch07s02.html">Accessing From Interrupt Context</a></span></dt><dt><span class="sect1"><a href="ch07s03.html">Exposing Objects Outside This File</a></span></dt><dd><dl><dt><span class="sect2"><a href="ch07s03.html#examples-refcnt-atomic">Using Atomic Operations For The Reference Count</a></span></dt></dl></dd><dt><span class="sect1"><a href="ch07s04.html">Protecting The Objects Themselves</a></span></dt></dl></div><p>
Let's step through a simple example: a cache of number to name
mappings.  The cache keeps a count of how often each of the objects is
used, and when it gets full, throws out the least used one.

    </p><div class="sect1" title="All In User Context"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="examples-usercontext"></a>All In User Context</h2></div></div></div><p>
For our first example, we assume that all operations are in user
context (ie. from system calls), so we can sleep.  This means we can
use a mutex to protect the cache and all the objects within
it.  Here's the code:
    </p><pre class="programlisting">
#include &lt;linux/list.h&gt;
#include &lt;linux/slab.h&gt;
#include &lt;linux/string.h&gt;
#include &lt;linux/mutex.h&gt;
#include &lt;asm/errno.h&gt;

struct object
{
        struct list_head list;
        int id;
        char name[32];
        int popularity;
};

/* Protects the cache, cache_num, and the objects within it */
static DEFINE_MUTEX(cache_lock);
static LIST_HEAD(cache);
static unsigned int cache_num = 0;
#define MAX_CACHE_SIZE 10

/* Must be holding cache_lock */
static struct object *__cache_find(int id)
{
        struct object *i;

        list_for_each_entry(i, &amp;cache, list)
                if (i-&gt;id == id) {
                        i-&gt;popularity++;
                        return i;
                }
        return NULL;
}

/* Must be holding cache_lock */
static void __cache_delete(struct object *obj)
{
        BUG_ON(!obj);
        list_del(&amp;obj-&gt;list);
        kfree(obj);
        cache_num--;
}

/* Must be holding cache_lock */
static void __cache_add(struct object *obj)
{
        list_add(&amp;obj-&gt;list, &amp;cache);
        if (++cache_num &gt; MAX_CACHE_SIZE) {
                struct object *i, *outcast = NULL;
                list_for_each_entry(i, &amp;cache, list) {
                        if (!outcast || i-&gt;popularity &lt; outcast-&gt;popularity)
                                outcast = i;
                }
                __cache_delete(outcast);
        }
}

int cache_add(int id, const char *name)
{
        struct object *obj;

        if ((obj = kmalloc(sizeof(*obj), GFP_KERNEL)) == NULL)
                return -ENOMEM;

        strlcpy(obj-&gt;name, name, sizeof(obj-&gt;name));
        obj-&gt;id = id;
        obj-&gt;popularity = 0;

        mutex_lock(&amp;cache_lock);
        __cache_add(obj);
        mutex_unlock(&amp;cache_lock);
        return 0;
}

void cache_delete(int id)
{
        mutex_lock(&amp;cache_lock);
        __cache_delete(__cache_find(id));
        mutex_unlock(&amp;cache_lock);
}

int cache_find(int id, char *name)
{
        struct object *obj;
        int ret = -ENOENT;

        mutex_lock(&amp;cache_lock);
        obj = __cache_find(id);
        if (obj) {
                ret = 0;
                strcpy(name, obj-&gt;name);
        }
        mutex_unlock(&amp;cache_lock);
        return ret;
}
</pre><p>
Note that we always make sure we have the cache_lock when we add,
delete, or look up the cache: both the cache infrastructure itself and
the contents of the objects are protected by the lock.  In this case
it's easy, since we copy the data for the user, and never let them
access the objects directly.
    </p><p>
There is a slight (and common) optimization here: in
<code class="function">cache_add</code> we set up the fields of the object
before grabbing the lock.  This is safe, as no-one else can access it
until we put it in cache.
    </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch06.html">Prev</a>&#160;</td><td width="20%" align="center">&#160;</td><td width="40%" align="right">&#160;<a accesskey="n" href="ch07s02.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&#160;6.&#160;The trylock Functions&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;Accessing From Interrupt Context</td></tr></table></div></body></html>