Provided by: manpages-posix-dev_2013a-1_all bug

PROLOG

       This  manual  page  is part of the POSIX Programmer's Manual.  The Linux implementation of
       this interface may differ (consult the corresponding Linux  manual  page  for  details  of
       Linux behavior), or the interface may not be implemented on Linux.

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  or  a  mutex  that  is  referenced  (for  example, while being used in a
       pthread_cond_timedwait() or pthread_cond_wait()) by another thread  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.  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.

       The   behavior   is   undefined   if   the  value  specified  by  the  mutex  argument  to
       pthread_mutex_destroy() does not refer to an initialized mutex.

       The  behavior  is  undefined  if  the  value   specified   by   the   attr   argument   to
       pthread_mutex_init() does not refer to an initialized mutex attributes object.

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.

ERRORS

       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:

       EINVAL The attributes object referenced by attr has the robust mutex attribute set without
              the process-shared attribute being set.

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

       The following sections are informative.

EXAMPLES

       None.

APPLICATION USAGE

       None.

RATIONALE

       If  an  implementation  detects  that  the  value  specified  by  the  mutex  argument  to
       pthread_mutex_destroy() does not refer to an initialized mutex, it is recommended that the
       function should fail and report an [EINVAL] error.

       If  an  implementation  detects  that  the  value  specified  by  the  mutex  argument  to
       pthread_mutex_destroy()  or  pthread_mutex_init() refers to a locked mutex or a mutex that
       is  referenced  (for  example,  while  being  used  in   a   pthread_cond_timedwait()   or
       pthread_cond_wait())  by  another thread, or detects that the value specified by the mutex
       argument to pthread_mutex_init() refers to an already initialized mutex, it is recommended
       that the function should fail and report an [EBUSY] error.

       If   an  implementation  detects  that  the  value  specified  by  the  attr  argument  to
       pthread_mutex_init() does not refer to an  initialized  mutex  attributes  object,  it  is
       recommended that the function should fail and report an [EINVAL] error.

   Alternate Implementations Possible
       This  volume  of POSIX.1‐2008 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  POSIX.1‐2008  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 error conditions that can occur are not required to be detected by the implementation
       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, conditions caused by the system (such as insufficient memory)  are  required
       to be detected, but conditions caused by an erroneously coded application (such as failing
       to provide adequate synchronization to prevent a mutex from being deleted  while  in  use)
       are specified to result in undefined behavior.

       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  POSIX.1‐2008  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. When the
       behavior is undefined, no error number is specified to be returned on implementations that
       do  detect  the  condition.  This is because undefined behavior means anything can happen,
       which includes returning with any value (which might happen to be a valid, but  different,
       error  number).  However, since the error number might be useful to application developers
       when diagnosing problems during application  development,  a  recommendation  is  made  in
       rationale   that   implementors   should   return  a  particular  error  number  if  their
       implementation does detect the condition.

   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).

   Robust Mutexes
       Implementations are required to provide robust mutexes for mutexes with the process-shared
       attribute set to PTHREAD_PROCESS_SHARED. Implementations are allowed, but not required, to
       provide   robust   mutexes   when    the    process-shared    attribute    is    set    to
       PTHREAD_PROCESS_PRIVATE.

FUTURE DIRECTIONS

       None.

SEE ALSO

       pthread_mutex_getprioceiling(), pthread_mutexattr_getrobust(), pthread_mutex_lock(),
       pthread_mutex_timedlock(), pthread_mutexattr_getpshared()

       The Base Definitions volume of POSIX.1‐2008, <pthread.h>

COPYRIGHT

       Portions of this text are reprinted and  reproduced  in  electronic  form  from  IEEE  Std
       1003.1,  2013  Edition,  Standard  for Information Technology -- Portable Operating System
       Interface (POSIX), The Open Group Base Specifications Issue 7, Copyright (C) 2013  by  the
       Institute  of  Electrical  and  Electronics  Engineers,  Inc and The Open Group.  (This is
       POSIX.1-2008 with the  2013  Technical  Corrigendum  1  applied.)  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.unix.org/online.html .

       Any  typographical  or  formatting errors that appear in this page are most likely to have
       been introduced during the conversion of the source files to man page  format.  To  report
       such errors, see https://www.kernel.org/doc/man-pages/reporting_bugs.html .