SPINLOCK(9) | Kernel Developer's Manual | SPINLOCK(9) |
spinlock
,
ke_spinlock_init
,
ke_spinlock_acquire
,
ke_spinlock_acquire_at
,
ke_spinlock_acquire_nospl
,
ke_spinlock_release
,
ke_spinlock_release_nospl
—
spinlock mutual exclusion mechanism
#include
<kdk/kern.h>
void
ke_spinlock_init
(kspinlock_t
*lock);
ipl_t
ke_spinlock_acquire
(kspinlock_t
*lock);
ipl_t
ke_spinlock_acquire_at
(kspinlock_t
*lock, ipl_t
ipl);
void
ke_spinlock_acquire_nospl
(kspinlock_t
*lock);
void
ke_spinlock_release
(kspinlock_t
*lock, ipl_t
ipl);
void
ke_spinlock_release_nospl
(kspinlock_t
*lock);
Spinlocks are a mutual exclusion mechanism used to synchronise shared state such that only one CPU can access it at a time.
The ipl(9) mechanism is closely integrated with spinlocks; spinlocks may only be held at or above DPC level. Consequently it is illegal and impossible to try to sleep while holding a mutex, neither will the current thread be rescheduled. This is how spinlocks synchronise CPUs as opposed to threads as such; in fact, the spinlock interface is implemented purely with IPL raising on uniprocessors.
As they are held at or above DPC level, while holding a spinlock, rcu(9) grace periods remain in effect, DPCs are masked, rescheduling/waiting is prevented, and certain operations forbidden; see ipl(9) for a full account of the restrictions. A particularly salient restriction is that paged memory may not be accessed while holding a spinlock, unless the memory has been locked resident.
Spinlocks are informally associated with a particular IPL, which is the IPL at which the spinlock may be acquired and held. This is usually DPC level, but may be higher, for example, for spinlocks which may be acquired by device interrupt handlers.
Spinlocks cannot be recursively acquired, and as they are held at a high IPL, they are not suitable for long-running operations.
The
ke_spinlock_init
()
function initialises a spinlock and should be called initially;
alternatively, the lock may be statically initialised with the macro
KPINLOCK_INITIALISER
.
The
ke_spinlock_acquire
()
function acquires a spinlock, raising the IPL to DPC level, and returns the
previous IPL, while
ke_spinlock_acquire_at
()
does the same but raises the IPL to the specified level instead of DPC
level, and
ke_spinlock_acquire_nospl
()
acquires a spinlock without raising the IPL - useful for when the IPL is
already at the required level.
The
ke_spinlock_release
()
function releases a spinlock, lowering the IPL to the specified level, which
will usually be the IPL returned by the lock function.
ke_spinlock_release_nospl
()
releases a spinlock without lowering the IPL.
The spinlock functions may be called from any context so long as the IPL is at or below the spinlock's associated IPL.
Spinlocks are implemented inline in kernel/include/kdk/kern.h.
The spinlock
interface has always been in
Keyronex.
October 5, 2024 | Debian |