mutex(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