Print this page
4213 Missing spaces in man pages
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/man/man3c/mutex_init.3c
+++ new/usr/src/man/man3c/mutex_init.3c
1 1 '\" te
2 2 .\" Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
3 3 .\" Portions Copyright (c) 2001, the Institute of Electrical and Electronics Engineers, Inc. and The Open Group. All Rights Reserved.
4 4 .\" Portions Copyright (c) 1995 IEEE All Rights Reserved.
5 5 .\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
6 6 .\" http://www.opengroup.org/bookstore/.
7 7 .\" The Institute of Electrical and Electronics Engineers and The Open Group, have given us permission to reprint portions of their documentation. In the following statement, the phrase "this text" refers to portions of the system documentation. Portions of this text are reprinted and reproduced in electronic form in the Sun OS Reference Manual, from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between these versions 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.
8 8 .\" This notice shall appear on any product containing this material.
9 9 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
10 10 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
11 11 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
12 12 .TH MUTEX_INIT 3C "Jun 5, 2007"
13 13 .SH NAME
14 14 mutex_init, mutex_lock, mutex_trylock, mutex_unlock, mutex_consistent,
15 15 mutex_destroy \- mutual exclusion locks
16 16 .SH SYNOPSIS
17 17 .LP
18 18 .nf
19 19 cc -mt [ \fIflag\fR... ] \fIfile\fR... [ \fIlibrary\fR... ]
20 20 #include <thread.h>
21 21 #include <synch.h>
22 22
23 23 \fBint\fR \fBmutex_init\fR(\fBmutex_t *\fR\fImp\fR, \fBint\fR \fItype\fR, \fBvoid *\fR \fIarg\fR);
24 24 .fi
25 25
26 26 .LP
27 27 .nf
28 28 \fBint\fR \fBmutex_lock\fR(\fBmutex_t *\fR\fImp\fR);
29 29 .fi
30 30
31 31 .LP
32 32 .nf
33 33 \fBint\fR \fBmutex_trylock\fR(\fBmutex_t *\fR\fImp\fR);
34 34 .fi
35 35
36 36 .LP
37 37 .nf
38 38 \fBint\fR \fBmutex_unlock\fR(\fBmutex_t *\fR\fImp\fR);
39 39 .fi
40 40
41 41 .LP
42 42 .nf
43 43 \fBint\fR \fBmutex_consistent\fR(\fBmutex_t *\fR\fImp\fR);
44 44 .fi
45 45
46 46 .LP
47 47 .nf
48 48 \fBint\fR \fBmutex_destroy\fR(\fBmutex_t *\fR\fImp\fR);
49 49 .fi
50 50
51 51 .SH DESCRIPTION
52 52 .sp
53 53 .LP
54 54 Mutual exclusion locks (mutexes) prevent multiple threads from simultaneously
55 55 executing critical sections of code that access shared data (that is, mutexes
56 56 are used to serialize the execution of threads). All mutexes must be global. A
57 57 successful call for a mutex lock by way of \fBmutex_lock()\fR will cause
58 58 another thread that is also trying to lock the same mutex to block until the
59 59 owner thread unlocks it by way of \fBmutex_unlock()\fR. Threads within the
60 60 same process or within other processes can share mutexes.
61 61 .sp
62 62 .LP
63 63 Mutexes can synchronize threads within the same process or in other processes.
64 64 Mutexes can be used to synchronize threads between processes if the mutexes are
65 65 allocated in writable memory and shared among the cooperating processes (see
66 66 \fBmmap\fR(2)), and have been initialized for this task.
67 67 .SS "Initialize"
68 68 .sp
69 69 .LP
70 70 Mutexes are either intra-process or inter-process, depending upon the argument
71 71 passed implicitly or explicitly to the initialization of that mutex. A
72 72 statically allocated mutex does not need to be explicitly initialized; by
73 73 default, a statically allocated mutex is initialized with all zeros and its
74 74 scope is set to be within the calling process.
75 75 .sp
76 76 .LP
77 77 For inter-process synchronization, a mutex needs to be allocated in memory
78 78 shared between these processes. Since the memory for such a mutex must be
79 79 allocated dynamically, the mutex needs to be explicitly initialized using
80 80 \fBmutex_init()\fR.
81 81 .sp
82 82 .LP
83 83 The \fBmutex_init()\fR function initializes the mutex referenced by \fImp\fR
84 84 with the type specified by \fItype\fR. Upon successful initialization the
85 85 state of the mutex becomes initialized and unlocked. Only the attribute type
86 86 \fBLOCK_PRIO_PROTECT\fR uses \fIarg\fR. The \fItype\fR argument must be one of
87 87 the following:
88 88 .sp
89 89 .ne 2
90 90 .na
91 91 \fB\fBUSYNC_THREAD\fR\fR
92 92 .ad
93 93 .sp .6
94 94 .RS 4n
95 95 The mutex can synchronize threads only in this process.
96 96 .RE
97 97
98 98 .sp
99 99 .ne 2
100 100 .na
101 101 \fB\fBUSYNC_PROCESS\fR\fR
102 102 .ad
103 103 .sp .6
104 104 .RS 4n
105 105 The mutex can synchronize threads in this process and other processes. The
106 106 object initialized with this attribute must be allocated in memory shared
107 107 between processes, either in System V shared memory (see \fBshmop\fR(2)) or in
108 108 memory mapped to a file (see \fBmmap\fR(2)). If the object is not allocated in
109 109 such shared memory, it will not be shared between processes.
110 110 .RE
111 111
112 112 .sp
113 113 .LP
114 114 The \fItype\fR argument can be augmented by the bitwise-inclusive-\fBOR\fR of
115 115 zero or more of the following flags:
116 116 .sp
117 117 .ne 2
118 118 .na
119 119 \fB\fBLOCK_ROBUST\fR\fR
120 120 .ad
121 121 .sp .6
122 122 .RS 4n
123 123 The mutex can synchronize threads robustly. At the time of thread or process
124 124 death, either by calling \fBthr_exit()\fR or \fBexit()\fR or due to process
125 125 abnormal termination, the lock is unlocked if is held by the thread or process.
126 126 The next owner of the mutex will acquire it with an error return of
127 127 \fBEOWNERDEAD\fR. The application must always check the return value from
128 128 \fBmutex_lock()\fR for a mutex of this type. The new owner of this mutex should
129 129 then attempt to make the state protected by the mutex consistent, since this
130 130 state could have been left inconsistent when the last owner died. If the new
131 131 owner is able to make the state consistent, it should call
132 132 \fBmutex_consistent()\fR to restore the state of the mutex and then unlock the
133 133 mutex. All subsequent calls to \fBmutex_lock()\fRwill then behave normally.
134 134 Only the new owner can make the mutex consistent. If for any reason the new
135 135 owner is not able to make the state consistent, it should not call
136 136 \fBmutex_consistent()\fR but should simply unlock the mutex. All waiting
137 137 processes will be awakened and all subsequent calls to \fBmutex_lock()\fR will
138 138 fail in acquiring the mutex with an error value of \fBENOTRECOVERABLE\fR. If
139 139 the thread or process that acquired the lock with \fBEOWNERDEAD\fR terminates
140 140 without unlocking the mutex, the next owner will acquire the lock with an error
141 141 value of \fBEOWNERDEAD\fR.
142 142 .sp
143 143 The memory for the object to be initialized with this attribute must be zeroed
144 144 before initialization. Any thread or process interested in the robust lock can
145 145 call \fBmutex_init()\fR to potentially initialize it, provided that all such
146 146 callers of \fBmutex_init()\fR specify the same set of attribute flags. In this
147 147 situation, if \fBmutex_init()\fR is called on a previously initialized robust
148 148 mutex, \fBmutex_init()\fR will not reinitialize the mutex and will return the
149 149 error value \fBEBUSY\fR.
150 150 .RE
151 151
152 152 .sp
153 153 .ne 2
154 154 .na
155 155 \fB\fBLOCK_RECURSIVE\fR\fR
156 156 .ad
157 157 .sp .6
158 158 .RS 4n
159 159 A thread attempting to relock this mutex without first unlocking it will
160 160 succeed in locking the mutex. The mutex must be unlocked as many times as it is
161 161 locked.
162 162 .RE
163 163
164 164 .sp
165 165 .ne 2
166 166 .na
167 167 \fB\fBLOCK_ERRORCHECK\fR\fR
168 168 .ad
169 169 .sp .6
170 170 .RS 4n
171 171 Unless \fBLOCK_RECURSIVE\fR is also set, a thread attempting to relock this
172 172 mutex without first unlocking it will return with an error rather than
173 173 deadlocking itself. A thread attempting to unlock this mutex without first
174 174 owning it will return with an error.
175 175 .RE
176 176
177 177 .sp
178 178 .ne 2
179 179 .na
180 180 \fB\fBLOCK_PRIO_INHERIT\fR\fR
181 181 .ad
182 182 .sp .6
183 183 .RS 4n
184 184 When a thread is blocking higher priority threads because of owning one or more
185 185 mutexes with the \fBLOCK_PRIO_INHERIT\fR attribute, it executes at the higher
186 186 of its priority or the priority of the highest priority thread waiting on any
187 187 of the mutexes owned by this thread and initialized with this attribute.
188 188 .RE
189 189
190 190 .sp
191 191 .ne 2
192 192 .na
193 193 \fB\fBLOCK_PRIO_PROTECT\fR\fR
194 194 .ad
195 195 .sp .6
196 196 .RS 4n
197 197 When a thread owns one or more mutexes initialized with the
198 198 \fBLOCK_PRIO_PROTECT\fR attribute, it executes at the higher of its priority or
199 199 the highest of the priority ceilings of all the mutexes owned by this thread
200 200 and initialized with this attribute, regardless of whether other threads are
201 201 blocked on any of these mutexes. When this attribute is specified, \fIarg\fR
202 202 must point to an \fBint\fR containing the priority ceiling.
203 203 .RE
204 204
205 205 .sp
206 206 .LP
207 207 See \fBpthread_mutexattr_getrobust\fR(3C) for more information about robust
208 208 mutexes. The \fBLOCK_ROBUST\fR attribute is the same as the POSIX
209 209 \fBPTHREAD_MUTEX_ROBUST\fR attribute.
210 210 .sp
211 211 .LP
212 212 See \fBpthread_mutexattr_settype\fR(3C) for more information on recursive and
213 213 error checking mutex types. The combination (\fBLOCK_RECURSIVE\fR |
214 214 \fBLOCK_ERRORCHECK\fR) is the same as the POSIX \fBPTHREAD_MUTEX_RECURSIVE\fR
215 215 type. By itself, \fBLOCK_ERRORCHECK\fR is the same as the \fBPOSIX
216 216 PTHREAD_MUTEX_ERRORCHECK\fR type.
217 217 .sp
218 218 .LP
219 219 The \fBLOCK_PRIO_INHERIT\fR attribute is the same as the POSIX
220 220 \fBPTHREAD_PRIO_INHERIT\fR attribute. The \fBLOCK_PRIO_PROTECT\fR attribute is
221 221 the same as the POSIX \fBPTHREAD_PRIO_PROTECT\fR attribute. See
222 222 \fBpthread_mutexattr_getprotocol\fR(3C),
223 223 \fBpthread_mutexattr_getprioceiling\fR(3C), and
224 224 \fBpthread_mutex_getprioceiling\fR(3C) for a full discussion. The
225 225 \fBLOCK_PRIO_INHERIT\fR and \fBLOCK_PRIO_PROTECT\fR attributes are mutually
226 226 exclusive. Specifying both of these attributes causes \fBmutex_init()\fR to
227 227 fail with \fBEINVAL\fR.
228 228 .sp
229 229 .LP
230 230 Initializing mutexes can also be accomplished by allocating in zeroed memory
231 231 (default), in which case a \fItype\fR of \fBUSYNC_THREAD\fR is assumed. In
232 232 general, the following rules apply to mutex initialization:
233 233 .RS +4
234 234 .TP
235 235 .ie t \(bu
236 236 .el o
237 237 The same mutex must not be simultaneously initialized by multiple threads.
↓ open down ↓ |
237 lines elided |
↑ open up ↑ |
238 238 .RE
239 239 .RS +4
240 240 .TP
241 241 .ie t \(bu
242 242 .el o
243 243 A mutex lock must not be reinitialized while in use by other threads.
244 244 .RE
245 245 .sp
246 246 .LP
247 247 These rules do not apply to \fBLOCK_ROBUST\fR mutexes. See the description for
248 -\fBLOCK_ROBUST\fRabove. If default mutex attributes are used, the macro
248 +\fBLOCK_ROBUST\fR above. If default mutex attributes are used, the macro
249 249 \fBDEFAULTMUTEX\fR can be used to initialize mutexes that are statically
250 250 allocated.
251 251 .sp
252 252 .LP
253 253 Default mutex initialization (intra-process):
254 254 .sp
255 255 .in +2
256 256 .nf
257 257 mutex_t mp;
258 258 mutex_init(&mp, USYNC_THREAD, NULL);
259 259 .fi
260 260 .in -2
261 261
262 262 .sp
263 263 .LP
264 264 or
265 265 .sp
266 266 .in +2
267 267 .nf
268 268 mutex_t mp = DEFAULTMUTEX;
269 269 .fi
270 270 .in -2
271 271
272 272 .sp
273 273 .LP
274 274 Customized mutex initialization (inter-process):
275 275 .sp
276 276 .in +2
277 277 .nf
278 278 mutex_init(&mp, USYNC_PROCESS, NULL);
279 279 .fi
280 280 .in -2
281 281
282 282 .sp
283 283 .LP
284 284 Customized mutex initialization (inter-process robust):
285 285 .sp
286 286 .in +2
287 287 .nf
288 288 mutex_init(&mp, USYNC_PROCESS | LOCK_ROBUST, NULL);
289 289 .fi
290 290 .in -2
291 291
292 292 .sp
293 293 .LP
294 294 Statically allocated mutexes can also be initialized with macros specifying
295 295 \fBLOCK_RECURSIVE\fR and/or \fBLOCK_ERRORCHECK\fR:
296 296 .sp
297 297 .ne 2
298 298 .na
299 299 \fB\fBmutex_t mp = RECURSIVEMUTEX;\fR\fR
300 300 .ad
301 301 .sp .6
302 302 .RS 4n
303 303 Same as (\fBUSYNC_THREAD\fR | \fBLOCK_RECURSIVE\fR)
304 304 .RE
305 305
306 306 .sp
307 307 .ne 2
308 308 .na
309 309 \fB\fBmutex_t mp = ERRORCHECKMUTEX;\fR\fR
310 310 .ad
311 311 .sp .6
312 312 .RS 4n
313 313 Same as (\fBUSYNC_THREAD\fR | \fBLOCK_ERRORCHECK\fR)
314 314 .RE
315 315
316 316 .sp
317 317 .ne 2
318 318 .na
319 319 \fB\fBmutex_t mp = RECURSIVE_ERRORCHECKMUTEX;\fR\fR
320 320 .ad
321 321 .sp .6
322 322 .RS 4n
323 323 Same as (\fBUSYNC_THREAD\fR | \fBLOCK_RECURSIVE\fR | \fBLOCK_ERRORCHECK\fR)
324 324 .RE
325 325
326 326 .SS "Lock and Unlock"
327 327 .sp
328 328 .LP
329 329 A critical section of code is enclosed by a the call to lock the mutex and the
330 330 call to unlock the mutex to protect it from simultaneous access by multiple
331 331 threads. Only one thread at a time may possess mutually exclusive access to
332 332 the critical section of code that is enclosed by the mutex-locking call and the
333 333 mutex-unlocking call, whether the mutex's scope is intra-process or
334 334 inter-process. A thread calling to lock the mutex either gets exclusive access
335 335 to the code starting from the successful locking until its call to unlock the
336 336 mutex, or it waits until the mutex is unlocked by the thread that locked it.
337 337 .sp
338 338 .LP
339 339 Mutexes have ownership, unlike semaphores. Although any thread, within the
340 340 scope of a mutex, can get an unlocked mutex and lock access to the same
341 341 critical section of code, only the thread that locked a mutex should unlock it.
342 342 .sp
343 343 .LP
344 344 If a thread waiting for a mutex receives a signal, upon return from the signal
345 345 handler, the thread resumes waiting for the mutex as if there was no interrupt.
346 346 A mutex protects code, not data; therefore, strongly bind a mutex with the
347 347 data by putting both within the same structure, or at least within the same
348 348 procedure.
349 349 .sp
350 350 .LP
351 351 A call to \fBmutex_lock()\fR locks the mutex object referenced by \fImp\fR. If
352 352 the mutex is already locked, the calling thread blocks until the mutex is
353 353 freed; this will return with the mutex object referenced by \fImp\fR in the
354 354 locked state with the calling thread as its owner. If the current owner of a
355 355 mutex tries to relock the mutex, it will result in deadlock.
356 356 .sp
357 357 .LP
358 358 The \fBmutex_trylock()\fR function is the same as \fBmutex_lock()\fR,
359 359 respectively, except that if the mutex object referenced by \fImp\fR is locked
360 360 (by any thread, including the current thread), the call returns immediately
361 361 with an error.
362 362 .sp
363 363 .LP
364 364 The \fBmutex_unlock()\fR function are called by the owner of the mutex object
365 365 referenced by \fImp\fR to release it. The mutex must be locked and the calling
366 366 thread must be the one that last locked the mutex (the owner). If there are
367 367 threads blocked on the mutex object referenced by \fImp\fR when
368 368 \fBmutex_unlock()\fR is called, the \fImp\fR is freed, and the scheduling
369 369 policy will determine which thread gets the mutex. If the calling thread is not
370 370 the owner of the lock, no error status is returned, and the behavior of the
371 371 program is undefined.
372 372 .SS "Destroy"
373 373 .sp
374 374 .LP
375 375 The \fBmutex_destroy()\fR function destroys the mutex object referenced by
376 376 \fImp\fR. The mutex object becomes uninitialized. The space used by the
377 377 destroyed mutex variable is not freed. It needs to be explicitly reclaimed.
378 378 .SH RETURN VALUES
379 379 .sp
380 380 .LP
381 381 If successful, these functions return \fB0\fR. Otherwise, an error number is
382 382 returned.
383 383 .SH ERRORS
384 384 .sp
385 385 .LP
386 386 The \fBmutex_init()\fR function will fail if:
387 387 .sp
388 388 .ne 2
389 389 .na
390 390 \fB\fBEINVAL\fR\fR
391 391 .ad
392 392 .RS 10n
393 393 The value specified by \fItype\fR is invalid, or the \fBLOCK_PRIO_INHERIT\fR
394 394 and \fBLOCK_PRIO_PROTECT\fR attributes are both specified.
395 395 .RE
396 396
397 397 .sp
398 398 .LP
399 399 The \fBmutex_init()\fR function will fail for \fBLOCK_ROBUST\fR type mutex if:
400 400 .sp
401 401 .ne 2
402 402 .na
403 403 \fB\fBEBUSY\fR\fR
404 404 .ad
405 405 .RS 10n
406 406 The mutex pointed to by \fImp\fR was previously initialized and has not yet
407 407 been destroyed.
408 408 .RE
409 409
410 410 .sp
411 411 .ne 2
412 412 .na
413 413 \fB\fBEINVAL\fR\fR
414 414 .ad
415 415 .RS 10n
416 416 The mutex pointed to by \fImp\fR was previously initialized with a different
417 417 set of attribute flags.
418 418 .RE
419 419
420 420 .sp
421 421 .LP
422 422 The \fBmutex_trylock()\fR function will fail if:
423 423 .sp
424 424 .ne 2
425 425 .na
426 426 \fB\fBEBUSY\fR\fR
427 427 .ad
428 428 .RS 9n
429 429 The mutex pointed to by \fImp\fR is already locked.
430 430 .RE
431 431
432 432 .sp
433 433 .LP
434 434 The \fBmutex_lock()\fR and \fBmutex_trylock()\fR functions will fail for a
435 435 \fBLOCK_RECURSIVE\fR mutex if:
436 436 .sp
437 437 .ne 2
438 438 .na
439 439 \fB\fBEAGAIN\fR\fR
440 440 .ad
441 441 .RS 10n
442 442 The mutex could not be acquired because the maximum number of recursive locks
443 443 for the mutex has been reached.
444 444 .RE
445 445
446 446 .sp
447 447 .LP
448 448 The \fBmutex_lock()\fR function will fail for a \fBLOCK_ERRORCHECK\fR and
449 449 non-\fBLOCK_RECURSIVE\fR mutex if:
450 450 .sp
451 451 .ne 2
452 452 .na
453 453 \fB\fBEDEADLK\fR\fR
454 454 .ad
455 455 .RS 11n
456 456 The caller already owns the mutex.
457 457 .RE
458 458
459 459 .sp
460 460 .LP
461 461 The \fBmutex_lock()\fR function may fail for a non-\fBLOCK_ERRORCHECK\fR and
462 462 non-\fBLOCK_RECURSIVE\fR mutex if:
463 463 .sp
464 464 .ne 2
465 465 .na
466 466 \fB\fBEDEADLK\fR\fR
467 467 .ad
468 468 .RS 11n
469 469 The caller already owns the mutex.
470 470 .RE
471 471
472 472 .sp
473 473 .LP
474 474 The \fBmutex_unlock()\fR function will fail for a \fBLOCK_ERRORCHECK\fR mutex
475 475 if:
476 476 .sp
477 477 .ne 2
478 478 .na
479 479 \fB\fBEPERM\fR\fR
480 480 .ad
481 481 .RS 9n
482 482 The caller does not own the mutex.
483 483 .RE
484 484
485 485 .sp
486 486 .LP
487 487 The \fBmutex_lock()\fR or \fBmutex_trylock()\fR functions will fail for
488 488 \fBLOCK_ROBUST\fR type mutex if:
489 489 .sp
490 490 .ne 2
491 491 .na
492 492 \fB\fBEOWNERDEAD\fR\fR
493 493 .ad
494 494 .RS 19n
495 495 The last owner of this mutex died while holding the mutex. This mutex is now
496 496 owned by the caller. The caller must now attempt to make the state protected by
497 497 the mutex consistent. If it is able to clean up the state, then it should
498 498 restore the state of the mutex by calling \fBmutex_consistent()\fR and unlock
499 499 the mutex. Subsequent calls to \fBmutex_lock()\fR will behave normally, as
500 500 before. If the caller is not able to clean up the state,
501 501 \fBmutex_consistent()\fR should not be called but the mutex should be unlocked.
502 502 Subsequent calls to \fBmutex_lock()\fR will fail to acquire the mutex,
503 503 returning with the error value \fBENOTRECOVERABLE\fR. If the owner who acquired
504 504 the lock with \fBEOWNERDEAD\fR dies, the next owner will acquire the lock with
505 505 \fBEOWNERDEAD\fR.
506 506 .RE
507 507
508 508 .sp
509 509 .ne 2
510 510 .na
511 511 \fB\fBENOTRECOVERABLE\fR\fR
512 512 .ad
513 513 .RS 19n
514 514 The mutex trying to be acquired was protecting the state that has been left
515 515 unrecoverable when the mutex's last owner could not make the state protected by
516 516 the mutex consistent. The mutex has not been acquired. This condition occurs
517 517 when the lock was previously acquired with \fBEOWNERDEAD\fR and the owner was
518 518 not able to clean up the state and unlocked the mutex without calling
519 519 \fBmutex_consistent()\fR.
520 520 .RE
521 521
522 522 .sp
523 523 .LP
524 524 The \fBmutex_consistent()\fR function will fail if:
525 525 .sp
526 526 .ne 2
527 527 .na
528 528 \fB\fBEINVAL\fR\fR
529 529 .ad
530 530 .RS 10n
531 531 The caller does not own the mutex or the mutex is not a \fBLOCK_ROBUST\fR mutex
532 532 having an inconsistent state (\fBEOWNERDEAD\fR).
533 533 .RE
534 534
535 535 .SH EXAMPLES
536 536 .SS "Single Gate"
537 537 .sp
538 538 .LP
539 539 The following example uses one global mutex as a gate-keeper to permit each
540 540 thread exclusive sequential access to the code within the user-defined
541 541 function "change_global_data." This type of synchronization will protect the
542 542 state of shared data, but it also prohibits parallelism.
543 543 .sp
544 544 .in +2
545 545 .nf
546 546 /* cc thisfile.c -lthread */
547 547 #define _REENTRANT
548 548 #include <stdio.h>
549 549 #include <thread.h>
550 550 #define NUM_THREADS 12
551 551 void *change_global_data(void *); /* for thr_create() */
552 552 main(int argc,char * argv[]) {
553 553 int i=0;
554 554 for (i=0; i< NUM_THREADS; i++) {
555 555 thr_create(NULL, 0, change_global_data, NULL, 0, NULL);
556 556 }
557 557 while ((thr_join(NULL, NULL, NULL) == 0));
558 558 }
559 559
560 560 void * change_global_data(void *null){
561 561 static mutex_t Global_mutex;
562 562 static int Global_data = 0;
563 563 mutex_lock(&Global_mutex);
564 564 Global_data++;
565 565 sleep(1);
566 566 printf("%d is global data\en",Global_data);
567 567 mutex_unlock(&Global_mutex);
568 568 return NULL;
569 569 }
570 570 .fi
571 571 .in -2
572 572
573 573 .SS "Multiple Instruction Single Data"
574 574 .sp
575 575 .LP
576 576 The previous example, the mutex, the code it owns, and the data it protects was
577 577 enclosed in one function. The next example uses C++ features to accommodate
578 578 many functions that use just one mutex to protect one data:
579 579 .sp
580 580 .in +2
581 581 .nf
582 582 /* CC thisfile.c -lthread use C++ to compile*/
583 583
584 584 #define _REENTRANT
585 585 #include <stdlib.h>
586 586 #include <stdio.h>
587 587 #include <thread.h>
588 588 #include <errno.h>
589 589 #include <iostream.h>
590 590 #define NUM_THREADS 16
591 591 void *change_global_data(void *); /* for thr_create() */
592 592
593 593 class Mutected {
594 594 private:
595 595 static mutex_t Global_mutex;
596 596 static int Global_data;
597 597 public:
598 598 static int add_to_global_data(void);
599 599 static int subtract_from_global_data(void);
600 600 };
601 601
602 602 int Mutected::Global_data = 0;
603 603 mutex_t Mutected::Global_mutex;
604 604
605 605 int Mutected::add_to_global_data() {
606 606 mutex_lock(&Global_mutex);
607 607 Global_data++;
608 608 mutex_unlock(&Global_mutex);
609 609 return Global_data;
610 610 }
611 611
612 612 int Mutected::subtract_from_global_data() {
613 613 mutex_lock(&Global_mutex);
614 614 Global_data--;
615 615 mutex_unlock(&Global_mutex);
616 616 return Global_data;
617 617 }
618 618
619 619 void
620 620 main(int argc,char * argv[]) {
621 621 int i=0;
622 622 for (i=0;i< NUM_THREADS;i++) {
623 623 thr_create(NULL,0,change_global_data,NULL,0,NULL);
624 624 }
625 625 while ((thr_join(NULL,NULL,NULL) == 0));
626 626 }
627 627
628 628 void * change_global_data(void *) {
629 629 static int switcher = 0;
630 630 if ((switcher++ % 3) == 0) /* one-in-three threads subtracts */
631 631 cout << Mutected::subtract_from_global_data() << endl;
632 632 else
633 633 cout << Mutected::add_to_global_data() << endl;
634 634 return NULL;
635 635 }
636 636 .fi
637 637 .in -2
638 638
639 639 .SS "Interprocess Locking"
640 640 .sp
641 641 .LP
642 642 A mutex can protect data that is shared among processes. The mutex would need
643 643 to be initialized as \fBUSYNC_PROCESS\fR. One process initializes the
644 644 process-shared mutex and writes it to a file to be mapped into memory by all
645 645 cooperating processes (see \fBmmap\fR(2)). Afterwards, other independent
646 646 processes can run the same program (whether concurrently or not) and share
647 647 mutex-protected data.
648 648 .sp
649 649 .in +2
650 650 .nf
651 651 /* cc thisfile.c -lthread */
652 652 /* To execute, run the command line "a.out 0 &; a.out 1" */
653 653
654 654 #define _REENTRANT
655 655 #include <sys/types.h>
656 656 #include <sys/mman.h>
657 657 #include <sys/stat.h>
658 658 #include <fcntl.h>
659 659 #include <stdio.h>
660 660 #include <thread.h>
661 661 #define INTERPROCESS_FILE "ipc-sharedfile"
662 662 #define NUM_ADDTHREADS 12
663 663 #define NUM_SUBTRACTTHREADS 10
664 664 #define INCREMENT '0'
665 665 #define DECREMENT '1'
666 666 typedef struct {
667 667 mutex_t Interprocess_mutex;
668 668 int Interprocess_data;
669 669 } buffer_t;
670 670 buffer_t *buffer;
671 671
672 672 void *add_interprocess_data(), *subtract_interprocess_data();
673 673 void create_shared_memory(), test_argv();
674 674 int zeroed[sizeof(buffer_t)];
675 675 int ipc_fd, i=0;
676 676
677 677 void
678 678 main(int argc,char * argv[]){
679 679 test_argv(argv[1]);
680 680
681 681 switch (*argv[1]) {
682 682 case INCREMENT:
683 683 /* Initializes the process-shared mutex */
684 684 /* Should be run prior to running a DECREMENT process */
685 685 create_shared_memory();
686 686 ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
687 687 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
688 688 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
689 689 buffer->Interprocess_data = 0;
690 690 mutex_init(&buffer->Interprocess_mutex, USYNC_PROCESS,0);
691 691 for (i=0; i< NUM_ADDTHREADS; i++)
692 692 thr_create(NULL, 0, add_interprocess_data, argv[1],
693 693 0, NULL);
694 694 break;
695 695
696 696 case DECREMENT:
697 697 /* Should be run after the INCREMENT process has run. */
698 698 while(ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
699 699 sleep(1);
700 700 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
701 701 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
702 702 for (i=0; i< NUM_SUBTRACTTHREADS; i++)
703 703 thr_create(NULL, 0, subtract_interprocess_data, argv[1],
704 704 0, NULL);
705 705 break;
706 706 } /* end switch */
707 707
708 708 while ((thr_join(NULL,NULL,NULL) == 0));
709 709 } /* end main */
710 710
711 711 void *add_interprocess_data(char argv_1[]){
712 712 mutex_lock(&buffer->Interprocess_mutex);
713 713 buffer->Interprocess_data++;
714 714 sleep(2);
715 715 printf("%d is add-interprocess data, and %c is argv1\en",
716 716 buffer->Interprocess_data, argv_1[0]);
717 717 mutex_unlock(&buffer->Interprocess_mutex);
718 718 return NULL;
719 719 }
720 720
721 721 void *subtract_interprocess_data(char argv_1[]) {
722 722 mutex_lock(&buffer->Interprocess_mutex);
723 723 buffer->Interprocess_data--;
724 724 sleep(2);
725 725 printf("%d is subtract-interprocess data, and %c is argv1\en",
726 726 buffer->Interprocess_data, argv_1[0]);
727 727 mutex_unlock(&buffer->Interprocess_mutex);
728 728 return NULL;
729 729 }
730 730
731 731 void create_shared_memory(){
732 732 int i;
733 733 ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR );
734 734 for (i=0; i<sizeof(buffer_t); i++){
735 735 zeroed[i] = 0;
736 736 write(ipc_fd, &zeroed[i],2);
737 737 }
738 738 close(ipc_fd);
739 739 chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
740 740 }
741 741
742 742 void test_argv(char argv1[]) {
743 743 if (argv1 == NULL) {
744 744 printf("use 0 as arg1 for initial process\en \e
745 745 or use 1 as arg1 for the second process\en");
746 746 exit(NULL);
747 747 }
748 748 }
749 749 .fi
750 750 .in -2
751 751
752 752 .SS "Solaris Interprocess Robust Locking"
753 753 .sp
754 754 .LP
755 755 A mutex can protect data that is shared among processes robustly. The mutex
756 756 would need to be initialized as \fBUSYNC_PROCESS\fR | \fBLOCK_ROBUST\fR. One
757 757 process initializes the robust process-shared mutex and writes it to a file to
758 758 be mapped into memory by all cooperating processes (see \fBmmap\fR(2)).
759 759 Afterwards, other independent processes can run the same program (whether
760 760 concurrently or not) and share mutex-protected data.
761 761 .sp
762 762 .LP
763 763 The following example shows how to use a \fBUSYNC_PROCESS\fR |
764 764 \fBLOCK_ROBUST\fR type mutex.
765 765 .sp
766 766 .in +2
767 767 .nf
768 768 /* cc thisfile.c -lthread */
769 769 /* To execute, run the command line "a.out & a.out 1" */
770 770 #include <sys/types.h>
771 771 #include <sys/mman.h>
772 772 #include <fcntl.h>
773 773 #include <stdio.h>
774 774 #include <thread.h>
775 775 #define INTERPROCESS_FILE "ipc-sharedfile"
776 776 typedef struct {
777 777 mutex_t Interprocess_mutex;
778 778 int Interprocess_data;
779 779 } buffer_t;
780 780 buffer_t *buffer;
781 781 int make_date_consistent();
782 782 void create_shared_memory();
783 783 int zeroed[sizeof(buffer_t)];
784 784 int ipc_fd, i=0;
785 785 main(int argc,char * argv[]) {
786 786 int rc;
787 787 if (argc > 1) {
788 788 while((ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
789 789 sleep(1);
790 790 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
791 791 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
792 792 mutex_init(&buffer->Interprocess_mutex,
793 793 USYNC_PROCESS | LOCK_ROBUST,0);
794 794 } else {
795 795 create_shared_memory();
796 796 ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
797 797 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
798 798 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
799 799 buffer->Interprocess_data = 0;
800 800 mutex_init(&buffer->Interprocess_mutex,
801 801 USYNC_PROCESS | LOCK_ROBUST,0);
802 802 }
803 803 for(;;) {
804 804 rc = mutex_lock(&buffer->Interprocess_mutex);
805 805 switch (rc) {
806 806 case EOWNERDEAD:
807 807 /*
808 808 * The lock is acquired.
809 809 * The last owner died holding the lock.
810 810 * Try to make the state associated with
811 811 * the mutex consistent.
812 812 * If successful, make the robust lock consistent.
813 813 */
814 814 if (make_data_consistent())
815 815 mutex_consistent(&buffer->Interprocess_mutex);
816 816 mutex_unlock(&buffer->Interprocess_mutex);
817 817 break;
818 818 case ENOTRECOVERABLE:
819 819 /*
820 820 * The lock is not acquired.
821 821 * The last owner got the mutex with EOWNERDEAD
822 822 * and failed to make the data consistent.
823 823 * There is no way to recover, so just exit.
824 824 */
825 825 exit(1);
826 826 case 0:
827 827 /*
828 828 * There is no error - data is consistent.
829 829 * Do something with data.
830 830 */
831 831 mutex_unlock(&buffer->Interprocess_mutex);
832 832 break;
833 833 }
834 834 }
835 835 } /* end main */
836 836 void create_shared_memory() {
837 837 int i;
838 838 ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR );
839 839 for (i=0; i<sizeof(buffer_t); i++) {
840 840 zeroed[i] = 0;
841 841 write(ipc_fd, &zeroed[i],2);
842 842 }
843 843 close(ipc_fd);
844 844 chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
845 845 }
846 846
847 847 /* return 1 if able to make data consistent, otherwise 0. */
848 848 int make_data_consistent () {
849 849 buffer->Interprocess_data = 0;
850 850 return (1);
851 851 }
852 852 .fi
853 853 .in -2
854 854
855 855 .SS "Dynamically Allocated Mutexes"
856 856 .sp
857 857 .LP
858 858 The following example allocates and frees memory in which a mutex is embedded.
859 859 .sp
860 860 .in +2
861 861 .nf
862 862 struct record {
863 863 int field1;
864 864 int field2;
865 865 mutex_t m;
866 866 } *r;
867 867 r = malloc(sizeof(struct record));
868 868 mutex_init(&r->m, USYNC_THREAD, NULL);
869 869 /*
870 870 * The fields in this record are accessed concurrently
871 871 * by acquiring the embedded lock.
872 872 */
873 873 .fi
874 874 .in -2
875 875
876 876 .sp
877 877 .LP
878 878 The thread execution in this example is as follows:
879 879 .sp
880 880 .in +2
881 881 .nf
882 882 \fIThread 1 executes:\fR \fIThread 2 executes:\fR
883 883
884 884 \&... ...
885 885 mutex_lock(&r->m); mutex_lock(&r->m);
886 886 r->field1++; localvar = r->field1;
887 887 mutex_unlock(&r->m); mutex_unlock(&r->m);
888 888 \&... ...
889 889 .fi
890 890 .in -2
891 891
892 892 .sp
893 893 .LP
894 894 Later, when a thread decides to free the memory pointed to by \fIr\fR, the
895 895 thread should call \fBmutex_destroy\fR(\|) on the mutexes in this memory.
896 896 .sp
897 897 .LP
898 898 In the following example, the main thread can do a \fBthr_join\fR(\|) on both
899 899 of the above threads. If there are no other threads using the memory in
900 900 \fIr\fR, the main thread can now safely free \fIr\fR:
901 901 .sp
902 902 .in +2
903 903 .nf
904 904 for (i = 0; i < 2; i++)
905 905 thr_join(0, 0, 0);
906 906 mutex_destroy(&r->m); /* first destroy mutex */
907 907 free(r); /* then free memory */
908 908 .fi
909 909 .in -2
910 910
911 911 .sp
912 912 .LP
913 913 If the mutex is not destroyed, the program could have memory leaks.
914 914 .SH ATTRIBUTES
915 915 .sp
916 916 .LP
917 917 See \fBattributes\fR(5) for descriptions of the following attributes:
918 918 .sp
919 919
920 920 .sp
921 921 .TS
922 922 box;
923 923 c | c
924 924 l | l .
925 925 ATTRIBUTE TYPE ATTRIBUTE VALUE
926 926 _
927 927 Interface Stability Stable
928 928 _
929 929 MT-Level MT-Safe
930 930 .TE
931 931
932 932 .SH SEE ALSO
933 933 .sp
934 934 .LP
935 935 \fBmmap\fR(2), \fBshmop\fR(2), \fBpthread_mutexattr_getprioceiling\fR(3C),
936 936 \fBpthread_mutexattr_getprotocol\fR(3C), \fBpthread_mutexattr_getrobust\fR(3C),
937 937 \fBpthread_mutexattr_gettype\fR(3C), \fBpthread_mutex_getprioceiling\fR(3C),
938 938 \fBpthread_mutex_init\fR(3C), \fBattributes\fR(5), \fBmutex\fR(5),
939 939 \fBstandards\fR(5)
940 940 .SH NOTES
941 941 .sp
942 942 .LP
943 943 Previous releases of Solaris provided the \fBUSYNC_PROCESS_ROBUST\fR mutex
944 944 type. This type is now deprecated but is still supported for source and binary
945 945 compatibility. When passed to \fBmutex_init()\fR, it is transformed into
946 946 (\fBUSYNC_PROCESS\fR | \fBLOCK_ROBUST\fR). The former method for restoring a
947 947 \fBUSYNC_PROCESS_ROBUST\fR mutex to a consistent state was to reinitialize it
948 948 by calling \fBmutex_init()\fR. This method is still supported for source and
949 949 binary compatibility, but the proper method is to call
950 950 \fBmutex_consistent()\fR.
951 951 .sp
952 952 .LP
953 953 The \fBUSYNC_PROCESS_ROBUST\fR type permitted an alternate error value,
954 954 \fBELOCKUNMAPPED\fR, to be returned by \fBmutex_lock()\fR if the process
955 955 containing a locked robust mutex unmapped the memory containing the mutex or
956 956 performed one of the \fBexec\fR(2) functions. The \fBELOCKUNMAPPED\fR error
957 957 value implies all of the consequences of the \fBEOWNERDEAD\fR error value and
958 958 as such is just a synonym for \fBEOWNERDEAD\fR. For full source and binary
959 959 compatibility, the \fBELOCKUNMAPPED\fR error value is still returned from
960 960 \fBmutex_lock()\fR in these circumstances, but only if the mutex was
961 961 initialized with the \fBUSYNC_PROCESS_ROBUST\fR type. Otherwise,
962 962 \fBEOWNERDEAD\fR is returned in these circumstances.
963 963 .sp
964 964 .LP
965 965 The \fBmutex_lock()\fR, \fBmutex_unlock()\fR, and \fBmutex_trylock()\fR
966 966 functions do not validate the mutex type. An uninitialized mutex or a mutex
967 967 with an invalid type does not return \fBEINVAL\fR. Interfaces for mutexes with
968 968 an invalid type have unspecified behavior.
969 969 .sp
970 970 .LP
971 971 Uninitialized mutexes that are allocated locally could contain junk data. Such
972 972 mutexes need to be initialized using \fBmutex_init()\fR.
973 973 .sp
974 974 .LP
975 975 By default, if multiple threads are waiting for a mutex, the order of
976 976 acquisition is undefined.
↓ open down ↓ |
718 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX