mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-29 12:03:03 +00:00
450 lines
13 KiB
Groff
450 lines
13 KiB
Groff
.\"
|
|
.\" Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. Berkeley Software Design Inc's name may not be used to endorse or
|
|
.\" promote products derived from this software without specific prior
|
|
.\" written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.\" from BSDI $Id: mutex.4,v 1.1.2.3 1998/04/27 22:53:13 ewv Exp $
|
|
.\" $FreeBSD$
|
|
.\"
|
|
.Dd April 20, 1998
|
|
.Dt MUTEX 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm mutex ,
|
|
.Nm mtx_init ,
|
|
.Nm mtx_lock ,
|
|
.Nm mtx_lock_spin ,
|
|
.Nm mtx_lock_flags ,
|
|
.Nm mtx_lock_spin_flags ,
|
|
.Nm mtx_trylock ,
|
|
.Nm mtx_trylock_flags ,
|
|
.Nm mtx_unlock ,
|
|
.Nm mtx_unlock_spin ,
|
|
.Nm mtx_unlock_flags ,
|
|
.Nm mtx_unlock_spin_flags ,
|
|
.Nm mtx_destroy ,
|
|
.Nm mtx_owned ,
|
|
.Nm mtx_recursed ,
|
|
.Nm mtx_assert
|
|
.Nd kernel synchronization primitives
|
|
.Sh SYNOPSIS
|
|
.Fd #include <sys/mutex.h>
|
|
.Ft int
|
|
.Fn mtx_init "struct mtx *mutex" "char *name" "int opts"
|
|
.Ft void
|
|
.Fn mtx_lock "struct mtx *mutex"
|
|
.Ft void
|
|
.Fn mtx_lock_spin "struct mtx *mutex"
|
|
.Ft void
|
|
.Fn mtx_lock_flags "struct mtx *mutex" "int flags"
|
|
.Ft void
|
|
.Fn mtx_lock_spin_flags "struct mtx *mutex" "int flags"
|
|
.Ft int
|
|
.Fn mtx_trylock "struct mtx *mutex"
|
|
.Ft int
|
|
.Fn mtx_trylock_flags "struct mtx *mutex" "int flags"
|
|
.Ft void
|
|
.Fn mtx_unlock "struct mtx *mutex"
|
|
.Ft void
|
|
.Fn mtx_unlock_spin "struct mtx *mutex"
|
|
.Ft void
|
|
.Fn mtx_unlock_flags "struct mtx *mutex" "int flags"
|
|
.Ft void
|
|
.Fn mtx_unlock_spin_flags "struct mtx *mutex" "int flags"
|
|
.Ft void
|
|
.Fn mtx_destroy "struct mtx *mutex"
|
|
.Ft int
|
|
.Fn mtx_owned "struct mtx *mutex"
|
|
.Ft int
|
|
.Fn mtx_recursed "struct mtx *mutex"
|
|
.Ft void
|
|
.Fn mtx_assert "struct mtx *mutex" "int what"
|
|
.Sh DESCRIPTION
|
|
Mutexes are the most basic and primary method of process synchronization.
|
|
The major design considerations for mutexes are:
|
|
.Bl -enum
|
|
.It
|
|
Acquiring and releasing uncontested mutexes should be as cheap
|
|
as possible.
|
|
.It
|
|
They must have the information and storage space to support
|
|
priority propagation.
|
|
.It
|
|
A process must be able to recursively acquire a mutex,
|
|
provided that the mutex is initialized to support recursion.
|
|
.El
|
|
.Pp
|
|
There are currently two flavors of mutexes, those that context switch
|
|
when they block and those that do not.
|
|
.Pp
|
|
By default,
|
|
.Dv MTX_DEF
|
|
mutexes will context switch when they are already held.
|
|
As a machine dependent optimization they may spin for some amount
|
|
of time before context switching.
|
|
It is important to remember that since a process may be preempted at any time,
|
|
the possible context switch introduced by acquiring a mutex is guaranteed
|
|
to not break anything that isn't already broken.
|
|
.Pp
|
|
Mutexes which do not context switch are
|
|
.Dv MTX_SPIN
|
|
mutexes.
|
|
These should only be used to protect data shared with any devices that
|
|
require non-preemptive interrupts, and low level scheduling code.
|
|
In most/all architectures both acquiring and releasing of a
|
|
uncontested spin mutex is more expensive than the same operation
|
|
on a non spin mutex.
|
|
In order to protect an interrupt service routine from blocking
|
|
against itself all interrupts are blocked on a processor while
|
|
holding a spin lock.
|
|
It is permissible to hold multiple spin mutexes.
|
|
In this case it is a required that they be released in the opposite
|
|
order to that which they were acquired.
|
|
.Pp
|
|
Once a spin mutex has been acquired it is not permissible to acquire a
|
|
blocking mutex.
|
|
.Pp
|
|
The storage needed to implement a mutex is provided by a
|
|
.Dv struct mtx .
|
|
In general this should be treated as an opaque object and
|
|
referenced only with the mutex primitives.
|
|
.Pp
|
|
The
|
|
.Fn mtx_init
|
|
function must be used to initialize a mutex
|
|
before it can be passed to
|
|
.Fn mtx_lock .
|
|
The
|
|
.Ar name
|
|
argument is used by the witness code
|
|
to classify a mutex when doing checks of lock ordering.
|
|
The pointer passed in as the
|
|
.Ar name
|
|
is saved rather than the data it points to.
|
|
The data pointed to must remain stable
|
|
until the mutex is destroyed.
|
|
The
|
|
.Ar opts
|
|
argument is used to set the type of mutex. It may contain either
|
|
.Dv MTX_DEF
|
|
or
|
|
.Dv MTX_SPIN
|
|
but not both. Optionally, it may also contain the
|
|
.Dv MTX_RECURSE
|
|
bit, which signifies that the mutex will be allowed to recurse.
|
|
It is not permissible to pass the same
|
|
.Ar mutex
|
|
to
|
|
.Fn mtx_init
|
|
multiple times without intervening calls to
|
|
.Fn mtx_destroy .
|
|
.Pp
|
|
The
|
|
.Fn mtx_lock
|
|
function acquires a
|
|
.Dv MTX_DEF
|
|
mutual exclusion lock
|
|
on behalf of the currently running kernel thread.
|
|
If another kernel thread is holding the mutex,
|
|
the caller will be disconnected from the CPU
|
|
until the mutex is available
|
|
(i.e. it will sleep).
|
|
.Pp
|
|
The
|
|
.Fn mtx_lock_spin
|
|
function acquires a
|
|
.Dv MTX_SPIN
|
|
mutual exclusion lock
|
|
on behalf of the currently running kernel thread.
|
|
If another kernel thread is holding the mutex,
|
|
the caller will spin until the mutex becomes available.
|
|
Interrupts are disabled during the spin and remain disabled
|
|
following the acquiring of the lock.
|
|
.Pp
|
|
It is possible for the same thread to recursively acquire a mutex
|
|
with no ill effects, provided that the
|
|
.Dv MTX_RECURSE
|
|
bit was passed to
|
|
.Fn mtx_init
|
|
during the initialization of the mutex.
|
|
.Pp
|
|
The
|
|
.Fn mtx_lock_flags
|
|
and
|
|
.Fn mtx_lock_spin_flags
|
|
functions acquire a
|
|
.Dv MTX_DEF
|
|
or
|
|
.Dv MTX_SPIN
|
|
lock, respectively, and also accept a
|
|
.Ar flags
|
|
argument.
|
|
In both cases, the only flag presently available for lock acquires is
|
|
.Dv MTX_QUIET .
|
|
If the
|
|
.Dv MTX_QUIET
|
|
bit is turned on in the
|
|
.Ar flags
|
|
argument, then if KTR_LOCK tracing is being done,
|
|
it will be silenced during the lock acquire.
|
|
.Pp
|
|
The
|
|
.Fn mtx_trylock
|
|
function is used to acquire exclusive access
|
|
to those objects protected by the mutex
|
|
pointed to by
|
|
.Ar mutex .
|
|
If the mutex can not be immediately acquired
|
|
.Fn mtx_try_enter
|
|
will return 0,
|
|
otherwise the mutex will be acquired
|
|
and a non-zero value will be returned.
|
|
.Pp
|
|
The
|
|
.Fn mtx_trylock_flags
|
|
function has the same behavior as
|
|
.Fn mtx_trylock
|
|
but should be used when the caller desires to pass in a
|
|
.Ar flags
|
|
value. Presently, the only valid value in the
|
|
.Fn mtx_trylock
|
|
case is
|
|
.Dv MTX_QUIET ,
|
|
and its effects are identical to those described for
|
|
.Fn mtx_lock
|
|
and
|
|
.Fn mtx_lock_spin
|
|
above.
|
|
.Pp
|
|
The
|
|
.Fn mtx_unlock
|
|
function releases a
|
|
.Dv MTX_DEF
|
|
mutual exclusion lock;
|
|
if a higher priority thread is waiting for the mutex,
|
|
the releasing thread will be disconnected
|
|
to allow the higher priority thread to acquire the mutex and run.
|
|
.Pp
|
|
The
|
|
.Fn mtx_unlock_spin
|
|
function releases a
|
|
.Dv MTX_SPIN
|
|
mutual exclusion lock;
|
|
interrupt state prior to the acquiring of the lock is restored.
|
|
.Pp
|
|
The
|
|
.Fn mtx_unlock_flags
|
|
and
|
|
.Fn mtx_unlock_spin_flags
|
|
functions behave in exactly the same way as do the standard mutex
|
|
unlock routines above, while also allowing a
|
|
.Ar flags
|
|
argument which may only be
|
|
.Dv MTX_QUIET
|
|
in the
|
|
.Fn mtx_unlock_spin_flags
|
|
case, and may be one or more of
|
|
.Dv MTX_QUIET
|
|
and
|
|
.Dv MTX_NOSWITCH
|
|
in the
|
|
.Fn mtx_unlock_flags
|
|
case. The behavior of
|
|
.Dv MTX_QUIET
|
|
is identical to its behavior in the mutex lock routines.
|
|
The
|
|
.Dv MTX_NOSWITCH
|
|
flag bit signifies,
|
|
for a
|
|
.Dv MTX_DEF
|
|
mutex only,
|
|
that the releasing thread is not to be disconnected from the CPU following
|
|
the release of the mutex.
|
|
.Pp
|
|
The
|
|
.Fn mtx_destroy
|
|
function is used to destroy
|
|
.Ar mutex
|
|
so the data associated with it may be freed
|
|
or otherwise overwritten.
|
|
Any mutex which is destroyed
|
|
must previously have been initialized with
|
|
.Fn mtx_init .
|
|
It is permissible to have a single hold count
|
|
on a mutex when it is destroyed.
|
|
It is not permissible to hold the mutex recursively,
|
|
or have another process blocked on the mutex
|
|
when it is destroyed.
|
|
.Pp
|
|
The
|
|
.Fn mtx_owned
|
|
function returns non-zero
|
|
if the current process holds
|
|
.Ar mutex .
|
|
If the current process does not hold
|
|
.Ar mutex
|
|
zero is returned.
|
|
.Pp
|
|
The
|
|
.Fn mtx_recursed
|
|
function returns non-zero if the
|
|
.Ar mutex
|
|
is recursed.
|
|
This check should only be made if the running thread already owns
|
|
.Ar mutex .
|
|
.Pp
|
|
The
|
|
.Fn mtx_assert
|
|
function allows assertions to be made about
|
|
.Ar mutex .
|
|
If the assertions are not true and the kernel is compiled with
|
|
.Dv INVARIANTS
|
|
then the kernel will panic.
|
|
Currently the following assertions are supported:
|
|
.Bl -tag -width MA_NOTRECURSED
|
|
.It Dv MA_OWNED
|
|
Assert that the current thread
|
|
holds the mutex
|
|
pointed to by the first argument.
|
|
.It Dv MA_NOTOWNED
|
|
Assert that the current thread
|
|
does not hold the mutex
|
|
pointed to by the first argument.
|
|
.It Dv MA_RECURSED
|
|
Assert that the current thread has recursed on the mutex
|
|
pointed to by the first argument.
|
|
This assertion is only valid in conjuction with
|
|
.Dv MA_OWNED .
|
|
.It Dv MA_NOTRECURSED
|
|
Assert that the current thread has not recursed on the mutex
|
|
pointed to by the first argument.
|
|
This assertion is only valid in conjuction with
|
|
.Dv MA_OWNED .
|
|
.El
|
|
.Ss The Default Mutex Type
|
|
Most kernel code should use the default lock type,
|
|
.Dv MTX_DEF ;
|
|
the default lock type will allow the thread
|
|
to be disconnected from the CPU
|
|
if it cannot get the lock.
|
|
The machine dependent implementation
|
|
may treat the lock as a short term spin lock
|
|
under some circumstances.
|
|
However, it is always safe to use these forms of locks
|
|
in an interrupt thread
|
|
without fear of deadlock
|
|
against an interrupted thread on the same CPU.
|
|
.Ss The Spin Mutex Type
|
|
A
|
|
.Dv MTX_SPIN
|
|
mutex will not relinquish the CPU
|
|
when it cannot immediately get the requested lock,
|
|
but will loop, waiting for the mutex to be released by another CPU.
|
|
This could result in deadlock
|
|
if a thread interrupted the thread which held a mutex
|
|
and then tried to acquire the mutex;
|
|
for this reason spin locks will disable all interrupts
|
|
(on the local CPU only).
|
|
.Pp
|
|
Spin locks are fairly specialized locks
|
|
that are intended to be held for very short periods of time;
|
|
their primary purpose is to protect portions of the code
|
|
that implement default (i.e. sleep) locks.
|
|
.Ss Initialization Options
|
|
The options passed in the
|
|
.Ar opts
|
|
argument of
|
|
.Fn mtx_init
|
|
specify the mutex type.
|
|
The possibilities are:
|
|
.Bl -tag -width MTX_RECURSE
|
|
.It Dv MTX_DEF
|
|
Default lock type;
|
|
will always allow the current thread to be suspended
|
|
to avoid deadlock conditions against interrupt threads.
|
|
The machine dependent implementation of this lock type
|
|
may spin for a while before suspending the current thread.
|
|
If this flag is specified, clearly
|
|
.Dv MTX_SPIN
|
|
must NOT be specified.
|
|
.It Dv MTX_SPIN
|
|
Spin lock type;
|
|
will never relinquish the CPU.
|
|
All interrupts are disabled on the local CPU
|
|
while any spin lock is held.
|
|
.It Dv MTX_RECURSE
|
|
Recursion option bit;
|
|
specifies that the initialized mutex is allowed to recurse.
|
|
This bit must be present if the mutex is going to be permitted to recurse.
|
|
It must always be accompanied by either
|
|
.Dv MTX_DEF
|
|
or
|
|
.Dv MTX_SPIN
|
|
but not both.
|
|
.El
|
|
.Ss Lock and Unlock Flags
|
|
The flags passed to the
|
|
.Fn mtx_lock_flags ,
|
|
.Fn mtx_lock_spin_flags ,
|
|
.Fn mtx_unlock_flags ,
|
|
and
|
|
.Fn mtx_unlock_spin_flags
|
|
functions provide some basic options to the caller,
|
|
and are often used only under special circumstances to modify lock or
|
|
unlock behavior. Standard locking and unlocking should be performed with the
|
|
.Fn mtx_lock ,
|
|
.Fn mtx_lock_spin ,
|
|
.Fn mtx_unlock ,
|
|
and
|
|
.Fn mtx_unlock_spin
|
|
functions. If one of these flags is required then, and only then,
|
|
should the corresponding flags-accepting routines be used.
|
|
.Pp
|
|
Options that modify mutex behavior:
|
|
.Bl -tag -width MTX_NOSWITCH
|
|
.It Dv MTX_NOSWITCH
|
|
When releasing a
|
|
.Dv MTX_DEF
|
|
mutex,
|
|
this flag prevents a thread switch that might occur
|
|
if another higher priority thread was waiting for the mutex.
|
|
This may cause priority inversion and should be used carefully.
|
|
This flag can only be passed to
|
|
.Fn mtx_unlock_flags .
|
|
.Pp
|
|
This flag is used internally by the lock code.
|
|
It should not be used in general kernel code
|
|
and is documented here for completeness only.
|
|
.It Dv MTX_QUIET
|
|
This option is used to quiet logging messages during mutex operations.
|
|
This can be used to trim superfluous logging messages for debugging purposes.
|
|
.El
|
|
.Sh HISTORY
|
|
These
|
|
functions appeared in
|
|
.Tn BSD/OS
|
|
4.1 and
|
|
.Fx 5.0 .
|