Mutex Management Routines

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.

Note

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

MTX_DEF

Initializes mutex as a sleep mutex; this bit or MTX_SPIN must be present

MTX_SPIN

Initializes mutex as a spin mutex; this bit or MTX_DEF must be present

MTX_RECURSE

Specifies that mutex is a recursive lock; more on recursive locks later

MTX_QUIET

Instructs the system to not log the operations done on this lock

MTX_NOWITNESS

Causes witness(4) to ignore this lock

MTX_DUPOK

Causes witness(4) to ignore duplicates of this lock

MTX_NOPROFILE

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).

Note

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).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.190.93