SX(9) | Kernel Developer's Manual | SX(9) |
NAME¶
sx
,
sx_init
,
sx_init_flags
,
sx_destroy
,
sx_slock
,
sx_xlock
,
sx_slock_sig
,
sx_xlock_sig
,
sx_try_slock
,
sx_try_xlock
,
sx_sunlock
,
sx_xunlock
,
sx_unlock
,
sx_try_upgrade
,
sx_downgrade
,
sx_sleep
,
sx_xholder
,
sx_xlocked
,
sx_assert
,
SX_SYSINIT
—
kernel shared/exclusive lock
SYNOPSIS¶
#include
<sys/param.h>
#include
<sys/lock.h>
#include
<sys/sx.h>
void
sx_init
(struct
sx *sx, const
char *description);
void
sx_init_flags
(struct
sx *sx, const
char *description,
int opts);
void
sx_destroy
(struct
sx *sx);
void
sx_slock
(struct
sx *sx);
void
sx_xlock
(struct
sx *sx);
int
sx_slock_sig
(struct
sx *sx);
int
sx_xlock_sig
(struct
sx *sx);
int
sx_try_slock
(struct
sx *sx);
int
sx_try_xlock
(struct
sx *sx);
void
sx_sunlock
(struct
sx *sx);
void
sx_xunlock
(struct
sx *sx);
void
sx_unlock
(struct
sx *sx);
int
sx_try_upgrade
(struct
sx *sx);
void
sx_downgrade
(struct
sx *sx);
int
sx_sleep
(void
*chan, struct sx
*sx, int
priority, const
char *wmesg, int
timo);
struct thread *
sx_xholder
(struct
sx *sx);
int
sx_xlocked
(const
struct sx *sx);
options INVARIANTS
options INVARIANT_SUPPORT
void
sx_assert
(const
struct sx *sx,
int what);
#include
<sys/kernel.h>
SX_SYSINIT
(name,
struct sx *sx,
const char
*description);
DESCRIPTION¶
Shared/exclusive locks are used to protect data that are read far more often than they are written. Shared/exclusive locks do not implement priority propagation like mutexes and reader/writer locks to prevent priority inversions, so shared/exclusive locks should be used prudently. Shared/exclusive locks are created with eithersx_init
() or
sx_init_flags
() where
sx is a pointer to space for a
struct sx, and
description is a pointer to a null-terminated
character string that describes the shared/exclusive lock. The
opts argument to
sx_init_flags
() specifies a set of optional
flags to alter the behavior of sx. It
contains one or more of the following flags:
SX_NOADAPTIVE
- If the kernel is not compiled with
options NO_ADAPTIVE_SX
, then lock operations for sx will spin instead of sleeping while an exclusive lock holder is executing on another CPU. SX_DUPOK
- Witness should not log messages about duplicate locks being acquired.
SX_NOWITNESS
- Instruct witness(4) to ignore this lock.
SX_NOPROFILE
- Do not profile this lock.
SX_RECURSE
- Allow threads to recursively acquire exclusive locks for sx.
SX_QUIET
- Do not log any operations for this lock via ktr(4).
sx_destroy
(). The lock
sx must not be locked by any thread when it
is destroyed.
Threads acquire and release a shared lock by calling
sx_slock
(),
sx_slock_sig
() or
sx_try_slock
() and
sx_sunlock
() or
sx_unlock
(). Threads acquire and release an
exclusive lock by calling sx_xlock
(),
sx_xlock_sig
() or
sx_try_xlock
() and
sx_xunlock
() or
sx_unlock
(). A thread can attempt to
upgrade a currently held shared lock to an exclusive lock by calling
sx_try_upgrade
(). A thread that has an
exclusive lock can downgrade it to a shared lock by calling
sx_downgrade
().
sx_try_slock
() and
sx_try_xlock
() will return 0 if the
shared/exclusive lock cannot be acquired immediately; otherwise the
shared/exclusive lock will be acquired and a non-zero value will be returned.
sx_try_upgrade
() will return 0 if the shared
lock cannot be upgraded to an exclusive lock immediately; otherwise the
exclusive lock will be acquired and a non-zero value will be returned.
sx_slock_sig
() and
sx_xlock_sig
() do the same as their normal
versions but performing an interruptible sleep. They return a non-zero value
if the sleep has been interrupted by a signal or an interrupt, otherwise 0.
A thread can atomically release a shared/exclusive lock while waiting for an
event by calling sx_sleep
(). For more
details on the parameters to this function, see
sleep(9).
When compiled with options INVARIANTS
and
options INVARIANT_SUPPORT
, the
sx_assert
() function tests
sx for the assertions specified in
what, and panics if they are not met. One of
the following assertions must be specified:
SA_LOCKED
- Assert that the current thread has either a shared or an exclusive lock on the sx lock pointed to by the first argument.
SA_SLOCKED
- Assert that the current thread has a shared lock on the sx lock pointed to by the first argument.
SA_XLOCKED
- Assert that the current thread has an exclusive lock on the sx lock pointed to by the first argument.
SA_UNLOCKED
- Assert that the current thread has no lock on the sx lock pointed to by the first argument.
SA_LOCKED
,
SA_SLOCKED
, or
SA_XLOCKED
assertion:
SA_RECURSED
- Assert that the current thread has a recursed lock on sx.
SA_NOTRECURSED
- Assert that the current thread does not have a recursed lock on sx.
sx_xholder
() will return a pointer to the
thread which currently holds an exclusive lock on
sx. If no thread holds an exclusive lock on
sx, then
NULL
is returned instead.
sx_xlocked
() will return non-zero if the
current thread holds the exclusive lock; otherwise, it will return zero.
For ease of programming, sx_unlock
() is
provided as a macro frontend to the respective functions,
sx_sunlock
() and
sx_xunlock
(). Algorithms that are aware of
what state the lock is in should use either of the two specific functions for
a minor performance benefit.
The SX_SYSINIT
() macro is used to generate a
call to the sx_sysinit
() routine at system
startup in order to initialize a given sx
lock. The parameters are the same as
sx_init
() but with an additional argument,
name, that is used in generating unique
variable names for the related structures associated with the lock and the
sysinit routine.
A thread may not hold both a shared lock and an exclusive lock on the same lock
simultaneously; attempting to do so will result in deadlock.
CONTEXT¶
A thread may hold a shared or exclusive lock on ansx
lock while sleeping. As a result, an
sx
lock may not be acquired while holding a
mutex. Otherwise, if one thread slept while holding an
sx
lock while another thread blocked on the
same sx
lock after acquiring a mutex, then
the second thread would effectively end up sleeping while holding a mutex,
which is not allowed.
SEE ALSO¶
locking(9), lock(9), mutex(9), panic(9), rwlock(9), sema(9)BUGS¶
Currently there is no way to assert that a lock is not held. This is not possible in the non-WITNESS
case
for asserting that this thread does not hold a shared lock. In the
non-WITNESS
case,
the SA_LOCKED
and
SA_SLOCKED
assertions merely check that
some thread holds a shared lock. They do not ensure that the current thread
holds a shared lock.November 16, 2011 | Debian |