other sections
| 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 |