xref: /freebsd/share/man/man9/sx.9 (revision b28624fde638caadd4a89f50c9b7e7da0f98c4d2)
1.\"
2.\" Copyright (C) 2001 Jason Evans <jasone@FreeBSD.org>.  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.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice(s), this list of conditions and the following disclaimer as
9.\"    the first lines of this file unmodified other than the possible
10.\"    addition of one or more copyright notices.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice(s), this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
16.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18.\" DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
19.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22.\" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25.\" DAMAGE.
26.\"
27.\" $FreeBSD$
28.\"
29.Dd February 1, 2006
30.Dt SX 9
31.Os
32.Sh NAME
33.Nm sx ,
34.Nm sx_init ,
35.Nm sx_init_flags ,
36.Nm sx_destroy ,
37.Nm sx_slock ,
38.Nm sx_xlock ,
39.Nm sx_try_slock ,
40.Nm sx_try_xlock ,
41.Nm sx_sunlock ,
42.Nm sx_xunlock ,
43.Nm sx_unlock ,
44.Nm sx_try_upgrade ,
45.Nm sx_downgrade ,
46.Nm sx_sleep ,
47.Nm sx_xholder ,
48.Nm sx_xlocked ,
49.Nm sx_assert ,
50.Nm SX_SYSINIT
51.Nd kernel shared/exclusive lock
52.Sh SYNOPSIS
53.In sys/param.h
54.In sys/lock.h
55.In sys/sx.h
56.Ft void
57.Fn sx_init "struct sx *sx" "const char *description"
58.Ft void
59.Fn sx_init_flags "struct sx *sx" "const char *description" "int opts"
60.Ft void
61.Fn sx_destroy "struct sx *sx"
62.Ft void
63.Fn sx_slock "struct sx *sx"
64.Ft void
65.Fn sx_xlock "struct sx *sx"
66.Ft int
67.Fn sx_try_slock "struct sx *sx"
68.Ft int
69.Fn sx_try_xlock "struct sx *sx"
70.Ft void
71.Fn sx_sunlock "struct sx *sx"
72.Ft void
73.Fn sx_xunlock "struct sx *sx"
74.Ft void
75.Fn sx_unlock "struct sx *sx"
76.Ft int
77.Fn sx_try_upgrade "struct sx *sx"
78.Ft void
79.Fn sx_downgrade "struct sx *sx"
80.Ft int
81.Fn sx_sleep "void *chan" "struct sx *sx" "int priority" "const char *wmesg" "int timo"
82.Ft "struct thread *"
83.Fn sx_xholder "struct sx *sx"
84.Ft int
85.Fn sx_xlocked "struct sx *sx"
86.Pp
87.Cd "options INVARIANTS"
88.Cd "options INVARIANT_SUPPORT"
89.Ft void
90.Fn sx_assert "struct sx *sx" "int what"
91.In sys/kernel.h
92.Fn SX_SYSINIT "name" "struct sx *sx" "const char *description"
93.Sh DESCRIPTION
94Shared/exclusive locks are used to protect data that are read far more often
95than they are written.
96Shared/exclusive locks do not implement priority propagation like mutexes and
97reader/writer locks to prevent priority inversions, so
98shared/exclusive locks should be used prudently.
99.Pp
100Shared/exclusive locks are created with either
101.Fn sx_init
102or
103.Fn sx_init_flags
104where
105.Fa sx
106is a pointer to space for a
107.Vt struct sx ,
108and
109.Fa description
110is a pointer to a null-terminated character string that describes the
111shared/exclusive lock.
112The
113.Fa opts
114argument to
115.Fn sx_init_flags
116specifies a set of optional flags to alter the behavior of
117.Fa sx .
118It contains one or more of the following flags:
119.Bl -tag -width SX_ADAPTIVESPIN
120.It Dv SX_ADAPTIVESPIN
121If the kernel is compiled with
122.Cd "options ADAPTIVE_SX" ,
123then lock operations for
124.Fa sx
125will spin instead of sleeping while an exclusive lock holder is executing on
126another CPU.
127.It Dv SX_DUPOK
128Witness should not log messages about duplicate locks being acquired.
129.It Dv SX_NOWITNESS
130Instruct
131.Xr witness 4
132to ignore this lock.
133.It Dv SX_NOPROFILE
134Do not profile this lock.
135.It Dv SX_RECURSE
136Allow threads to recursively acquire exclusive locks for
137.Fa sx .
138.It Dv SX_QUIET
139Do not log any operations for this lock via
140.Xr ktr 4 .
141.El
142.Pp
143Shared/exclusive locks are destroyed with
144.Fn sx_destroy .
145The lock
146.Fa sx
147must not be locked by any thread when it is destroyed.
148.Pp
149Threads acquire and release a shared lock by calling
150.Fn sx_slock
151or
152.Fn sx_try_slock
153and
154.Fn sx_sunlock
155or
156.Fn sx_unlock .
157Threads acquire and release an exclusive lock by calling
158.Fn sx_xlock
159or
160.Fn sx_try_xlock
161and
162.Fn sx_xunlock
163or
164.Fn sx_unlock .
165A thread can attempt to upgrade a currently held shared lock to an exclusive
166lock by calling
167.Fn sx_try_upgrade .
168A thread that has an exclusive lock can downgrade it to a shared lock by
169calling
170.Fn sx_downgrade .
171.Pp
172.Fn sx_try_slock
173and
174.Fn sx_try_xlock
175will return 0 if the shared/exclusive lock cannot be acquired immediately;
176otherwise the shared/exclusive lock will be acquired and a non-zero value will
177be returned.
178.Pp
179.Fn sx_try_upgrade
180will return 0 if the shared lock cannot be upgraded to an exclusive lock
181immediately; otherwise the exclusive lock will be acquired and a non-zero value
182will be returned.
183.Pp
184A thread can atomically release a shared/exclusive lock while waiting for an
185event by calling
186.Fn sx_sleep .
187For more details on the parameters to this function,
188see
189.Xr sleep 9 .
190.Pp
191When compiled with
192.Cd "options INVARIANTS"
193and
194.Cd "options INVARIANT_SUPPORT" ,
195the
196.Fn sx_assert
197function tests
198.Fa sx
199for the assertions specified in
200.Fa what ,
201and panics if they are not met.
202One of the following assertions must be specified:
203.Bl -tag -width ".Dv SA_UNLOCKED"
204.It Dv SA_LOCKED
205Assert that the current thread has either a shared or an exclusive lock on the
206.Vt sx
207lock pointed to by the first argument.
208.It Dv SA_SLOCKED
209Assert that the current thread has a shared lock on the
210.Vt sx
211lock pointed to by
212the first argument.
213.It Dv SA_XLOCKED
214Assert that the current thread has an exclusive lock on the
215.Vt sx
216lock pointed to
217by the first argument.
218.It Dv SA_UNLOCKED
219Assert that the current thread has no lock on the
220.Vt sx
221lock pointed to
222by the first argument.
223.El
224.Pp
225In addition, one of the following optional assertions may be included with
226either an
227.Dv SA_LOCKED ,
228.Dv SA_SLOCKED ,
229or
230.Dv SA_XLOCKED
231assertion:
232.Bl -tag -width ".Dv SA_NOTRECURSED"
233.It Dv SA_RECURSED
234Assert that the current thread has a recursed lock on
235.Fa sx .
236.It Dv SA_NOTRECURSED
237Assert that the current thread does not have a recursed lock on
238.Fa sx .
239.El
240.Pp
241.Fn sx_xholder
242will return a pointer to the thread which currently holds an exclusive lock on
243.Fa sx .
244If no thread holds an exclusive lock on
245.Fa sx ,
246then
247.Dv NULL
248is returned instead.
249.Pp
250.Fn sx_xlocked
251will return non-zero if the current thread holds the exclusive lock;
252otherwise, it will return zero.
253.Pp
254For ease of programming,
255.Fn sx_unlock
256is provided as a macro frontend to the respective functions,
257.Fn sx_sunlock
258and
259.Fn sx_xunlock .
260Algorithms that are aware of what state the lock is in should use either
261of the two specific functions for a minor performance benefit.
262.Pp
263The
264.Fn SX_SYSINIT
265macro is used to generate a call to the
266.Fn sx_sysinit
267routine at system startup in order to initialize a given
268.Fa sx
269lock.
270The parameters are the same as
271.Fn sx_init
272but with an additional argument,
273.Fa name ,
274that is used in generating unique variable names for the related
275structures associated with the lock and the sysinit routine.
276.Pp
277A thread may not hold both a shared lock and an exclusive lock on the same
278lock simultaneously;
279attempting to do so will result in deadlock.
280.Sh CONTEXT
281A thread may hold a shared or exclusive lock on an
282.Nm
283lock while sleeping.
284As a result, an
285.Nm
286lock may not be acquired while holding a mutex.
287Otherwise, if one thread slept while holding an
288.Nm
289lock while another thread blocked on the same
290.Nm
291lock after acquiring a mutex, then the second thread would effectively
292end up sleeping while holding a mutex, which is not allowed.
293.Sh SEE ALSO
294.Xr locking 9 ,
295.Xr lock 9 ,
296.Xr mutex 9 ,
297.Xr panic 9 ,
298.Xr rwlock 9 ,
299.Xr sema 9
300.Sh BUGS
301Currently there is no way to assert that a lock is not held.
302This is not possible in the
303.No non- Ns Dv WITNESS
304case for asserting that this thread
305does not hold a shared lock.
306In the
307.No non- Ns Dv WITNESS
308case, the
309.Dv SA_LOCKED
310and
311.Dv SA_SLOCKED
312assertions merely check that some thread holds a shared lock.
313They do not ensure that the current thread holds a shared lock.
314