1<html><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.78.1"><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="trylock-functions.html" title="Chapter&#160;6.&#160;The trylock Functions"><link rel="next" href="examples-interrupt.html" title="Accessing From Interrupt Context"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><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="trylock-functions.html">Prev</a>&#160;</td><th width="60%" align="center">&#160;</th><td width="20%" align="right">&#160;<a accesskey="n" href="examples-interrupt.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="Examples"></a>Chapter&#160;7.&#160;Common Examples</h1></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="sect1"><a href="Examples.html#examples-usercontext">All In User Context</a></span></dt><dt><span class="sect1"><a href="examples-interrupt.html">Accessing From Interrupt Context</a></span></dt><dt><span class="sect1"><a href="examples-refcnt.html">Exposing Objects Outside This File</a></span></dt><dd><dl><dt><span class="sect2"><a href="examples-refcnt.html#examples-refcnt-atomic">Using Atomic Operations For The Reference Count</a></span></dt></dl></dd><dt><span class="sect1"><a href="examples-lock-per-obj.html">Protecting The Objects Themselves</a></span></dt></dl></div><p>
2Let's step through a simple example: a cache of number to name
3mappings.  The cache keeps a count of how often each of the objects is
4used, and when it gets full, throws out the least used one.
5
6    </p><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="examples-usercontext"></a>All In User Context</h2></div></div></div><p>
7For our first example, we assume that all operations are in user
8context (ie. from system calls), so we can sleep.  This means we can
9use a mutex to protect the cache and all the objects within
10it.  Here's the code:
11    </p><pre class="programlisting">
12#include &lt;linux/list.h&gt;
13#include &lt;linux/slab.h&gt;
14#include &lt;linux/string.h&gt;
15#include &lt;linux/mutex.h&gt;
16#include &lt;asm/errno.h&gt;
17
18struct object
19{
20        struct list_head list;
21        int id;
22        char name[32];
23        int popularity;
24};
25
26/* Protects the cache, cache_num, and the objects within it */
27static DEFINE_MUTEX(cache_lock);
28static LIST_HEAD(cache);
29static unsigned int cache_num = 0;
30#define MAX_CACHE_SIZE 10
31
32/* Must be holding cache_lock */
33static struct object *__cache_find(int id)
34{
35        struct object *i;
36
37        list_for_each_entry(i, &amp;cache, list)
38                if (i-&gt;id == id) {
39                        i-&gt;popularity++;
40                        return i;
41                }
42        return NULL;
43}
44
45/* Must be holding cache_lock */
46static void __cache_delete(struct object *obj)
47{
48        BUG_ON(!obj);
49        list_del(&amp;obj-&gt;list);
50        kfree(obj);
51        cache_num--;
52}
53
54/* Must be holding cache_lock */
55static void __cache_add(struct object *obj)
56{
57        list_add(&amp;obj-&gt;list, &amp;cache);
58        if (++cache_num &gt; MAX_CACHE_SIZE) {
59                struct object *i, *outcast = NULL;
60                list_for_each_entry(i, &amp;cache, list) {
61                        if (!outcast || i-&gt;popularity &lt; outcast-&gt;popularity)
62                                outcast = i;
63                }
64                __cache_delete(outcast);
65        }
66}
67
68int cache_add(int id, const char *name)
69{
70        struct object *obj;
71
72        if ((obj = kmalloc(sizeof(*obj), GFP_KERNEL)) == NULL)
73                return -ENOMEM;
74
75        strlcpy(obj-&gt;name, name, sizeof(obj-&gt;name));
76        obj-&gt;id = id;
77        obj-&gt;popularity = 0;
78
79        mutex_lock(&amp;cache_lock);
80        __cache_add(obj);
81        mutex_unlock(&amp;cache_lock);
82        return 0;
83}
84
85void cache_delete(int id)
86{
87        mutex_lock(&amp;cache_lock);
88        __cache_delete(__cache_find(id));
89        mutex_unlock(&amp;cache_lock);
90}
91
92int cache_find(int id, char *name)
93{
94        struct object *obj;
95        int ret = -ENOENT;
96
97        mutex_lock(&amp;cache_lock);
98        obj = __cache_find(id);
99        if (obj) {
100                ret = 0;
101                strcpy(name, obj-&gt;name);
102        }
103        mutex_unlock(&amp;cache_lock);
104        return ret;
105}
106</pre><p>
107Note that we always make sure we have the cache_lock when we add,
108delete, or look up the cache: both the cache infrastructure itself and
109the contents of the objects are protected by the lock.  In this case
110it's easy, since we copy the data for the user, and never let them
111access the objects directly.
112    </p><p>
113There is a slight (and common) optimization here: in
114<code class="function">cache_add</code> we set up the fields of the object
115before grabbing the lock.  This is safe, as no-one else can access it
116until we put it in cache.
117    </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="trylock-functions.html">Prev</a>&#160;</td><td width="20%" align="center">&#160;</td><td width="40%" align="right">&#160;<a accesskey="n" href="examples-interrupt.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>
118