1PTHREAD_MUTEX_DESTROY(3P) POSIX Programmer's Manual PTHREAD_MUTEX_DESTROY(3P)
2
3
4
6 This manual page is part of the POSIX Programmer's Manual. The Linux
7 implementation of this interface may differ (consult the corresponding
8 Linux manual page for details of Linux behavior), or the interface may
9 not be implemented on Linux.
10
12 pthread_mutex_destroy, pthread_mutex_init — destroy and initialize a
13 mutex
14
16 #include <pthread.h>
17
18 int pthread_mutex_destroy(pthread_mutex_t *mutex);
19 int pthread_mutex_init(pthread_mutex_t *restrict mutex,
20 const pthread_mutexattr_t *restrict attr);
21 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
22
24 The pthread_mutex_destroy() function shall destroy the mutex object
25 referenced by mutex; the mutex object becomes, in effect, uninitial‐
26 ized. An implementation may cause pthread_mutex_destroy() to set the
27 object referenced by mutex to an invalid value.
28
29 A destroyed mutex object can be reinitialized using
30 pthread_mutex_init(); the results of otherwise referencing the object
31 after it has been destroyed are undefined.
32
33 It shall be safe to destroy an initialized mutex that is unlocked.
34 Attempting to destroy a locked mutex, or a mutex that another thread is
35 attempting to lock, or a mutex that is being used in a
36 pthread_cond_timedwait() or pthread_cond_wait() call by another thread,
37 results in undefined behavior.
38
39 The pthread_mutex_init() function shall initialize the mutex referenced
40 by mutex with attributes specified by attr. If attr is NULL, the
41 default mutex attributes are used; the effect shall be the same as
42 passing the address of a default mutex attributes object. Upon success‐
43 ful initialization, the state of the mutex becomes initialized and
44 unlocked.
45
46 See Section 2.9.9, Synchronization Object Copies and Alternative Map‐
47 pings for further requirements.
48
49 Attempting to initialize an already initialized mutex results in unde‐
50 fined behavior.
51
52 In cases where default mutex attributes are appropriate, the macro
53 PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes. The effect
54 shall be equivalent to dynamic initialization by a call to
55 pthread_mutex_init() with parameter attr specified as NULL, except that
56 no error checks are performed.
57
58 The behavior is undefined if the value specified by the mutex argument
59 to pthread_mutex_destroy() does not refer to an initialized mutex.
60
61 The behavior is undefined if the value specified by the attr argument
62 to pthread_mutex_init() does not refer to an initialized mutex
63 attributes object.
64
66 If successful, the pthread_mutex_destroy() and pthread_mutex_init()
67 functions shall return zero; otherwise, an error number shall be
68 returned to indicate the error.
69
71 The pthread_mutex_init() function shall fail if:
72
73 EAGAIN The system lacked the necessary resources (other than memory) to
74 initialize another mutex.
75
76 ENOMEM Insufficient memory exists to initialize the mutex.
77
78 EPERM The caller does not have the privilege to perform the operation.
79
80 The pthread_mutex_init() function may fail if:
81
82 EINVAL The attributes object referenced by attr has the robust mutex
83 attribute set without the process-shared attribute being set.
84
85 These functions shall not return an error code of [EINTR].
86
87 The following sections are informative.
88
90 None.
91
93 None.
94
96 If an implementation detects that the value specified by the mutex
97 argument to pthread_mutex_destroy() does not refer to an initialized
98 mutex, it is recommended that the function should fail and report an
99 [EINVAL] error.
100
101 If an implementation detects that the value specified by the mutex
102 argument to pthread_mutex_destroy() or pthread_mutex_init() refers to a
103 locked mutex or a mutex that is referenced (for example, while being
104 used in a pthread_cond_timedwait() or pthread_cond_wait()) by another
105 thread, or detects that the value specified by the mutex argument to
106 pthread_mutex_init() refers to an already initialized mutex, it is rec‐
107 ommended that the function should fail and report an [EBUSY] error.
108
109 If an implementation detects that the value specified by the attr argu‐
110 ment to pthread_mutex_init() does not refer to an initialized mutex
111 attributes object, it is recommended that the function should fail and
112 report an [EINVAL] error.
113
114 Alternate Implementations Possible
115 This volume of POSIX.1‐2017 supports several alternative implementa‐
116 tions of mutexes. An implementation may store the lock directly in the
117 object of type pthread_mutex_t. Alternatively, an implementation may
118 store the lock in the heap and merely store a pointer, handle, or
119 unique ID in the mutex object. Either implementation has advantages or
120 may be required on certain hardware configurations. So that portable
121 code can be written that is invariant to this choice, this volume of
122 POSIX.1‐2017 does not define assignment or equality for this type, and
123 it uses the term ``initialize'' to reinforce the (more restrictive)
124 notion that the lock may actually reside in the mutex object itself.
125
126 Note that this precludes an over-specification of the type of the mutex
127 or condition variable and motivates the opaqueness of the type.
128
129 An implementation is permitted, but not required, to have
130 pthread_mutex_destroy() store an illegal value into the mutex. This may
131 help detect erroneous programs that try to lock (or otherwise refer‐
132 ence) a mutex that has already been destroyed.
133
134 Tradeoff Between Error Checks and Performance Supported
135 Many error conditions that can occur are not required to be detected by
136 the implementation in order to let implementations trade off perfor‐
137 mance versus degree of error checking according to the needs of their
138 specific applications and execution environment. As a general rule,
139 conditions caused by the system (such as insufficient memory) are
140 required to be detected, but conditions caused by an erroneously coded
141 application (such as failing to provide adequate synchronization to
142 prevent a mutex from being deleted while in use) are specified to
143 result in undefined behavior.
144
145 A wide range of implementations is thus made possible. For example, an
146 implementation intended for application debugging may implement all of
147 the error checks, but an implementation running a single, provably cor‐
148 rect application under very tight performance constraints in an embed‐
149 ded computer might implement minimal checks. An implementation might
150 even be provided in two versions, similar to the options that compilers
151 provide: a full-checking, but slower version; and a limited-checking,
152 but faster version. To forbid this optionality would be a disservice to
153 users.
154
155 By carefully limiting the use of ``undefined behavior'' only to things
156 that an erroneous (badly coded) application might do, and by defining
157 that resource-not-available errors are mandatory, this volume of
158 POSIX.1‐2017 ensures that a fully-conforming application is portable
159 across the full range of implementations, while not forcing all imple‐
160 mentations to add overhead to check for numerous things that a correct
161 program never does. When the behavior is undefined, no error number is
162 specified to be returned on implementations that do detect the condi‐
163 tion. This is because undefined behavior means anything can happen,
164 which includes returning with any value (which might happen to be a
165 valid, but different, error number). However, since the error number
166 might be useful to application developers when diagnosing problems dur‐
167 ing application development, a recommendation is made in rationale that
168 implementors should return a particular error number if their implemen‐
169 tation does detect the condition.
170
171 Why No Limits are Defined
172 Defining symbols for the maximum number of mutexes and condition vari‐
173 ables was considered but rejected because the number of these objects
174 may change dynamically. Furthermore, many implementations place these
175 objects into application memory; thus, there is no explicit maximum.
176
177 Static Initializers for Mutexes and Condition Variables
178 Providing for static initialization of statically allocated synchro‐
179 nization objects allows modules with private static synchronization
180 variables to avoid runtime initialization tests and overhead. Further‐
181 more, it simplifies the coding of self-initializing modules. Such mod‐
182 ules are common in C libraries, where for various reasons the design
183 calls for self-initialization instead of requiring an explicit module
184 initialization function to be called. An example use of static initial‐
185 ization follows.
186
187 Without static initialization, a self-initializing routine foo() might
188 look as follows:
189
190
191 static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
192 static pthread_mutex_t foo_mutex;
193
194 void foo_init()
195 {
196 pthread_mutex_init(&foo_mutex, NULL);
197 }
198
199 void foo()
200 {
201 pthread_once(&foo_once, foo_init);
202 pthread_mutex_lock(&foo_mutex);
203 /* Do work. */
204 pthread_mutex_unlock(&foo_mutex);
205 }
206
207 With static initialization, the same routine could be coded as follows:
208
209
210 static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
211
212 void foo()
213 {
214 pthread_mutex_lock(&foo_mutex);
215 /* Do work. */
216 pthread_mutex_unlock(&foo_mutex);
217 }
218
219 Note that the static initialization both eliminates the need for the
220 initialization test inside pthread_once() and the fetch of &foo_mutex
221 to learn the address to be passed to pthread_mutex_lock() or
222 pthread_mutex_unlock().
223
224 Thus, the C code written to initialize static objects is simpler on all
225 systems and is also faster on a large class of systems; those where the
226 (entire) synchronization object can be stored in application memory.
227
228 Yet the locking performance question is likely to be raised for
229 machines that require mutexes to be allocated out of special memory.
230 Such machines actually have to have mutexes and possibly condition
231 variables contain pointers to the actual hardware locks. For static
232 initialization to work on such machines, pthread_mutex_lock() also has
233 to test whether or not the pointer to the actual lock has been allo‐
234 cated. If it has not, pthread_mutex_lock() has to initialize it before
235 use. The reservation of such resources can be made when the program is
236 loaded, and hence return codes have not been added to mutex locking and
237 condition variable waiting to indicate failure to complete initializa‐
238 tion.
239
240 This runtime test in pthread_mutex_lock() would at first seem to be
241 extra work; an extra test is required to see whether the pointer has
242 been initialized. On most machines this would actually be implemented
243 as a fetch of the pointer, testing the pointer against zero, and then
244 using the pointer if it has already been initialized. While the test
245 might seem to add extra work, the extra effort of testing a register is
246 usually negligible since no extra memory references are actually done.
247 As more and more machines provide caches, the real expenses are memory
248 references, not instructions executed.
249
250 Alternatively, depending on the machine architecture, there are often
251 ways to eliminate all overhead in the most important case: on the lock
252 operations that occur after the lock has been initialized. This can be
253 done by shifting more overhead to the less frequent operation: initial‐
254 ization. Since out-of-line mutex allocation also means that an address
255 has to be dereferenced to find the actual lock, one technique that is
256 widely applicable is to have static initialization store a bogus value
257 for that address; in particular, an address that causes a machine fault
258 to occur. When such a fault occurs upon the first attempt to lock such
259 a mutex, validity checks can be done, and then the correct address for
260 the actual lock can be filled in. Subsequent lock operations incur no
261 extra overhead since they do not ``fault''. This is merely one tech‐
262 nique that can be used to support static initialization, while not
263 adversely affecting the performance of lock acquisition. No doubt there
264 are other techniques that are highly machine-dependent.
265
266 The locking overhead for machines doing out-of-line mutex allocation is
267 thus similar for modules being implicitly initialized, where it is
268 improved for those doing mutex allocation entirely inline. The inline
269 case is thus made much faster, and the out-of-line case is not signifi‐
270 cantly worse.
271
272 Besides the issue of locking performance for such machines, a concern
273 is raised that it is possible that threads would serialize contending
274 for initialization locks when attempting to finish initializing stati‐
275 cally allocated mutexes. (Such finishing would typically involve taking
276 an internal lock, allocating a structure, storing a pointer to the
277 structure in the mutex, and releasing the internal lock.) First, many
278 implementations would reduce such serialization by hashing on the mutex
279 address. Second, such serialization can only occur a bounded number of
280 times. In particular, it can happen at most as many times as there are
281 statically allocated synchronization objects. Dynamically allocated
282 objects would still be initialized via pthread_mutex_init() or
283 pthread_cond_init().
284
285 Finally, if none of the above optimization techniques for out-of-line
286 allocation yields sufficient performance for an application on some
287 implementation, the application can avoid static initialization alto‐
288 gether by explicitly initializing all synchronization objects with the
289 corresponding pthread_*_init() functions, which are supported by all
290 implementations. An implementation can also document the tradeoffs and
291 advise which initialization technique is more efficient for that par‐
292 ticular implementation.
293
294 Destroying Mutexes
295 A mutex can be destroyed immediately after it is unlocked. However,
296 since attempting to destroy a locked mutex, or a mutex that another
297 thread is attempting to lock, or a mutex that is being used in a
298 pthread_cond_timedwait() or pthread_cond_wait() call by another thread,
299 results in undefined behavior, care must be taken to ensure that no
300 other thread may be referencing the mutex.
301
302 Robust Mutexes
303 Implementations are required to provide robust mutexes for mutexes with
304 the process-shared attribute set to PTHREAD_PROCESS_SHARED. Implementa‐
305 tions are allowed, but not required, to provide robust mutexes when the
306 process-shared attribute is set to PTHREAD_PROCESS_PRIVATE.
307
309 None.
310
312 pthread_mutex_getprioceiling(), pthread_mutexattr_getrobust(),
313 pthread_mutex_lock(), pthread_mutex_timedlock(), pthread_mutex‐
314 attr_getpshared()
315
316 The Base Definitions volume of POSIX.1‐2017, <pthread.h>
317
319 Portions of this text are reprinted and reproduced in electronic form
320 from IEEE Std 1003.1-2017, Standard for Information Technology -- Por‐
321 table Operating System Interface (POSIX), The Open Group Base Specifi‐
322 cations Issue 7, 2018 Edition, Copyright (C) 2018 by the Institute of
323 Electrical and Electronics Engineers, Inc and The Open Group. In the
324 event of any discrepancy between this version and the original IEEE and
325 The Open Group Standard, the original IEEE and The Open Group Standard
326 is the referee document. The original Standard can be obtained online
327 at http://www.opengroup.org/unix/online.html .
328
329 Any typographical or formatting errors that appear in this page are
330 most likely to have been introduced during the conversion of the source
331 files to man page format. To report such errors, see https://www.ker‐
332 nel.org/doc/man-pages/reporting_bugs.html .
333
334
335
336IEEE/The Open Group 2017 PTHREAD_MUTEX_DESTROY(3P)