PROLOG | NAME | SYNOPSIS | DESCRIPTION | RETURN VALUE | ERRORS | EXAMPLES | APPLICATION USAGE | RATIONALE | FUTURE DIRECTIONS | SEE ALSO | COPYRIGHT

PTHREAD_MUTEX_DESTROY(3P) POSIX Programmer's ManualPTHREAD_MUTEX_DESTROY(3P)

PROLOG         top

       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         top

       pthread_mutex_destroy, pthread_mutex_init — destroy and initialize a
       mutex

SYNOPSIS         top

       #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         top

       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         top

       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         top

       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         top

       None.

APPLICATION USAGE         top

       None.

RATIONALE         top

       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         top

       None.

SEE ALSO         top

       pthread_mutex_getprioceiling(3p), pthread_mutexattr_getrobust(3p),
       pthread_mutex_lock(3p), pthread_mutex_timedlock(3p),
       pthread_mutexattr_getpshared(3p)
       The Base Definitions volume of POSIX.1‐2008, pthread.h(0p)

COPYRIGHT         top

       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 .
IEEE/The Open Group                 2013           PTHREAD_MUTEX_DESTROY(3P)

Pages that refer to this page: pthread.h(0p)pthread_condattr_destroy(3p)pthread_condattr_getclock(3p)pthread_condattr_getpshared(3p)pthread_cond_destroy(3p)pthread_mutexattr_destroy(3p)pthread_mutexattr_getprioceiling(3p)pthread_mutexattr_getprotocol(3p)pthread_mutexattr_getpshared(3p)pthread_mutexattr_getrobust(3p)pthread_mutex_getprioceiling(3p)pthread_mutex_init(3p)pthread_mutex_lock(3p)pthread_mutex_timedlock(3p)