mutex_destroy(9F)
NAME
mutex, mutex_enter, mutex_exit, mutex_init, mutex_destroy,
mutex_owned, mutex_tryenter - mutual exclusion lock routines
SYNOPSIS
#include <sys/ksynch.h>
void mutex_init(kmutex_t *mp, char *name, kmutex_type_t
type, void *arg);
void mutex_destroy(kmutex_t *mp);
void mutex_enter(kmutex_t *mp);
void mutex_exit(kmutex_t *mp);
int mutex_owned(kmutex_t *mp);
int mutex_tryenter(kmutex_t *mp);
INTERFACE LEVEL
Solaris DDI specific (Solaris DDI).
PARAMETERS
mp Pointer to a kernel mutex lock (kmutex_t).
name Descriptive string. This is obsolete and should be
NULL. (Non-NULL strings are legal, but they are a
waste of kernel memory.)
type Type of mutex lock.
arg Type-specific argument for initialization routine.
DESCRIPTION
A mutex enforces a policy of mutual exclusion. Only one
thread at a time may hold a particular mutex. Threads try-
ing to lock a held mutex will block until the mutex is
unlocked.
Mutexes are strictly bracketing and may not be recursively
locked, meaning that mutexes should be exited in the oppo-
site order they were entered, and cannot be reentered before
exiting.
mutex_init() initializes a mutex. It is an error to initial-
ize a mutex more than once. The type argument should be set
to MUTEX_DRIVER.
arg provides type-specific information for a given variant
type of mutex. When mutex_init() is called for driver
mutexes, if the mutex is used by the interrupt handler, the
arg should be the ddi_iblock_cookie returned from
ddi_get_iblock_cookie(9F) or ddi_get_soft_iblock_cookie(9F).
Note that arg should be the value of the iblock cookie
casted to (void *), not the address of the cookie. The argu-
ments passed to ddi_get_iblock_cookie(9F) and
ddi_get_soft_iblock_cookie(9F), on the other hand, are the
addresses of the cookie. If the mutex is never used inside
an interrupt handler, the argument should be NULL.
mutex_enter() is used to acquire a mutex. If the mutex is
already held, then the caller blocks. After returning, the
calling thread is the owner of the mutex. If the mutex is
already held by the calling thread, a panic ensues.
mutex_owned() should only be used in ASSERT() and may be
enforced by not being defined unless the preprocessor symbol
DEBUG is defined. Its return value is non-zero if the
current thread (or, if that cannot be determined, at least
some thread) holds the mutex pointed to by mp.
mutex_tryenter() is very similar to mutex_enter() except
that it doesn't block when the mutex is already held.
mutex_tryenter() returns non-zero when it acquired the mutex
and 0 when the mutex is already held.
mutex_exit() releases a mutex and will unblock another
thread if any are blocked on the mutex.
mutex_destroy() releases any resources that might have been
allocated by mutex_init(). mutex_destroy() must be called
before freeing the memory containing the mutex, and should
be called with the mutex unheld (not owned by any thread).
The caller must be sure that no other thread attempts to use
the mutex.
RETURN VALUES
mutex_tryenter() returns non-zero on success and zero of
failure.
mutex_owned() returns non-zero if the calling thread
currently holds the mutex pointed to by mp, or when that
cannot be determined, if any thread holds the mutex.
mutex_owned() returns zero.
CONTEXT
These functions can be called from user, kernel, or high-
level interrupt context, except for mutex_init() and
mutex_destroy(), which can be called from user or kernel
context only.
EXAMPLES
Example 1: Initializing a Mutex
A driver might do this to initialize a mutex that is part of
its unit structure and used in its interrupt routine:
ddi_get_iblock_cookie(dip, 0, &iblock);
mutex_init(&un->un_lock, NULL, MUTEX_DRIVER,
(void *)iblock);
ddi_add_intr(dip, 0, NULL, &dev_cookie, xxintr,
(caddr_t)un);
Example 2: Calling a Routine with a Lock
A routine that expects to be called with a certain lock held
might have the following ASSERT:
xxstart(struct xxunit *un)
{
ASSERT(mutex_owned(&un->un_lock));
...
SEE ALSO
lockstat(1M), Intro(9F), condvar(9F), ddi_add_intr(9F),
ddi_get_iblock_cookie(9F), ddi_get_soft_iblock_cookie(9F),
rwlock(9F), semaphore(9F)
Writing Device Drivers
NOTES
Compiling with _LOCKTEST or _MPSTATS defined has no effect.
To gather lock statistics, see lockstat(1M).
To write scalable, responsive drivers that do not hang,
panic or deadlock the system, follow these guidelines:
Never return from a driver entry point with a
mutex held.
Never hold a mutex when calling a service that may
block, for example kmem_alloc(9F) with KM_SLEEP or
delay(9F).
Always acquire mutexes in a consistent order. If
a critical section acquires mutex A followed by B,
and elsewhere in the driver mutex B is acquired
before A, the driver can deadlock with one thread
holding A and waiting for B and another thread
holding B while waiting for A.
Always use a mutex to enforce exclusive access to
data, not instruction paths.
Acquiring a lock in user context that is also
acquired in interrupt context means that, as long
as that lock is held, the driver instance holding
the lock is subject to all the rules and limita-
tions of interrupt context.
In most cases, a mutex can and should be acquired
and released within the same function.
Liberal use of debugging aids like
ASSERT(mutex_owned(&mutex)) can help find callers
of a function which should be holding a mutex but
are not. This means you need to test your driver
compiled with DEBUG.
Do not use a mutex to set driver state. However,
you should use a mutex to protect driver state
data.
Use per-instance and automatic data where possible
to reduce the amount of shared data. Per-instance
data can be protected by a per-instance lock to
improve scalability and reduce contention with
multiple hardware instances.
Avoid global data and global mutexes whenever pos-
sible.
Man(1) output converted with
man2html