Provided by: manpages-posix-dev_2.16-1_all bug

NAME

       pthread_mutex_destroy, pthread_mutex_init - destroy and initialize a mutex

SYNOPSIS

       #include <pthread.h>

       int pthread_mutex_destroy(pthread_mutex_t *mutex);
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);
       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

DESCRIPTION

       The  pthread_mutex_destroy()  function shall destroy the mutex object referenced by mutex;
       the  mutex  object  becomes,  in  effect,  uninitialized.  An  implementation  may   cause
       pthread_mutex_destroy()  to  set  the  object  referenced  by mutex to an invalid value. A
       destroyed mutex object can be reinitialized using  pthread_mutex_init();  the  results  of
       otherwise referencing the object after it has been destroyed are undefined.

       It  shall be safe to destroy an initialized mutex that is unlocked.  Attempting to destroy
       a locked mutex results in undefined behavior.

       The pthread_mutex_init() function shall initialize the  mutex  referenced  by  mutex  with
       attributes  specified by attr. If attr is NULL, the default mutex attributes are used; the
       effect shall be the same as passing the address of a default mutex attributes object. Upon
       successful initialization, the state of the mutex becomes initialized and unlocked.

       Only  mutex itself may be used for performing synchronization.  The result of referring to
       copies   of   mutex   in   calls   to    pthread_mutex_lock(),    pthread_mutex_trylock(),
       pthread_mutex_unlock(), and pthread_mutex_destroy() is undefined.

       Attempting to initialize an already initialized mutex results in undefined behavior.

       In    cases    where    default    mutex    attributes    are   appropriate,   the   macro
       PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes that are statically allocated.
       The effect shall be equivalent to dynamic initialization by a call to pthread_mutex_init()
       with parameter attr specified as NULL, except that no error checks are performed.

RETURN VALUE

       If successful, the pthread_mutex_destroy() and pthread_mutex_init() functions shall return
       zero; otherwise, an error number shall be returned to indicate the error.

       The  [EBUSY]  and  [EINVAL]  error  checks,  if implemented, act as if they were performed
       immediately at the beginning of processing for the  function  and  shall  cause  an  error
       return prior to modifying the state of the mutex specified by mutex.

ERRORS

       The pthread_mutex_destroy() function may fail if:

       EBUSY  The  implementation  has  detected  an  attempt to destroy the object referenced by
              mutex while it is locked  or  referenced  (for  example,  while  being  used  in  a
              pthread_cond_timedwait() or pthread_cond_wait()) by another thread.

       EINVAL The value specified by mutex is invalid.

       The pthread_mutex_init() function shall fail if:

       EAGAIN The system lacked the necessary resources (other than memory) to initialize another
              mutex.

       ENOMEM Insufficient memory exists to initialize the mutex.

       EPERM  The caller does not have the privilege to perform the operation.

       The pthread_mutex_init() function may fail if:

       EBUSY  The implementation has detected an attempt to reinitialize the object referenced by
              mutex, a previously initialized, but not yet destroyed, mutex.

       EINVAL The value specified by attr is invalid.

       These functions shall not return an error code of [EINTR].

       The following sections are informative.

EXAMPLES

       None.

APPLICATION USAGE

       None.

RATIONALE

   Alternate Implementations Possible
       This  volume  of  IEEE Std 1003.1-2001  supports  several  alternative  implementations of
       mutexes.  An  implementation  may  store  the  lock  directly  in  the  object   of   type
       pthread_mutex_t.   Alternatively,  an  implementation  may  store the lock in the heap and
       merely store a pointer, handle, or unique ID in the mutex  object.  Either  implementation
       has  advantages  or  may  be required on certain hardware configurations. So that portable
       code can be written that is invariant to this choice, this volume of  IEEE Std 1003.1-2001
       does not define assignment or equality for this type, and it uses the term "initialize" to
       reinforce the (more restrictive) notion that the lock may actually  reside  in  the  mutex
       object itself.

       Note  that  this  precludes  an  over-specification  of the type of the mutex or condition
       variable and motivates the opaqueness of the type.

       An implementation is permitted, but not required, to have pthread_mutex_destroy() store an
       illegal  value  into  the mutex.  This may help detect erroneous programs that try to lock
       (or otherwise reference) a mutex that has already been destroyed.

   Tradeoff Between Error Checks and Performance Supported
       Many of the error checks were made optional in order  to  let  implementations  trade  off
       performance  versus  degree  of  error  checking  according to the needs of their specific
       applications and execution environment. As a general rule, errors or conditions caused  by
       the  system (such as insufficient memory) always need to be reported, but errors due to an
       erroneously coded application (such as failing  to  provide  adequate  synchronization  to
       prevent a mutex from being deleted while in use) are made optional.

       A  wide  range  of  implementations  is thus made possible. For example, an implementation
       intended for application  debugging  may  implement  all  of  the  error  checks,  but  an
       implementation running a single, provably correct application under very tight performance
       constraints in an embedded computer might  implement  minimal  checks.  An  implementation
       might  even  be provided in two versions, similar to the options that compilers provide: a
       full-checking, but slower version; and a limited-checking, but faster version.  To  forbid
       this optionality would be a disservice to users.

       By  carefully  limiting  the  use of "undefined behavior" only to things that an erroneous
       (badly coded) application might do, and by defining that resource-not-available errors are
       mandatory, this volume of IEEE Std 1003.1-2001 ensures that a fully-conforming application
       is  portable  across  the  full  range  of  implementations,   while   not   forcing   all
       implementations  to add overhead to check for numerous things that a correct program never
       does.

   Why No Limits are Defined
       Defining symbols for the maximum number of mutexes and condition variables was  considered
       but rejected because the number of these objects may change dynamically. Furthermore, many
       implementations place these objects into application memory; thus, there  is  no  explicit
       maximum.

   Static Initializers for Mutexes and Condition Variables
       Providing for static initialization of statically allocated synchronization objects allows
       modules with private static synchronization  variables  to  avoid  runtime  initialization
       tests  and  overhead.  Furthermore, it simplifies the coding of self-initializing modules.
       Such modules are common in C libraries, where for various reasons  the  design  calls  for
       self-initialization  instead of requiring an explicit module initialization function to be
       called. An example use of static initialization follows.

       Without static initialization, a self-initializing routine foo() might look as follows:

              static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
              static pthread_mutex_t foo_mutex;

              void foo_init()
              {
                  pthread_mutex_init(&foo_mutex, NULL);
              }

              void foo()
              {
                  pthread_once(&foo_once, foo_init);
                  pthread_mutex_lock(&foo_mutex);
                 /* Do work. */
                  pthread_mutex_unlock(&foo_mutex);
              }

       With static initialization, the same routine could be coded as follows:

              static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;

              void foo()
              {
                  pthread_mutex_lock(&foo_mutex);
                 /* Do work. */
                  pthread_mutex_unlock(&foo_mutex);
              }

       Note that the static initialization both eliminates the need for the  initialization  test
       inside  pthread_once()  and  the  fetch of &foo_mutex to learn the address to be passed to
       pthread_mutex_lock() or pthread_mutex_unlock().

       Thus, the C code written to initialize static objects is simpler on  all  systems  and  is
       also  faster  on a large class of systems; those where the (entire) synchronization object
       can be stored in application memory.

       Yet the locking performance question is likely to be  raised  for  machines  that  require
       mutexes to be allocated out of special memory. Such machines actually have to have mutexes
       and possibly condition variables contain pointers  to  the  actual  hardware  locks.   For
       static  initialization  to  work  on  such machines, pthread_mutex_lock() also has to test
       whether or not the pointer to  the  actual  lock  has  been  allocated.  If  it  has  not,
       pthread_mutex_lock()  has  to  initialize it before use. The reservation of such resources
       can be made when the program is loaded, and hence return codes  have  not  been  added  to
       mutex   locking   and   condition   variable  waiting  to  indicate  failure  to  complete
       initialization.

       This runtime test in pthread_mutex_lock() would at first seem to be extra work;  an  extra
       test  is  required  to see whether the pointer has been initialized. On most machines this
       would actually be implemented as a fetch of the pointer, testing the pointer against zero,
       and  then  using the pointer if it has already been initialized. While the test might seem
       to add extra work, the extra effort of testing a register is usually negligible  since  no
       extra  memory  references are actually done. As more and more machines provide caches, the
       real expenses are memory references, not instructions executed.

       Alternatively, depending on the machine architecture, there are often  ways  to  eliminate
       all  overhead in the most important case: on the lock operations that occur after the lock
       has been initialized. This can be done by shifting more  overhead  to  the  less  frequent
       operation:  initialization.  Since out-of-line mutex allocation also means that an address
       has to be dereferenced to find the actual lock, one technique that is widely applicable is
       to  have  static  initialization  store  a bogus value for that address; in particular, an
       address that causes a machine fault to occur. When such a  fault  occurs  upon  the  first
       attempt  to  lock  such a mutex, validity checks can be done, and then the correct address
       for the actual lock can be filled in. Subsequent lock operations incur no  extra  overhead
       since  they  do  not  "fault".   This  is merely one technique that can be used to support
       static initialization, while not adversely affecting the performance of lock  acquisition.
       No doubt there are other techniques that are highly machine-dependent.

       The  locking  overhead for machines doing out-of-line mutex allocation is thus similar for
       modules being  implicitly  initialized,  where  it  is  improved  for  those  doing  mutex
       allocation entirely inline.  The inline case is thus made much faster, and the out-of-line
       case is not significantly worse.

       Besides the issue of locking performance for such machines, a concern is raised that it is
       possible  that threads would serialize contending for initialization locks when attempting
       to finish initializing statically  allocated  mutexes.  (Such  finishing  would  typically
       involve  taking  an  internal  lock,  allocating  a  structure,  storing  a pointer to the
       structure in the mutex, and releasing the  internal  lock.)  First,  many  implementations
       would   reduce   such  serialization  by  hashing  on  the  mutex  address.  Second,  such
       serialization can only occur a bounded number of times. In particular, it  can  happen  at
       most  as many times as there are statically allocated synchronization objects. Dynamically
       allocated   objects   would   still   be   initialized   via    pthread_mutex_init()    or
       pthread_cond_init().

       Finally,  if  none  of the above optimization techniques for out-of-line allocation yields
       sufficient performance for an application on  some  implementation,  the  application  can
       avoid  static  initialization  altogether  by  explicitly initializing all synchronization
       objects with the corresponding pthread_*_init() functions,  which  are  supported  by  all
       implementations.  An  implementation  can  also  document  the  tradeoffs and advise which
       initialization technique is more efficient for that particular implementation.

   Destroying Mutexes
       A mutex can be destroyed immediately after it  is  unlocked.  For  example,  consider  the
       following code:

              struct obj {
              pthread_mutex_t om;
                  int refcnt;
                  ...
              };

              obj_done(struct obj *op)
              {
                  pthread_mutex_lock(&op->om);
                  if (--op->refcnt == 0) {
                      pthread_mutex_unlock(&op->om);
              (A)     pthread_mutex_destroy(&op->om);
              (B)     free(op);
                  } else
              (C)     pthread_mutex_unlock(&op->om);
              }

       In this case obj is reference counted and obj_done() is called whenever a reference to the
       object is dropped.  Implementations are required to allow an object to  be  destroyed  and
       freed  and  potentially unmapped (for example, lines A and B) immediately after the object
       is unlocked (line C).

FUTURE DIRECTIONS

       None.

SEE ALSO

       pthread_mutex_getprioceiling()  ,  pthread_mutex_lock()  ,   pthread_mutex_timedlock()   ,
       pthread_mutexattr_getpshared()  ,  the  Base  Definitions  volume of IEEE Std 1003.1-2001,
       <pthread.h>

COPYRIGHT

       Portions of this text are reprinted and  reproduced  in  electronic  form  from  IEEE  Std
       1003.1,  2003  Edition,  Standard  for Information Technology -- Portable Operating System
       Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2003  by
       the  Institute  of  Electrical  and  Electronics Engineers, Inc and The Open Group. In the
       event of any discrepancy between this version and the original IEEE  and  The  Open  Group
       Standard,  the  original  IEEE  and  The  Open Group Standard is the referee document. The
       original Standard can be obtained online at http://www.opengroup.org/unix/online.html .