Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Documentation: rw_lock lessons learned

In recent months, two different network projects erroneously
strayed down the rw_lock path. Update the Documentation
based upon comments by Eric Dumazet and Paul E. McKenney in
those threads.

Further updates await somebody else with more expertise.

Changes:
- Merged with extensive content by Stephen Hemminger.
- Fix one of the comments by Linus Torvalds.

Signed-off-by: William.Allen.Simpson@gmail.com
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

William Allen Simpson and committed by
Linus Torvalds
fb0bbb92 f4054253

+84 -100
+84 -100
Documentation/spinlocks.txt
··· 1 - SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and 2 - are hence deprecated. 1 + Lesson 1: Spin locks 3 2 4 - Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or 5 - __SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate for static 6 - initialization. 3 + The most basic primitive for locking is spinlock. 7 4 8 - Most of the time, you can simply turn: 9 - 10 - static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED; 11 - 12 - into: 13 - 14 - static DEFINE_SPINLOCK(xxx_lock); 15 - 16 - Static structure member variables go from: 17 - 18 - struct foo bar { 19 - .lock = SPIN_LOCK_UNLOCKED; 20 - }; 21 - 22 - to: 23 - 24 - struct foo bar { 25 - .lock = __SPIN_LOCK_UNLOCKED(bar.lock); 26 - }; 27 - 28 - Declaration of static rw_locks undergo a similar transformation. 29 - 30 - Dynamic initialization, when necessary, may be performed as 31 - demonstrated below. 32 - 33 - spinlock_t xxx_lock; 34 - rwlock_t xxx_rw_lock; 35 - 36 - static int __init xxx_init(void) 37 - { 38 - spin_lock_init(&xxx_lock); 39 - rwlock_init(&xxx_rw_lock); 40 - ... 41 - } 42 - 43 - module_init(xxx_init); 44 - 45 - The following discussion is still valid, however, with the dynamic 46 - initialization of spinlocks or with DEFINE_SPINLOCK, etc., used 47 - instead of SPIN_LOCK_UNLOCKED. 48 - 49 - ----------------------- 50 - 51 - On Fri, 2 Jan 1998, Doug Ledford wrote: 52 - > 53 - > I'm working on making the aic7xxx driver more SMP friendly (as well as 54 - > importing the latest FreeBSD sequencer code to have 7895 support) and wanted 55 - > to get some info from you. The goal here is to make the various routines 56 - > SMP safe as well as UP safe during interrupts and other manipulating 57 - > routines. So far, I've added a spin_lock variable to things like my queue 58 - > structs. Now, from what I recall, there are some spin lock functions I can 59 - > use to lock these spin locks from other use as opposed to a (nasty) 60 - > save_flags(); cli(); stuff; restore_flags(); construct. Where do I find 61 - > these routines and go about making use of them? Do they only lock on a 62 - > per-processor basis or can they also lock say an interrupt routine from 63 - > mucking with a queue if the queue routine was manipulating it when the 64 - > interrupt occurred, or should I still use a cli(); based construct on that 65 - > one? 66 - 67 - See <asm/spinlock.h>. The basic version is: 68 - 69 - spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED; 70 - 5 + static DEFINE_SPINLOCK(xxx_lock); 71 6 72 7 unsigned long flags; 73 8 ··· 10 75 ... critical section here .. 11 76 spin_unlock_irqrestore(&xxx_lock, flags); 12 77 13 - and the above is always safe. It will disable interrupts _locally_, but the 78 + The above is always safe. It will disable interrupts _locally_, but the 14 79 spinlock itself will guarantee the global lock, so it will guarantee that 15 80 there is only one thread-of-control within the region(s) protected by that 16 - lock. 17 - 18 - Note that it works well even under UP - the above sequence under UP 19 - essentially is just the same as doing a 81 + lock. This works well even under UP. The above sequence under UP 82 + essentially is just the same as doing 20 83 21 84 unsigned long flags; 22 85 ··· 24 91 25 92 so the code does _not_ need to worry about UP vs SMP issues: the spinlocks 26 93 work correctly under both (and spinlocks are actually more efficient on 27 - architectures that allow doing the "save_flags + cli" in one go because I 28 - don't export that interface normally). 94 + architectures that allow doing the "save_flags + cli" in one operation). 29 95 30 - NOTE NOTE NOTE! The reason the spinlock is so much faster than a global 31 - interrupt lock under SMP is exactly because it disables interrupts only on 32 - the local CPU. The spin-lock is safe only when you _also_ use the lock 33 - itself to do locking across CPU's, which implies that EVERYTHING that 34 - touches a shared variable has to agree about the spinlock they want to 35 - use. 96 + NOTE! Implications of spin_locks for memory are further described in: 97 + 98 + Documentation/memory-barriers.txt 99 + (5) LOCK operations. 100 + (6) UNLOCK operations. 36 101 37 102 The above is usually pretty simple (you usually need and want only one 38 103 spinlock for most things - using more than one spinlock can make things a ··· 51 120 then they are NOT mutually exclusive, and the critical regions can happen 52 121 at the same time on two different CPU's. That's fine per se, but the 53 122 critical regions had better be critical for different things (ie they 54 - can't stomp on each other). 123 + can't stomp on each other). 55 124 56 125 The above is a problem mainly if you end up mixing code - for example the 57 126 routines in ll_rw_block() tend to use cli/sti to protect the atomicity of 58 127 their actions, and if a driver uses spinlocks instead then you should 59 - think about issues like the above.. 128 + think about issues like the above. 60 129 61 130 This is really the only really hard part about spinlocks: once you start 62 131 using spinlocks they tend to expand to areas you might not have noticed 63 132 before, because you have to make sure the spinlocks correctly protect the 64 133 shared data structures _everywhere_ they are used. The spinlocks are most 65 - easily added to places that are completely independent of other code (ie 66 - internal driver data structures that nobody else ever touches, for 67 - example). 134 + easily added to places that are completely independent of other code (for 135 + example, internal driver data structures that nobody else ever touches). 136 + 137 + NOTE! The spin-lock is safe only when you _also_ use the lock itself 138 + to do locking across CPU's, which implies that EVERYTHING that 139 + touches a shared variable has to agree about the spinlock they want 140 + to use. 68 141 69 142 ---- 70 143 ··· 76 141 77 142 If your data accesses have a very natural pattern where you usually tend 78 143 to mostly read from the shared variables, the reader-writer locks 79 - (rw_lock) versions of the spinlocks are often nicer. They allow multiple 144 + (rw_lock) versions of the spinlocks are sometimes useful. They allow multiple 80 145 readers to be in the same critical region at once, but if somebody wants 81 - to change the variables it has to get an exclusive write lock. The 82 - routines look the same as above: 146 + to change the variables it has to get an exclusive write lock. 147 + 148 + NOTE! reader-writer locks require more atomic memory operations than 149 + simple spinlocks. Unless the reader critical section is long, you 150 + are better off just using spinlocks. 151 + 152 + The routines look the same as above: 83 153 84 154 rwlock_t xxx_lock = RW_LOCK_UNLOCKED; 85 - 86 155 87 156 unsigned long flags; 88 157 ··· 98 159 .. read and write exclusive access to the info ... 99 160 write_unlock_irqrestore(&xxx_lock, flags); 100 161 101 - The above kind of lock is useful for complex data structures like linked 102 - lists etc, especially when you know that most of the work is to just 103 - traverse the list searching for entries without changing the list itself, 104 - for example. Then you can use the read lock for that kind of list 105 - traversal, which allows many concurrent readers. Anything that _changes_ 106 - the list will have to get the write lock. 162 + The above kind of lock may be useful for complex data structures like 163 + linked lists, especially searching for entries without changing the list 164 + itself. The read lock allows many concurrent readers. Anything that 165 + _changes_ the list will have to get the write lock. 107 166 108 - Note: you cannot "upgrade" a read-lock to a write-lock, so if you at _any_ 167 + NOTE! RCU is better for list traversal, but requires careful 168 + attention to design detail (see Documentation/RCU/listRCU.txt). 169 + 170 + Also, you cannot "upgrade" a read-lock to a write-lock, so if you at _any_ 109 171 time need to do any changes (even if you don't do it every time), you have 110 - to get the write-lock at the very beginning. I could fairly easily add a 111 - primitive to create a "upgradeable" read-lock, but it hasn't been an issue 112 - yet. Tell me if you'd want one. 172 + to get the write-lock at the very beginning. 173 + 174 + NOTE! We are working hard to remove reader-writer spinlocks in most 175 + cases, so please don't add a new one without consensus. (Instead, see 176 + Documentation/RCU/rcu.txt for complete information.) 113 177 114 178 ---- 115 179 ··· 175 233 176 234 Linus 177 235 236 + ---- 178 237 238 + Reference information: 239 + 240 + For dynamic initialization, use spin_lock_init() or rwlock_init() as 241 + appropriate: 242 + 243 + spinlock_t xxx_lock; 244 + rwlock_t xxx_rw_lock; 245 + 246 + static int __init xxx_init(void) 247 + { 248 + spin_lock_init(&xxx_lock); 249 + rwlock_init(&xxx_rw_lock); 250 + ... 251 + } 252 + 253 + module_init(xxx_init); 254 + 255 + For static initialization, use DEFINE_SPINLOCK() / DEFINE_RWLOCK() or 256 + __SPIN_LOCK_UNLOCKED() / __RW_LOCK_UNLOCKED() as appropriate. 257 + 258 + SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated. These interfere 259 + with lockdep state tracking. 260 + 261 + Most of the time, you can simply turn: 262 + static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED; 263 + into: 264 + static DEFINE_SPINLOCK(xxx_lock); 265 + 266 + Static structure member variables go from: 267 + 268 + struct foo bar { 269 + .lock = SPIN_LOCK_UNLOCKED; 270 + }; 271 + 272 + to: 273 + 274 + struct foo bar { 275 + .lock = __SPIN_LOCK_UNLOCKED(bar.lock); 276 + }; 277 + 278 + Declaration of static rw_locks undergo a similar transformation.