Merge branch 'vendor/MPFR' into gcc441
[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 .\" $DragonFly: src/share/man/man9/spinlock.9,v 1.7 2008/02/17 21:47:39 nant Exp $
32 .\"
33 .Dd February 17, 2008
34 .Os
35 .Dt SPINLOCK 9
36 .Sh NAME
37 .Nm spin_init ,
38 .Nm spin_lock_rd ,
39 .Nm spin_lock_rd_quick ,
40 .Nm spin_lock_wr ,
41 .Nm spin_lock_wr_quick ,
42 .Nm spin_trylock_wr ,
43 .Nm spin_uninit ,
44 .Nm spin_unlock_rd ,
45 .Nm spin_unlock_rd_quick ,
46 .Nm spin_unlock_wr ,
47 .Nm spin_unlock_wr_quick
48 .Nd core spinlocks
49 .Sh SYNOPSIS
50 .In sys/spinlock.h
51 .In sys/spinlock2.h
52 .Ft void
53 .Fn spin_init "struct spinlock *mtx"
54 .Ft void
55 .Fn spin_uninit "struct spinlock *mtx"
56 .Ft void
57 .Fn spin_lock_rd "struct spinlock *mtx"
58 .Ft void
59 .Fn spin_lock_rd_quick "globaldata_t gd" "struct spinlock *mtx"
60 .Ft void
61 .Fn spin_unlock_rd "struct spinlock *mtx"
62 .Ft void
63 .Fn spin_unlock_rd_quick "globaldata_t gd" "struct spinlock *mtx"
64 .Ft void
65 .Fn spin_lock_wr "struct spinlock *mtx"
66 .Ft void
67 .Fn spin_lock_wr_quick "globaldata_t gd" "struct spinlock *mtx"
68 .Ft boolean_t
69 .Fn spin_trylock_wr "struct spinlock *mtx"
70 .Ft void
71 .Fn spin_unlock_wr "struct spinlock *mtx"
72 .Ft void
73 .Fn spin_unlock_wr_quick "globaldata_t gd" "struct spinlock *mtx"
74 .Sh DESCRIPTION
75 The
76 .Fa spinlock
77 structure and call API are defined in the
78 .In sys/spinlock.h
79 and
80 .In sys/spinlock2.h
81 header files, respectively.
82 .Pp
83 The
84 .Fn spin_init
85 function initializes a new
86 .Fa spinlock
87 structure for use.
88 The structure is cleaned up with
89 .Fn spin_uninit
90 when it is no longer needed.
91 .Pp
92 The
93 .Fn spin_lock_rd
94 function obtains a shared
95 .Em read-only
96 spinlock.
97 A thread may hold only one shared lock at a time, and may not acquire any
98 new exclusive locks while holding a shared lock (but may already be holding
99 some).
100 A shared spinlock can be held by multiple CPUs concurrently.
101 If a thread attempts to obtain an exclusive spinlock while shared
102 references from other CPUs exist it will spin until the shared references
103 go away.
104 No new shared references will be allowed (that is, new shared requests
105 will also spin) while the exclusive spinlock is being acquired.
106 If you have the current CPU's
107 .Fa globaldata
108 pointer in hand you can call
109 .Fn spin_lock_rd_quick ,
110 but most code will just call the normal version.
111 Shared spinlocks reserve a bit in the spinlock's memory for each CPU
112 and do not clear the bit once set.
113 This means that once set, a shared spinlock does not need to issue a
114 locked read-modify-write bus cycle to the spinlock's memory, which in
115 turn greatly reduces conflicts between CPU caches.
116 The bit is cleared via a different mechanism only when an exclusive
117 spinlock is acquired.
118 The result is extremely low overheads even when a shared spinlock is
119 being operated upon concurrently by multiple CPUs.
120 .Pp
121 A previously obtained shared spinlock is released by calling either
122 .Fn spin_unlock_rd
123 or
124 .Fn spin_unlock_rd_quick .
125 .Pp
126 The
127 .Fn spin_lock_wr
128 function obtains an exclusive
129 .Em read-write
130 spinlock.
131 A thread may hold any number of exclusive spinlocks but should always
132 be mindful of ordering deadlocks.
133 Exclusive spinlocks can only be safely
134 acquired if no shared spinlocks are held.
135 The
136 .Fn spin_trylock_wr
137 function will return
138 .Dv TRUE
139 if the spinlock was successfully obtained and
140 .Dv FALSE
141 if it wasn't.
142 If you have the current CPU's
143 .Fa globaldata
144 pointer in hand you can call
145 .Fn spin_lock_wr_quick ,
146 but most code will just call the normal version.
147 A spinlock used only for exclusive access has about the same overhead
148 as a mutex based on a locked bus cycle.
149 When used in a mixed shared/exclusive environment, however, additional
150 overhead may be incurred to obtain the exclusive spinlock.
151 Because shared spinlocks are left intact even after released (to
152 optimize shared spinlock performance), the exclusive spinlock code
153 must run through any shared bits it finds in the spinlock, clear them,
154 and check the related CPU's
155 .Fa globaldata
156 structure to determine whether it needs to spin or not.
157 .Pp
158 A previously obtained exclusive spinlock is released by calling either
159 .Fn spin_unlock_wr
160 or
161 .Fn spin_unlock_wr_quick .
162 .Sh IMPLEMENTATION NOTES
163 A thread may not hold any spinlock across a blocking condition or
164 thread switch.
165 LWKT tokens should be used for situations where you want an exclusive
166 run-time lock that will survive a blocking condition or thread switch.
167 Tokens will be automatically unlocked when a thread switches away and
168 relocked when the thread is switched back in.
169 If you want a lock that survives a blocking condition or thread switch
170 without being released, use
171 .Xr lockmgr 9
172 locks or LWKT reader/writer locks.
173 .Pp
174 .Dx Ap s
175 core spinlocks should only be used around small contained sections of
176 code.
177 For example, to manage a reference count or to implement higher level
178 locking mechanisms.
179 Both the token code and the
180 .Xr lockmgr 9
181 code use exclusive spinlocks internally.
182 Core spinlocks should not be used around large chunks of code.
183 .Pp
184 Holding one or more spinlocks will disable thread preemption by
185 another thread (e.g. preemption by an interrupt thread), but will not
186 disable FAST interrupts or IPIs.
187 This means that a FAST interrupt can still operate during a spinlock,
188 and any threaded interrupt (which is basically all interrupts except
189 the clock interrupt) will still be scheduled for later execution, but
190 will not be able to preempt the current thread.
191 If you wish to disable FAST interrupts and IPIs you need to enter a
192 critical section prior to obtaining the spinlock.
193 .Pp
194 Currently, FAST interrupts, including IPI messages, are not allowed to
195 acquire any spinlocks.
196 It is possible to work around this if
197 .Va mycpu->gd_spinlocks_wr
198 and
199 .Va mycpu->gd_spinlocks_rd
200 are both 0.
201 If one
202 or the other is not zero, the FAST interrupt or IPI cannot acquire
203 any spinlocks without risking a deadlock, even if the spinlocks in
204 question are not related.
205 .Pp
206 A thread may hold any number of exclusive
207 .Em read-write
208 spinlocks.
209 However, a thread may only hold one shared
210 .Em read-only
211 spinlock, and may not acquire any new exclusive locks while it is holding
212 that one shared lock.
213 This requirement is due to the method exclusive
214 spinlocks use to determine when they can clear cached shared bits in
215 the lock.
216 If an exclusive lock is acquired while holding shared locks,
217 a deadlock can occur even if the locks are unrelated.
218 Always be mindful of potential deadlocks.
219 .Pp
220 Spinlocks spin.
221 A thread will not block, switch away, or lose its critical section
222 while obtaining or releasing a spinlock.
223 Spinlocks do not use IPIs or other mechanisms.
224 They are considered to be a very low level mechanism.
225 .Pp
226 If a spinlock can not be obtained after one second a warning will be
227 printed on the console.
228 If a system panic occurs, spinlocks will succeed after one second in
229 order to allow the panic operation to proceed.
230 .Pp
231 If you have a complex structure such as a
232 .Xr vnode 9
233 which contains a token or
234 .Xr lockmgr 9
235 lock, it is legal to directly access the internal spinlock embedded
236 in those structures for other purposes as long as the spinlock is not
237 held when you issue the token or
238 .Xr lockmgr 9
239 operation.
240 .Sh SEE ALSO
241 .Xr crit_enter 9 ,
242 .Xr lockmgr 9 ,
243 .Xr serializer 9
244 .Sh HISTORY
245 A
246 .Nm spinlock
247 implementation first appeared in
248 .Dx 1.3 .
249 .Sh AUTHORS
250 .An -nosplit
251 The original
252 .Nm spinlock
253 implementation was written by
254 .An Jeffrey M. Hsu
255 and was later extended by
256 .An Matthew Dillon .
257 This manual page was written by
258 .An Matthew Dillon
259 and
260 .An Sascha Wildner .