NAME
spin_init
,
spin_lock
, spin_lock_quick
,
spin_trylock
, spin_uninit
,
spin_unlock
,
spin_unlock_quick
—
core spinlocks
SYNOPSIS
#include
<sys/spinlock.h>
#include <sys/spinlock2.h>
void
spin_init
(struct
spinlock *mtx, const char
*descr);
void
spin_uninit
(struct
spinlock *mtx);
void
spin_lock
(struct
spinlock *mtx);
void
spin_lock_quick
(globaldata_t
gd, struct spinlock
*mtx);
boolean_t
spin_trylock
(struct
spinlock *mtx);
void
spin_unlock
(struct
spinlock *mtx);
void
spin_unlock_quick
(globaldata_t
gd, struct spinlock
*mtx);
DESCRIPTION
The spinlock structure and call API are defined in the<sys/spinlock.h>
and
<sys/spinlock2.h>
header
files, respectively.
The
spin_init
()
function initializes a new spinlock structure for use.
An initializer macro, SPINLOCK_INITIALIZER
, is
provided as well, taking the same arguments as
spin_init
(). The structure is cleaned up with
spin_uninit
()
when it is no longer needed.
The
spin_lock
()
function obtains an exclusive read-write spinlock. A
thread may hold any number of exclusive spinlocks but should always be
mindful of ordering deadlocks. The
spin_trylock
()
function will return TRUE
if the spinlock was
successfully obtained and FALSE
if it wasn't. If you
have the current CPU's globaldata pointer in hand you
can call
spin_lock_quick
(),
but most code will just call the normal version. A spinlock used only for
exclusive access has about the same overhead as a mutex based on a locked
bus cycle.
A previously obtained exclusive spinlock is
released by calling either
spin_unlock
()
or
spin_unlock_quick
().
IMPLEMENTATION NOTES
A thread may not hold any spinlock across a blocking condition or thread switch. LWKT tokens should be used for situations where you want an exclusive run-time lock that will survive a blocking condition or thread switch. Tokens will be automatically unlocked when a thread switches away and relocked when the thread is switched back in. If you want a lock that survives a blocking condition or thread switch without being released, use lockmgr(9) locks or LWKT reader/writer locks.
DragonFly's core spinlocks should only be used around small contained sections of code. For example, to manage a reference count or to implement higher level locking mechanisms. Both the token code and the lockmgr(9) code use exclusive spinlocks internally. Core spinlocks should not be used around large chunks of code.
Holding one or more spinlocks will disable thread preemption by another thread (e.g. preemption by an interrupt thread), and will prevent FAST interrupts or IPIs from running. This means that a FAST interrupt, IPI and any threaded interrupt (which is basically all interrupts except the clock interrupt) will still be scheduled for later execution, but will not be able to preempt the current thread.
A thread may hold any number of exclusive read-write spinlocks.
Spinlocks spin. A thread will not block, switch away, or lose its critical section while obtaining or releasing a spinlock. Spinlocks do not use IPIs or other mechanisms. They are considered to be a very low level mechanism.
If a spinlock can not be obtained after one second a warning will be printed on the console. If a system panic occurs, spinlocks will succeed after one second in order to allow the panic operation to proceed.
If you have a complex structure such as a vnode(9) which contains a token or lockmgr(9) lock, it is legal to directly access the internal spinlock embedded in those structures for other purposes as long as the spinlock is not held when you issue the token or lockmgr(9) operation.
FILES
The uncontended path of the spinlock implementation is in /sys/sys/spinlock2.h. The core of the spinlock implementation is in /sys/kern/kern_spinlock.c.
SEE ALSO
HISTORY
A spinlock
implementation first appeared
in DragonFly 1.3.
AUTHORS
The original spinlock
implementation was
written by Jeffrey M. Hsu and was later extended by
Matthew Dillon. This manual page was written by
Matthew Dillon and Sascha
Wildner.