pthread_mutex_destroy.3p (15973B)
- '\" et
- .TH PTHREAD_MUTEX_DESTROY "3P" 2017 "IEEE/The Open Group" "POSIX Programmer's Manual"
- .\"
- .SH 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.
- .\"
- .SH NAME
- pthread_mutex_destroy,
- pthread_mutex_init
- \(em destroy and initialize a mutex
- .SH SYNOPSIS
- .LP
- .nf
- #include <pthread.h>
- .P
- int pthread_mutex_destroy(pthread_mutex_t *\fImutex\fP);
- int pthread_mutex_init(pthread_mutex_t *restrict \fImutex\fP,
- const pthread_mutexattr_t *restrict \fIattr\fP);
- pthread_mutex_t \fImutex\fP = PTHREAD_MUTEX_INITIALIZER;
- .fi
- .SH DESCRIPTION
- The
- \fIpthread_mutex_destroy\fR()
- function shall destroy the mutex object referenced by
- .IR mutex ;
- the mutex object becomes, in effect, uninitialized. An implementation
- may cause
- \fIpthread_mutex_destroy\fR()
- to set the object referenced by
- .IR mutex
- to an invalid value.
- .P
- A destroyed mutex object can be reinitialized using
- \fIpthread_mutex_init\fR();
- the results of otherwise referencing the object after it has been
- destroyed are undefined.
- .P
- It shall be safe to destroy an initialized mutex that is unlocked.
- Attempting to destroy a locked mutex, or a mutex that another thread
- is attempting to lock, or a mutex that is being used in a
- \fIpthread_cond_timedwait\fR()
- or
- \fIpthread_cond_wait\fR()
- call by another thread, results in undefined behavior.
- .P
- The
- \fIpthread_mutex_init\fR()
- function shall initialize the mutex referenced by
- .IR mutex
- with attributes specified by
- .IR attr .
- If
- .IR 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.
- .P
- See
- .IR "Section 2.9.9" ", " "Synchronization Object Copies and Alternative Mappings"
- for further requirements.
- .P
- Attempting to initialize an already initialized mutex results in
- undefined behavior.
- .P
- 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
- \fIpthread_mutex_init\fR()
- with parameter
- .IR attr
- specified as NULL, except that no error checks are performed.
- .P
- The behavior is undefined if the value specified by the
- .IR mutex
- argument to
- \fIpthread_mutex_destroy\fR()
- does not refer to an initialized mutex.
- .P
- The behavior is undefined if the value specified by the
- .IR attr
- argument to
- \fIpthread_mutex_init\fR()
- does not refer to an initialized mutex attributes object.
- .SH "RETURN VALUE"
- If successful, the
- \fIpthread_mutex_destroy\fR()
- and
- \fIpthread_mutex_init\fR()
- functions shall return zero; otherwise, an error number shall be
- returned to indicate the error.
- .SH ERRORS
- The
- \fIpthread_mutex_init\fR()
- function shall fail if:
- .TP
- .BR EAGAIN
- The system lacked the necessary resources (other than memory) to
- initialize another mutex.
- .TP
- .BR ENOMEM
- Insufficient memory exists to initialize the mutex.
- .TP
- .BR EPERM
- The caller does not have the privilege to perform the operation.
- .br
- .P
- The
- \fIpthread_mutex_init\fR()
- function may fail if:
- .TP
- .BR EINVAL
- The attributes object referenced by
- .IR attr
- has the robust mutex attribute set without the process-shared attribute
- being set.
- .P
- These functions shall not return an error code of
- .BR [EINTR] .
- .LP
- .IR "The following sections are informative."
- .SH EXAMPLES
- None.
- .SH "APPLICATION USAGE"
- None.
- .SH RATIONALE
- If an implementation detects that the value specified by the
- .IR mutex
- argument to
- \fIpthread_mutex_destroy\fR()
- does not refer to an initialized mutex, it is recommended that the
- function should fail and report an
- .BR [EINVAL]
- error.
- .P
- If an implementation detects that the value specified by the
- .IR mutex
- argument to
- \fIpthread_mutex_destroy\fR()
- or
- \fIpthread_mutex_init\fR()
- refers to a locked mutex or a mutex that is referenced (for example,
- while being used in a
- \fIpthread_cond_timedwait\fR()
- or
- \fIpthread_cond_wait\fR())
- by another thread, or detects that the value specified by the
- .IR mutex
- argument to
- \fIpthread_mutex_init\fR()
- refers to an already initialized mutex, it is recommended that the
- function should fail and report an
- .BR [EBUSY]
- error.
- .P
- If an implementation detects that the value specified by the
- .IR attr
- argument to
- \fIpthread_mutex_init\fR()
- does not refer to an initialized mutex attributes object, it is
- recommended that the function should fail and report an
- .BR [EINVAL]
- error.
- .SS "Alternate Implementations Possible"
- .P
- This volume of POSIX.1\(hy2017 supports several alternative implementations of mutexes.
- An implementation may store the lock directly in the object of type
- .BR 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\(hy2017 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.
- .P
- Note that this precludes an over-specification of the type of the mutex
- or condition variable and motivates the opaqueness of the type.
- .P
- An implementation is permitted, but not required, to have
- \fIpthread_mutex_destroy\fR()
- 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.
- .SS "Tradeoff Between Error Checks and Performance Supported"
- .P
- Many error conditions that can occur are not required to be detected by
- the implementation in order to let implementations trade off performance
- \fIversus\fR 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.
- .P
- 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.
- .P
- 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\(hy2017 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 \fIanything\fR 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.
- .SS "Why No Limits are Defined"
- .P
- 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.
- .SS "Static Initializers for Mutexes and Condition Variables"
- .P
- 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.
- .P
- Without static initialization, a self-initializing routine
- \fIfoo\fR()
- might look as follows:
- .sp
- .RS 4
- .nf
- static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
- static pthread_mutex_t foo_mutex;
- .P
- void foo_init()
- {
- pthread_mutex_init(&foo_mutex, NULL);
- }
- .P
- void foo()
- {
- pthread_once(&foo_once, foo_init);
- pthread_mutex_lock(&foo_mutex);
- /* Do work. */
- pthread_mutex_unlock(&foo_mutex);
- }
- .fi
- .P
- .RE
- .P
- With static initialization, the same routine could be coded as
- follows:
- .sp
- .RS 4
- .nf
- static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
- .P
- void foo()
- {
- pthread_mutex_lock(&foo_mutex);
- /* Do work. */
- pthread_mutex_unlock(&foo_mutex);
- }
- .fi
- .P
- .RE
- .P
- Note that the static initialization both eliminates the need for the
- initialization test inside
- \fIpthread_once\fR()
- and the fetch of &\fIfoo_mutex\fP to learn the address to be passed to
- \fIpthread_mutex_lock\fR()
- or
- \fIpthread_mutex_unlock\fR().
- .P
- 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.
- .P
- 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,
- \fIpthread_mutex_lock\fR()
- also has to test whether or not the pointer to the actual lock has been
- allocated. If it has not,
- \fIpthread_mutex_lock\fR()
- 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.
- .P
- This runtime test in
- \fIpthread_mutex_lock\fR()
- 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.
- .P
- Alternatively, depending on the machine architecture, there are often
- ways to eliminate
- .IR all
- overhead in the most important case: on the lock operations that occur
- .IR 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.
- .P
- 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.
- .P
- 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
- \fIpthread_mutex_init\fR()
- or
- \fIpthread_cond_init\fR().
- .P
- 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
- .IR 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.
- .SS "Destroying Mutexes"
- .P
- A mutex can be destroyed immediately after it is unlocked. However,
- since attempting to destroy a locked mutex, or a mutex that another
- thread is attempting to lock, or a mutex that is being used in a
- \fIpthread_cond_timedwait\fR()
- or
- \fIpthread_cond_wait\fR()
- call by another thread, results in undefined behavior, care must be
- taken to ensure that no other thread may be referencing the mutex.
- .SS "Robust Mutexes"
- .P
- 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.
- .SH "FUTURE DIRECTIONS"
- None.
- .SH "SEE ALSO"
- .ad l
- .IR "\fIpthread_mutex_getprioceiling\fR\^(\|)",
- .IR "\fIpthread_mutexattr_getrobust\fR\^(\|)",
- .IR "\fIpthread_mutex_lock\fR\^(\|)",
- .IR "\fIpthread_mutex_timedlock\fR\^(\|)",
- .IR "\fIpthread_mutexattr_getpshared\fR\^(\|)"
- .ad b
- .P
- The Base Definitions volume of POSIX.1\(hy2017,
- .IR "\fB<pthread.h>\fP"
- .\"
- .SH COPYRIGHT
- Portions of this text are reprinted and reproduced in electronic form
- from IEEE Std 1003.1-2017, Standard for Information Technology
- -- Portable Operating System Interface (POSIX), The Open Group Base
- Specifications Issue 7, 2018 Edition,
- Copyright (C) 2018 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 .
- .PP
- 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 .