Merge branch 'master' into net80211-update
[dragonfly.git] / share / man / man9 / spinlock.9
1 .\"
2 .\" Copyright (c) 2006 The DragonFly Project.  All rights reserved.
3 .\" 
4 .\" Redistribution and use in source and binary forms, with or without
5 .\" modification, are permitted provided that the following conditions
6 .\" are met:
7 .\" 
8 .\" 1. Redistributions of source code must retain the above copyright
9 .\"    notice, this list of conditions and the following disclaimer.
10 .\" 2. Redistributions in binary form must reproduce the above copyright
11 .\"    notice, this list of conditions and the following disclaimer in
12 .\"    the documentation and/or other materials provided with the
13 .\"    distribution.
14 .\" 3. Neither the name of The DragonFly Project nor the names of its
15 .\"    contributors may be used to endorse or promote products derived
16 .\"    from this software without specific, prior written permission.
17 .\" 
18 .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 .\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22 .\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 .\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 .\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 .\" SUCH DAMAGE.
30 .\"
31 .Dd April 10, 2010
32 .Os
33 .Dt SPINLOCK 9
34 .Sh NAME
35 .Nm spin_init ,
36 .Nm spin_lock_rd ,
37 .Nm spin_lock_rd_quick ,
38 .Nm spin_lock_wr ,
39 .Nm spin_lock_wr_quick ,
40 .Nm spin_trylock_wr ,
41 .Nm spin_uninit ,
42 .Nm spin_unlock_rd ,
43 .Nm spin_unlock_rd_quick ,
44 .Nm spin_unlock_wr ,
45 .Nm spin_unlock_wr_quick
46 .Nd core spinlocks
47 .Sh SYNOPSIS
48 .In sys/spinlock.h
49 .In sys/spinlock2.h
50 .Ft void
51 .Fn spin_init "struct spinlock *mtx"
52 .Ft void
53 .Fn spin_uninit "struct spinlock *mtx"
54 .Ft void
55 .Fn spin_lock_rd "struct spinlock *mtx"
56 .Ft void
57 .Fn spin_lock_rd_quick "globaldata_t gd" "struct spinlock *mtx"
58 .Ft void
59 .Fn spin_unlock_rd "struct spinlock *mtx"
60 .Ft void
61 .Fn spin_unlock_rd_quick "globaldata_t gd" "struct spinlock *mtx"
62 .Ft void
63 .Fn spin_lock_wr "struct spinlock *mtx"
64 .Ft void
65 .Fn spin_lock_wr_quick "globaldata_t gd" "struct spinlock *mtx"
66 .Ft boolean_t
67 .Fn spin_trylock_wr "struct spinlock *mtx"
68 .Ft void
69 .Fn spin_unlock_wr "struct spinlock *mtx"
70 .Ft void
71 .Fn spin_unlock_wr_quick "globaldata_t gd" "struct spinlock *mtx"
72 .Sh DESCRIPTION
73 The
74 .Fa spinlock
75 structure and call API are defined in the
76 .In sys/spinlock.h
77 and
78 .In sys/spinlock2.h
79 header files, respectively.
80 .Pp
81 The
82 .Fn spin_init
83 function initializes a new
84 .Fa spinlock
85 structure for use.
86 The structure is cleaned up with
87 .Fn spin_uninit
88 when it is no longer needed.
89 .Pp
90 The
91 .Fn spin_lock_rd
92 function obtains a shared
93 .Em read-only
94 spinlock.
95 A thread may hold only one shared lock at a time, and may not acquire any
96 new exclusive locks while holding a shared lock (but may already be holding
97 some).
98 A shared spinlock can be held by multiple CPUs concurrently.
99 If a thread attempts to obtain an exclusive spinlock while shared
100 references from other CPUs exist it will spin until the shared references
101 go away.
102 No new shared references will be allowed (that is, new shared requests
103 will also spin) while the exclusive spinlock is being acquired.
104 If you have the current CPU's
105 .Fa globaldata
106 pointer in hand you can call
107 .Fn spin_lock_rd_quick ,
108 but most code will just call the normal version.
109 Shared spinlocks reserve a bit in the spinlock's memory for each CPU
110 and do not clear the bit once set.
111 This means that once set, a shared spinlock does not need to issue a
112 locked read-modify-write bus cycle to the spinlock's memory, which in
113 turn greatly reduces conflicts between CPU caches.
114 The bit is cleared via a different mechanism only when an exclusive
115 spinlock is acquired.
116 The result is extremely low overheads even when a shared spinlock is
117 being operated upon concurrently by multiple CPUs.
118 .Pp
119 A previously obtained shared spinlock is released by calling either
120 .Fn spin_unlock_rd
121 or
122 .Fn spin_unlock_rd_quick .
123 .Pp
124 The
125 .Fn spin_lock_wr
126 function obtains an exclusive
127 .Em read-write
128 spinlock.
129 A thread may hold any number of exclusive spinlocks but should always
130 be mindful of ordering deadlocks.
131 Exclusive spinlocks can only be safely
132 acquired if no shared spinlocks are held.
133 The
134 .Fn spin_trylock_wr
135 function will return
136 .Dv TRUE
137 if the spinlock was successfully obtained and
138 .Dv FALSE
139 if it wasn't.
140 If you have the current CPU's
141 .Fa globaldata
142 pointer in hand you can call
143 .Fn spin_lock_wr_quick ,
144 but most code will just call the normal version.
145 A spinlock used only for exclusive access has about the same overhead
146 as a mutex based on a locked bus cycle.
147 When used in a mixed shared/exclusive environment, however, additional
148 overhead may be incurred to obtain the exclusive spinlock.
149 Because shared spinlocks are left intact even after released (to
150 optimize shared spinlock performance), the exclusive spinlock code
151 must run through any shared bits it finds in the spinlock, clear them,
152 and check the related CPU's
153 .Fa globaldata
154 structure to determine whether it needs to spin or not.
155 .Pp
156 A previously obtained exclusive spinlock is released by calling either
157 .Fn spin_unlock_wr
158 or
159 .Fn spin_unlock_wr_quick .
160 .Sh IMPLEMENTATION NOTES
161 A thread may not hold any spinlock across a blocking condition or
162 thread switch.
163 LWKT tokens should be used for situations where you want an exclusive
164 run-time lock that will survive a blocking condition or thread switch.
165 Tokens will be automatically unlocked when a thread switches away and
166 relocked when the thread is switched back in.
167 If you want a lock that survives a blocking condition or thread switch
168 without being released, use
169 .Xr lockmgr 9
170 locks or LWKT reader/writer locks.
171 .Pp
172 .Dx Ap s
173 core spinlocks should only be used around small contained sections of
174 code.
175 For example, to manage a reference count or to implement higher level
176 locking mechanisms.
177 Both the token code and the
178 .Xr lockmgr 9
179 code use exclusive spinlocks internally.
180 Core spinlocks should not be used around large chunks of code.
181 .Pp
182 Holding one or more spinlocks will disable thread preemption by
183 another thread (e.g. preemption by an interrupt thread), but will not
184 disable FAST interrupts or IPIs.
185 This means that a FAST interrupt can still operate during a spinlock,
186 and any threaded interrupt (which is basically all interrupts except
187 the clock interrupt) will still be scheduled for later execution, but
188 will not be able to preempt the current thread.
189 If you wish to disable FAST interrupts and IPIs you need to enter a
190 critical section prior to obtaining the spinlock.
191 .Pp
192 Currently, FAST interrupts, including IPI messages, are not allowed to
193 acquire any spinlocks.
194 It is possible to work around this if
195 .Va mycpu->gd_spinlocks_wr
196 and
197 .Va mycpu->gd_spinlocks_rd
198 are both 0.
199 If one
200 or the other is not zero, the FAST interrupt or IPI cannot acquire
201 any spinlocks without risking a deadlock, even if the spinlocks in
202 question are not related.
203 .Pp
204 A thread may hold any number of exclusive
205 .Em read-write
206 spinlocks.
207 However, a thread may only hold one shared
208 .Em read-only
209 spinlock, and may not acquire any new exclusive locks while it is holding
210 that one shared lock.
211 This requirement is due to the method exclusive
212 spinlocks use to determine when they can clear cached shared bits in
213 the lock.
214 If an exclusive lock is acquired while holding shared locks,
215 a deadlock can occur even if the locks are unrelated.
216 Always be mindful of potential deadlocks.
217 .Pp
218 Spinlocks spin.
219 A thread will not block, switch away, or lose its critical section
220 while obtaining or releasing a spinlock.
221 Spinlocks do not use IPIs or other mechanisms.
222 They are considered to be a very low level mechanism.
223 .Pp
224 If a spinlock can not be obtained after one second a warning will be
225 printed on the console.
226 If a system panic occurs, spinlocks will succeed after one second in
227 order to allow the panic operation to proceed.
228 .Pp
229 If you have a complex structure such as a
230 .Xr vnode 9
231 which contains a token or
232 .Xr lockmgr 9
233 lock, it is legal to directly access the internal spinlock embedded
234 in those structures for other purposes as long as the spinlock is not
235 held when you issue the token or
236 .Xr lockmgr 9
237 operation.
238 .Sh FILES
239 The uncontended path of the spinlock implementation is in
240 .Pa /sys/sys/spinlock2.h .
241 The core of the spinlock implementation is in
242 .Pa /sys/kern/kern_spinlock.c .
243 .Sh SEE ALSO
244 .Xr crit_enter 9 ,
245 .Xr lockmgr 9 ,
246 .Xr serializer 9
247 .Sh HISTORY
248 A
249 .Nm spinlock
250 implementation first appeared in
251 .Dx 1.3 .
252 .Sh AUTHORS
253 .An -nosplit
254 The original
255 .Nm spinlock
256 implementation was written by
257 .An Jeffrey M. Hsu
258 and was later extended by
259 .An Matthew Dillon .
260 This manual page was written by
261 .An Matthew Dillon
262 and
263 .An Sascha Wildner .