The FreeBSD kernel provides the following seven functions for working with mutexes:
#include <sys/param.h> #include <sys/lock.h> #include <sys/mutex.h> void mtx_init(struct mtx mutex, const char name, const char type, int opts); void mtx_lock(struct mtx mutex); void mtx_lock_spin(struct mtx mutex); int mtx_trylock(struct mtx mutex); void mtx_unlock(struct mtx mutex); void mtx_unlock_spin(struct mtx mutex); void mtx_destroy(struct mtx *mutex);
The mtx_init
function initializes the mutex mutex
. The name
argument is used during debugging to identify mutex
. The type
argument is used during lock-order verification by witness(4)
. If type
is NULL
, name
is used instead.
You’ll typically pass NULL
as type
.
The opts
argument modifies mtx_init
’s behavior. Valid values for opts
are shown in Table 4-1.
Table 4-1. mtx_init Symbolic Constants
Constant | Description |
---|---|
| Initializes |
| Initializes |
| Specifies that |
| Instructs the system to not log the operations done on this lock |
| Causes |
| Causes |
| Instructs the system to not profile this lock |
Threads acquire sleep mutexes by calling mtx_lock
. If another thread is currently holding mutex
, the caller will sleep until mutex
is available.
Threads acquire spin mutexes by calling mtx_lock_spin
. If another thread is currently holding mutex
, the caller will spin until mutex
is available. Note that all interrupts are blocked on the local processor during the spin, and they remain disabled following the acquisition of mutex
.
A thread can recursively acquire mutex
(with no ill effects) if MTX_RECURSE
was passed to opts
. A recursive lock is useful if it’ll be acquired at two or more levels. For example:
static void foo() { ... mtx_lock(&mutex); ... foo(); ... mtx_unlock(&mutex); ... }
By using a recursive lock, lower levels don’t need to check if mutex
has been acquired by a higher level. They can simply acquire and release mutex as needed (McKusick and Neville-Neil, 2005).
I would avoid recursive mutexes. You’ll learn why in Avoid Recursing on Exclusive Locks in Memory Management Routines
The mtx_trylock
function is identical to mtx_lock
except that if another thread is currently holding mutex
, it returns 0
(that is, the caller does not sleep).
Threads release sleep mutexes by calling mtx_unlock
. Note that recursive locks “remember” the number of times they’ve been acquired. Consequently, each successful lock acquisition must have a corresponding lock release.
Threads release spin mutexes by calling mtx_unlock_spin
. The mtx_unlock_spin
function also restores the interrupt state to what it was before mutex
was acquired.
The mtx_destroy
function destroys the mutex mutex
. Note that mutex
can be held when it is destroyed. However, mutex cannot be held recursively orhave other threads waiting for it when it is destroyed or else the kernel will panic (McKusick and Neville-Neil, 2005).
18.227.190.93