summaryrefslogtreecommitdiffstats
path: root/man-pages-posix-2017/man3p/pthread_mutex_destroy.3p
blob: 1be3493cb5862b61c79c9174357e4af0b64fe531 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
'\" 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 .