274 lines
8.4 KiB
Groff
274 lines
8.4 KiB
Groff
.\" $NetBSD: mutex.9,v 1.9 2007/04/09 13:37:57 ad Exp $
|
|
.\"
|
|
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Andrew Doran.
|
|
.\"
|
|
.\" 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. All advertising materials mentioning features or use of this software
|
|
.\" must display the following acknowledgement:
|
|
.\" This product includes software developed by the NetBSD
|
|
.\" Foundation, Inc. and its contributors.
|
|
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
.\" contributors may be used to endorse or promote products derived
|
|
.\" from this software without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``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 THE FOUNDATION OR CONTRIBUTORS
|
|
.\" 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.
|
|
.\"
|
|
.Dd April 9, 2007
|
|
.Dt MUTEX 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm mutex ,
|
|
.Nm mutex_init ,
|
|
.Nm mutex_destroy ,
|
|
.Nm mutex_enter ,
|
|
.Nm mutex_exit ,
|
|
.Nm mutex_tryenter ,
|
|
.Nm mutex_owned
|
|
.Nd mutual exclusion primitives
|
|
.Sh SYNOPSIS
|
|
.In sys/mutex.h
|
|
.Ft void
|
|
.Fn mutex_init "kmutex_t *mtx" "kmutex_type_t type" "int ipl"
|
|
.Ft void
|
|
.Fn mutex_destroy "kmutex_t *mtx"
|
|
.Ft void
|
|
.Fn mutex_enter "kmutex_t *mtx"
|
|
.Ft void
|
|
.Fn mutex_exit "kmutex_t *mtx"
|
|
.Ft int
|
|
.Fn mutex_tryenter "kmutex_t *mtx"
|
|
.Ft int
|
|
.Fn mutex_owned "kmutex_t *mtx"
|
|
.Pp
|
|
.Cd "options DIAGNOSTIC"
|
|
.Cd "options LOCKDEBUG"
|
|
.Sh DESCRIPTION
|
|
Mutexes are used in the kernel to implement mutual exclusion among LWPs
|
|
(lightweight processes) and interrupt handlers.
|
|
.Pp
|
|
The
|
|
.Vt kmutex_t
|
|
type provides storage for the mutex object.
|
|
This should be treated as an opaque object and not examined directly by
|
|
consumers.
|
|
.Pp
|
|
Mutexes replace the
|
|
.Xr spl 9
|
|
system traditionally used to provide synchronization between interrupt
|
|
handlers and LWPs, and in combination with reader / writer locks replace
|
|
the
|
|
.Xr lockmgr 9
|
|
facility.
|
|
.Sh OPTIONS
|
|
.Bl -tag -width abcd
|
|
.It Cd "options DIAGNOSTIC"
|
|
.Pp
|
|
Kernels compiled with the
|
|
.Dv DIAGNOSTIC
|
|
option perform basic sanity checks on mutex operations.
|
|
.It Cd "options LOCKDEBUG"
|
|
.Pp
|
|
Kernels compiled with the
|
|
.Dv LOCKDEBUG
|
|
option perform potentially CPU intensive sanity checks
|
|
on mutex operations.
|
|
.El
|
|
.Sh FUNCTIONS
|
|
.Bl -tag -width abcd
|
|
.It Fn mutex_init "mtx" "type" "ipl"
|
|
.Pp
|
|
Dynamically initialize a mutex for use.
|
|
No other operations can be performed on a mutex until it has been initialized.
|
|
.Fn mutex_init
|
|
may block in order to allocate memory.
|
|
.Pp
|
|
The
|
|
.Fa type
|
|
argument specifies the kind of mutex to be initialized, controlling the
|
|
behaviour of the mutex.
|
|
Once initialized, all types of mutex are manipulated using the same interface.
|
|
Valid types are as follows:
|
|
.Bl -tag -width cdoscdosrunru
|
|
.It Dv MUTEX_DEFAULT
|
|
Requests an adaptive mutex.
|
|
Adaptive mutexes provide mutual exclusion between LWPs.
|
|
.Pp
|
|
When initializing an adaptive mutex,
|
|
.Dv IPL_NONE
|
|
must be specified as the
|
|
.Fa ipl
|
|
argument.
|
|
Adaptive mutexes should not be acquired from an interrupt handler.
|
|
.Pp
|
|
An LWP may either sleep or busy-wait when attempting to acquire
|
|
an adaptive mutex that is already held.
|
|
.It Dv MUTEX_SPIN
|
|
Requests a spin mutex.
|
|
Spin mutexes provide mutual exclusion between LWPs, and between LWPs
|
|
and interrupt handlers.
|
|
.Pp
|
|
When initializing a spin mutex, the
|
|
.Fa ipl
|
|
argument is used to pass an system interrupt priority level (SPL)
|
|
that will block all interrupt handlers that may try to acquire the mutex.
|
|
.Pp
|
|
LWPs that own spin mutexes may not sleep, and therefore must not
|
|
try to acquire adaptive mutexes or other sleep locks.
|
|
.Pp
|
|
A processor will always busy-wait when attempting to acquire
|
|
a spin mutex that is already held.
|
|
.El
|
|
.Pp
|
|
In general, device drivers should not directly request spin or adaptive
|
|
mutexes.
|
|
For device drivers a third type of mutex is provided:
|
|
.Bl -tag -width cdoscdosrunru
|
|
.It Dv MUTEX_DRIVER
|
|
Requests a device driver mutex.
|
|
.Pp
|
|
The
|
|
.Fa ipl
|
|
argument is used to determine whether a spin or adaptive mutex is
|
|
returned, depending on how interrupt handling is implemented by
|
|
the machine architecture.
|
|
.Pp
|
|
If
|
|
.Dv IPL_NONE
|
|
is specified,
|
|
.Fn mutex_init
|
|
is guaranteed to return an adaptive mutex that can be used to
|
|
provide mutual exclusion for device driver code that does not
|
|
run from an interrupt handler.
|
|
Other levels return mutexes that can be used to synchronize
|
|
with interrupt handlers.
|
|
For example, to request a mutex for synchronizing with network
|
|
interrupt handlers, specify
|
|
.Dv IPL_NET .
|
|
Beyond this, device drivers should not make assumptions about
|
|
the type of mutex returned.
|
|
.El
|
|
.It Fn mutex_destroy "mtx"
|
|
.Pp
|
|
Release resources used by a mutex.
|
|
The mutex may not be used after it has been destroyed.
|
|
.Fn mutex_destroy
|
|
may block in order to free memory.
|
|
.It Fn mutex_enter "mtx"
|
|
.Pp
|
|
Acquire a mutex.
|
|
If the mutex is already held, the caller will block and not return until the
|
|
mutex is acquired.
|
|
.Pp
|
|
Mutexes and other types of locks must always be acquired in a
|
|
consistent order with respect to each other.
|
|
Otherwise, the potential for system deadlock exists.
|
|
.Pp
|
|
Adaptive mutexes and other types of lock that can sleep may
|
|
not be acquired once a spin mutex is held by the caller.
|
|
Note that device driver mutexes at a level other than
|
|
.Dv IPL_NONE
|
|
can be spin mutexes.
|
|
.It Fn mutex_exit "mtx"
|
|
.Pp
|
|
Release a mutex.
|
|
The mutex must have been previously acquired by the caller.
|
|
Mutexes may be released out of order as needed.
|
|
.It Fn mutex_tryenter "mtx"
|
|
.Pp
|
|
Try to acquire a mutex, but do not block if the mutex is already held.
|
|
Returns non-zero if the mutex was acquired, or zero if the mutex was
|
|
already held.
|
|
.Pp
|
|
.Fn mutex_tryenter
|
|
can be used as an optimization when acquiring locks in the the wrong order.
|
|
For example, in a setting where the convention is that
|
|
.Dv first_lock
|
|
must be acquired before
|
|
.Dv second_lock ,
|
|
the following can be used to optimistically lock in reverse order:
|
|
.Bd -literal
|
|
/* We hold second_lock, but not first_lock. */
|
|
KASSERT(mutex_owned(\*[Am]second_lock));
|
|
|
|
if (!mutex_tryenter(\*[Am]first_lock)) {
|
|
/* Failed to get it - lock in the correct order. */
|
|
mutex_exit(\*[Am]second_lock);
|
|
mutex_enter(\*[Am]first_lock);
|
|
mutex_enter(\*[Am]second_lock);
|
|
|
|
/*
|
|
* We may need to recheck any conditions the code
|
|
* path depends on, as we released second_lock
|
|
* briefly.
|
|
*/
|
|
}
|
|
.Ed
|
|
.It Fn mutex_owned "mtx"
|
|
.Pp
|
|
For adaptive mutexes, return non-zero if the current LWP holds the mutex.
|
|
For spin mutexes, return non-zero if the mutex is held, potentially by the
|
|
current processor.
|
|
Otherwise, return zero.
|
|
.Pp
|
|
.Fn mutex_owned
|
|
is provided for making diagnostic checks to verify that a lock is held.
|
|
For example:
|
|
.Bd -literal
|
|
KASSERT(mutex_owned(\*[Am]driver_lock));
|
|
.Ed
|
|
.Pp
|
|
It should not be used to make locking decisions at run time, or to
|
|
verify that a lock is unheld.
|
|
.El
|
|
.Sh CODE REFERENCES
|
|
This section describes places within the
|
|
.Nx
|
|
source tree where code implementing mutexes can be found.
|
|
All pathnames are relative to
|
|
.Pa /usr/src .
|
|
.Pp
|
|
The core of the mutex implementation is in
|
|
.Pa sys/kern/kern_mutex.c .
|
|
.Pp
|
|
The header file
|
|
.Pa sys/sys/mutex.h
|
|
describes the public interface, and interfaces that machine-dependent
|
|
code must provide to support mutexes.
|
|
.Sh SEE ALSO
|
|
.Xr condvar 9 ,
|
|
.Xr mb 9 ,
|
|
.Xr rwlock 9
|
|
.Pp
|
|
.Rs
|
|
.%A Jim Mauro
|
|
.%A Richard McDougall
|
|
.%T Solaris Internals: Core Kernel Architecture ,
|
|
.%I Prentice Hall
|
|
.%D 2001
|
|
.%O ISBN 0-13-022496-0
|
|
.Re
|
|
.Sh HISTORY
|
|
The mutex primitives first appeared in
|
|
.Nx 5.0 .
|