- Lock only data, not code.
- Lock only what you want to protect, not everything around it. Use locking optimally.
Surprisingly enough, there are only two small rules for locking. These rules are definitely not exhaustive, they are rules of thumb and form the basis of this article. From these rules we will draw more and try to use real world examples to illustrate the various rules. Lets now see what each rule means.
/* Find the cache in the chain of caches. */
down(&cache_chain_sem);
/* the chain is never empty, cache_cache
is never destroyed */
if (clock_searchp == cachep)
clock_searchp =
list_entry(cachep->next.next,
kmem_cache_t, next);
list_del(&cachep->next);
up(&cache_chain_sem);
if (__kmem_cache_shrink(cachep)) {
printk(KERN_ERR "kmem_cache_destroy:
Can't free all objects %p\n", cachep);
down(&cache_chain_sem);
list_add(&cachep->next,&cache_chain);
up(&cache_chain_sem);
return 1;
}
In the example above, we grab the cache_chain_sem lock twice. We release the lock before calling __kmem_cache_shrink() and grab it again if necessary i.e, if __kmem_cache_shrink() returns a value greater than zero. We could have held the lock for the entire duration and freed it at the end, but it would conflict with the rules we stated above.
We would be protecting code and not data, we need to protect the cachep list, so we use the lock only to protect the contents of that list from changing. What if we held the lock and __kmem_cache_shrink() turned out to be an extremely long function? Other routines waiting for that lock would really starve, especially if __kmem_cache_shrink() does not change the cachep list. It would even be unfair to hold the lock and make merry while others are waiting for the lock.
This brings us to some important questions
- When do I need to implement locking into my code?
- How do I design my code to in corporate locking into it?
These questions are answered in the articles to follow.
No comments:
Post a Comment