<?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>Protecting The Objects Themselves</title><meta name="generator" content="DocBook XSL Stylesheets V1.76.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><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" title="Protecting The Objects Themselves"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="examples-lock-per-obj"></a>Protecting The Objects Themselves</h2></div></div></div><p> In these examples, we assumed that the objects (except the reference counts) never changed once they are created. If we wanted to allow the name to change, there are three possibilities: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> You can make <span class="symbol">cache_lock</span> non-static, and tell people to grab that lock before changing the name in any object. </p></li><li class="listitem"><p> You can provide a <code class="function">cache_obj_rename</code> which grabs this lock and changes the name for the caller, and tell everyone to use that function. </p></li><li class="listitem"><p> You can make the <span class="symbol">cache_lock</span> protect only the cache itself, and use another lock to protect the name. </p></li></ul></div><p> Theoretically, you can make the locks as fine-grained as one lock for every field, for every object. In practice, the most common variants are: </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> One lock which protects the infrastructure (the <span class="symbol">cache</span> list in this example) and all the objects. This is what we have done so far. </p></li><li class="listitem"><p> One lock which protects the infrastructure (including the list pointers inside the objects), and one lock inside the object which protects the rest of that object. </p></li><li class="listitem"><p> Multiple locks to protect the infrastructure (eg. one lock per hash chain), possibly with a separate per-object lock. </p></li></ul></div><p> Here is the "lock-per-object" implementation: </p><pre class="programlisting"> --- cache.c.refcnt-atomic 2003-12-11 15:50:54.000000000 +1100 +++ cache.c.perobjectlock 2003-12-11 17:15:03.000000000 +1100 @@ -6,11 +6,17 @@ struct object { + /* These two protected by cache_lock. */ struct list_head list; + int popularity; + atomic_t refcnt; + + /* Doesn't change once created. */ int id; + + spinlock_t lock; /* Protects the name */ char name[32]; - int popularity; }; static DEFINE_SPINLOCK(cache_lock); @@ -77,6 +84,7 @@ obj->id = id; obj->popularity = 0; atomic_set(&obj->refcnt, 1); /* The cache holds a reference */ + spin_lock_init(&obj->lock); spin_lock_irqsave(&cache_lock, flags); __cache_add(obj); </pre><p> Note that I decide that the <em class="structfield"><code>popularity</code></em> count should be protected by the <span class="symbol">cache_lock</span> rather than the per-object lock: this is because it (like the <span class="structname">struct list_head</span> inside the object) is logically part of the infrastructure. This way, I don't need to grab the lock of every object in <code class="function">__cache_add</code> when seeking the least popular. </p><p> I also decided that the <em class="structfield"><code>id</code></em> member is unchangeable, so I don't need to grab each object lock in <code class="function">__cache_find()</code> to examine the <em class="structfield"><code>id</code></em>: the object lock is only used by a caller who wants to read or write the <em class="structfield"><code>name</code></em> field. </p><p> Note also that I added a comment describing what data was protected by which locks. This is extremely important, as it describes the runtime behavior of the code, and can be hard to gain from just reading. And as Alan Cox says, <span class="quote">“<span class="quote">Lock data, not code</span>”</span>. </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>