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 7. Common Examples"><link rel="prev" href="examples-refcnt.html" title="Exposing Objects Outside This File"><link rel="next" href="common-problems.html" title="Chapter 8. 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> </td><th width="60%" align="center">Chapter 7. Common Examples</th><td width="20%" align="right"> <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->id = id; 56 obj->popularity = 0; 57 atomic_set(&obj->refcnt, 1); /* The cache holds a reference */ 58+ spin_lock_init(&obj->lock); 59 60 spin_lock_irqsave(&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">“<span class="quote">Lock data, not code</span>”</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> </td><td width="20%" align="center"><a accesskey="u" href="Examples.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="common-problems.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Exposing Objects Outside This File </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 8. Common Problems</td></tr></table></div></body></html> 83