1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>Protecting The Objects Themselves</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="Examples.html" title="Chapter&#160;7.&#160;Common Examples"><link rel="prev" href="examples-refcnt.html" title="Exposing Objects Outside This File"><link rel="next" href="common-problems.html" title="Chapter&#160;8.&#160;Common Problems"></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">Protecting The Objects Themselves</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="examples-refcnt.html">Prev</a>&#160;</td><th width="60%" align="center">Chapter&#160;7.&#160;Common Examples</th><td width="20%" align="right">&#160;<a accesskey="n" href="common-problems.html">Next</a></td></tr></table><hr></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="examples-lock-per-obj"></a>Protecting The Objects Themselves</h2></div></div></div><p>
2In these examples, we assumed that the objects (except the reference
3counts) never changed once they are created.  If we wanted to allow
4the name to change, there are three possibilities:
5    </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
6You can make <span class="symbol">cache_lock</span> non-static, and tell people
7to grab that lock before changing the name in any object.
8        </p></li><li class="listitem"><p>
9You can provide a <code class="function">cache_obj_rename</code> which grabs
10this lock and changes the name for the caller, and tell everyone to
11use that function.
12        </p></li><li class="listitem"><p>
13You can make the <span class="symbol">cache_lock</span> protect only the cache
14itself, and use another lock to protect the name.
15        </p></li></ul></div><p>
16Theoretically, you can make the locks as fine-grained as one lock for
17every field, for every object.  In practice, the most common variants
18are:
19</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
20One lock which protects the infrastructure (the <span class="symbol">cache</span>
21list in this example) and all the objects.  This is what we have done
22so far.
23	</p></li><li class="listitem"><p>
24One lock which protects the infrastructure (including the list
25pointers inside the objects), and one lock inside the object which
26protects the rest of that object.
27        </p></li><li class="listitem"><p>
28Multiple locks to protect the infrastructure (eg. one lock per hash
29chain), possibly with a separate per-object lock.
30        </p></li></ul></div><p>
31Here is the "lock-per-object" implementation:
32</p><pre class="programlisting">
33--- cache.c.refcnt-atomic	2003-12-11 15:50:54.000000000 +1100
34+++ cache.c.perobjectlock	2003-12-11 17:15:03.000000000 +1100
35@@ -6,11 +6,17 @@
36
37 struct object
38 {
39+        /* These two protected by cache_lock. */
40         struct list_head list;
41+        int popularity;
42+
43         atomic_t refcnt;
44+
45+        /* Doesn't change once created. */
46         int id;
47+
48+        spinlock_t lock; /* Protects the name */
49         char name[32];
50-        int popularity;
51 };
52
53 static DEFINE_SPINLOCK(cache_lock);
54@@ -77,6 +84,7 @@
55         obj-&gt;id = id;
56         obj-&gt;popularity = 0;
57         atomic_set(&amp;obj-&gt;refcnt, 1); /* The cache holds a reference */
58+        spin_lock_init(&amp;obj-&gt;lock);
59
60         spin_lock_irqsave(&amp;cache_lock, flags);
61         __cache_add(obj);
62</pre><p>
63Note that I decide that the <em class="structfield"><code>popularity</code></em>
64count should be protected by the <span class="symbol">cache_lock</span> rather
65than the per-object lock: this is because it (like the
66<span class="structname">struct list_head</span> inside the object) is
67logically part of the infrastructure.  This way, I don't need to grab
68the lock of every object in <code class="function">__cache_add</code> when
69seeking the least popular.
70</p><p>
71I also decided that the <em class="structfield"><code>id</code></em> member is
72unchangeable, so I don't need to grab each object lock in
73<code class="function">__cache_find()</code> to examine the
74<em class="structfield"><code>id</code></em>: the object lock is only used by a
75caller who wants to read or write the <em class="structfield"><code>name</code></em>
76field.
77</p><p>
78Note also that I added a comment describing what data was protected by
79which locks.  This is extremely important, as it describes the runtime
80behavior of the code, and can be hard to gain from just reading.  And
81as Alan Cox says, <span class="quote">&#8220;<span class="quote">Lock data, not code</span>&#8221;</span>.
82</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="examples-refcnt.html">Prev</a>&#160;</td><td width="20%" align="center"><a accesskey="u" href="Examples.html">Up</a></td><td width="40%" align="right">&#160;<a accesskey="n" href="common-problems.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Exposing Objects Outside This File&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;Chapter&#160;8.&#160;Common Problems</td></tr></table></div></body></html>
83