1mutex_init(3C) Standard C Library Functions mutex_init(3C)
2
3
4
6 mutex_init, mutex_lock, mutex_trylock, mutex_unlock, mutex_consistent,
7 mutex_destroy - mutual exclusion locks
8
10 cc -mt [ flag... ] file... [ library... ]
11 #include <thread.h>
12 #include <synch.h>
13
14 int mutex_init(mutex_t *mp, int type, void * arg);
15
16
17 int mutex_lock(mutex_t *mp);
18
19
20 int mutex_trylock(mutex_t *mp);
21
22
23 int mutex_unlock(mutex_t *mp);
24
25
26 int mutex_consistent(mutex_t *mp);
27
28
29 int mutex_destroy(mutex_t *mp);
30
31
33 Mutual exclusion locks (mutexes) prevent multiple threads from simulta‐
34 neously executing critical sections of code that access shared data
35 (that is, mutexes are used to serialize the execution of threads). All
36 mutexes must be global. A successful call for a mutex lock by way of
37 mutex_lock() will cause another thread that is also trying to lock the
38 same mutex to block until the owner thread unlocks it by way of
39 mutex_unlock(). Threads within the same process or within other pro‐
40 cesses can share mutexes.
41
42
43 Mutexes can synchronize threads within the same process or in other
44 processes. Mutexes can be used to synchronize threads between processes
45 if the mutexes are allocated in writable memory and shared among the
46 cooperating processes (see mmap(2)), and have been initialized for this
47 task.
48
49 Initialize
50 Mutexes are either intra-process or inter-process, depending upon the
51 argument passed implicitly or explicitly to the initialization of that
52 mutex. A statically allocated mutex does not need to be explicitly
53 initialized; by default, a statically allocated mutex is initialized
54 with all zeros and its scope is set to be within the calling process.
55
56
57 For inter-process synchronization, a mutex needs to be allocated in
58 memory shared between these processes. Since the memory for such a
59 mutex must be allocated dynamically, the mutex needs to be explicitly
60 initialized using mutex_init().
61
62
63 The mutex_init() function initializes the mutex referenced by mp with
64 the type specified by type. Upon successful initialization the state
65 of the mutex becomes initialized and unlocked. Only the attribute type
66 LOCK_PRIO_PROTECT uses arg. The type argument must be one of the fol‐
67 lowing:
68
69 USYNC_THREAD
70
71 The mutex can synchronize threads only in this process.
72
73
74 USYNC_PROCESS
75
76 The mutex can synchronize threads in this process and other pro‐
77 cesses. The object initialized with this attribute must be allo‐
78 cated in memory shared between processes, either in System V shared
79 memory (see shmop(2)) or in memory mapped to a file (see
80 mmap(2)). If the object is not allocated in such shared memory, it
81 will not be shared between processes.
82
83
84
85 The type argument can be augmented by the bitwise-inclusive-OR of zero
86 or more of the following flags:
87
88 LOCK_ROBUST
89
90 The mutex can synchronize threads robustly. At the time of thread
91 or process death, either by calling thr_exit() or exit() or due to
92 process abnormal termination, the lock is unlocked if is held by
93 the thread or process. The next owner of the mutex will acquire it
94 with an error return of EOWNERDEAD. The application must always
95 check the return value from mutex_lock() for a mutex of this type.
96 The new owner of this mutex should then attempt to make the state
97 protected by the mutex consistent, since this state could have been
98 left inconsistent when the last owner died. If the new owner is
99 able to make the state consistent, it should call mutex_consis‐
100 tent() to restore the state of the mutex and then unlock the mutex.
101 All subsequent calls to mutex_lock()will then behave normally. Only
102 the new owner can make the mutex consistent. If for any reason the
103 new owner is not able to make the state consistent, it should not
104 call mutex_consistent() but should simply unlock the mutex. All
105 waiting processes will be awakened and all subsequent calls to
106 mutex_lock() will fail in acquiring the mutex with an error value
107 of ENOTRECOVERABLE. If the thread or process that acquired the lock
108 with EOWNERDEAD terminates without unlocking the mutex, the next
109 owner will acquire the lock with an error value of EOWNERDEAD.
110
111 The memory for the object to be initialized with this attribute
112 must be zeroed before initialization. Any thread or process inter‐
113 ested in the robust lock can call mutex_init() to potentially ini‐
114 tialize it, provided that all such callers of mutex_init() specify
115 the same set of attribute flags. In this situation, if
116 mutex_init() is called on a previously initialized robust mutex,
117 mutex_init() will not reinitialize the mutex and will return the
118 error value EBUSY.
119
120
121 LOCK_RECURSIVE
122
123 A thread attempting to relock this mutex without first unlocking it
124 will succeed in locking the mutex. The mutex must be unlocked as
125 many times as it is locked.
126
127
128 LOCK_ERRORCHECK
129
130 Unless LOCK_RECURSIVE is also set, a thread attempting to relock
131 this mutex without first unlocking it will return with an error
132 rather than deadlocking itself. A thread attempting to unlock this
133 mutex without first owning it will return with an error.
134
135
136 LOCK_PRIO_INHERIT
137
138 When a thread is blocking higher priority threads because of owning
139 one or more mutexes with the LOCK_PRIO_INHERIT attribute, it exe‐
140 cutes at the higher of its priority or the priority of the highest
141 priority thread waiting on any of the mutexes owned by this thread
142 and initialized with this attribute.
143
144
145 LOCK_PRIO_PROTECT
146
147 When a thread owns one or more mutexes initialized with the
148 LOCK_PRIO_PROTECT attribute, it executes at the higher of its pri‐
149 ority or the highest of the priority ceilings of all the mutexes
150 owned by this thread and initialized with this attribute, regard‐
151 less of whether other threads are blocked on any of these mutexes.
152 When this attribute is specified, arg must point to an int contain‐
153 ing the priority ceiling.
154
155
156
157 See pthread_mutexattr_getrobust(3C) for more information about robust
158 mutexes. The LOCK_ROBUST attribute is the same as the POSIX
159 PTHREAD_MUTEX_ROBUST attribute.
160
161
162 See pthread_mutexattr_settype(3C) for more information on recursive and
163 error checking mutex types. The combination (LOCK_RECURSIVE |
164 LOCK_ERRORCHECK) is the same as the POSIX PTHREAD_MUTEX_RECURSIVE type.
165 By itself, LOCK_ERRORCHECK is the same as the POSIX
166 PTHREAD_MUTEX_ERRORCHECK type.
167
168
169 The LOCK_PRIO_INHERIT attribute is the same as the POSIX
170 PTHREAD_PRIO_INHERIT attribute. The LOCK_PRIO_PROTECT attribute is the
171 same as the POSIX PTHREAD_PRIO_PROTECT attribute. See pthread_mutex‐
172 attr_getprotocol(3C), pthread_mutexattr_getprioceiling(3C), and
173 pthread_mutex_getprioceiling(3C) for a full discussion. The
174 LOCK_PRIO_INHERIT and LOCK_PRIO_PROTECT attributes are mutually exclu‐
175 sive. Specifying both of these attributes causes mutex_init() to fail
176 with EINVAL.
177
178
179 Initializing mutexes can also be accomplished by allocating in zeroed
180 memory (default), in which case a type of USYNC_THREAD is assumed. In
181 general, the following rules apply to mutex initialization:
182
183 o The same mutex must not be simultaneously initialized by
184 multiple threads.
185
186 o A mutex lock must not be reinitialized while in use by other
187 threads.
188
189
190 These rules do not apply to LOCK_ROBUST mutexes. See the description
191 for LOCK_ROBUSTabove. If default mutex attributes are used, the macro
192 DEFAULTMUTEX can be used to initialize mutexes that are statically
193 allocated.
194
195
196 Default mutex initialization (intra-process):
197
198 mutex_t mp;
199 mutex_init(&mp, USYNC_THREAD, NULL);
200
201
202
203 or
204
205 mutex_t mp = DEFAULTMUTEX;
206
207
208
209 Customized mutex initialization (inter-process):
210
211 mutex_init(&mp, USYNC_PROCESS, NULL);
212
213
214
215 Customized mutex initialization (inter-process robust):
216
217 mutex_init(&mp, USYNC_PROCESS | LOCK_ROBUST, NULL);
218
219
220
221 Statically allocated mutexes can also be initialized with macros speci‐
222 fying LOCK_RECURSIVE and/or LOCK_ERRORCHECK:
223
224 mutex_t mp = RECURSIVEMUTEX;
225
226 Same as (USYNC_THREAD | LOCK_RECURSIVE)
227
228
229 mutex_t mp = ERRORCHECKMUTEX;
230
231 Same as (USYNC_THREAD | LOCK_ERRORCHECK)
232
233
234 mutex_t mp = RECURSIVE_ERRORCHECKMUTEX;
235
236 Same as (USYNC_THREAD | LOCK_RECURSIVE | LOCK_ERRORCHECK)
237
238
239 Lock and Unlock
240 A critical section of code is enclosed by a the call to lock the mutex
241 and the call to unlock the mutex to protect it from simultaneous access
242 by multiple threads. Only one thread at a time may possess mutually
243 exclusive access to the critical section of code that is enclosed by
244 the mutex-locking call and the mutex-unlocking call, whether the
245 mutex's scope is intra-process or inter-process. A thread calling to
246 lock the mutex either gets exclusive access to the code starting from
247 the successful locking until its call to unlock the mutex, or it waits
248 until the mutex is unlocked by the thread that locked it.
249
250
251 Mutexes have ownership, unlike semaphores. Although any thread, within
252 the scope of a mutex, can get an unlocked mutex and lock access to the
253 same critical section of code, only the thread that locked a mutex
254 should unlock it.
255
256
257 If a thread waiting for a mutex receives a signal, upon return from the
258 signal handler, the thread resumes waiting for the mutex as if there
259 was no interrupt. A mutex protects code, not data; therefore, strongly
260 bind a mutex with the data by putting both within the same structure,
261 or at least within the same procedure.
262
263
264 A call to mutex_lock() locks the mutex object referenced by mp. If the
265 mutex is already locked, the calling thread blocks until the mutex is
266 freed; this will return with the mutex object referenced by mp in the
267 locked state with the calling thread as its owner. If the current owner
268 of a mutex tries to relock the mutex, it will result in deadlock.
269
270
271 The mutex_trylock() function is the same as mutex_lock(), respectively,
272 except that if the mutex object referenced by mp is locked (by any
273 thread, including the current thread), the call returns immediately
274 with an error.
275
276
277 The mutex_unlock() function are called by the owner of the mutex object
278 referenced by mp to release it. The mutex must be locked and the call‐
279 ing thread must be the one that last locked the mutex (the owner). If
280 there are threads blocked on the mutex object referenced by mp when
281 mutex_unlock() is called, the mp is freed, and the scheduling policy
282 will determine which thread gets the mutex. If the calling thread is
283 not the owner of the lock, no error status is returned, and the behav‐
284 ior of the program is undefined.
285
286 Destroy
287 The mutex_destroy() function destroys the mutex object referenced by
288 mp. The mutex object becomes uninitialized. The space used by the
289 destroyed mutex variable is not freed. It needs to be explicitly
290 reclaimed.
291
293 If successful, these functions return 0. Otherwise, an error number is
294 returned.
295
297 The mutex_init() function will fail if:
298
299 EINVAL The value specified by type is invalid, or the
300 LOCK_PRIO_INHERIT and LOCK_PRIO_PROTECT attributes are both
301 specified.
302
303
304
305 The mutex_init() function will fail for LOCK_ROBUST type mutex if:
306
307 EBUSY The mutex pointed to by mp was previously initialized and
308 has not yet been destroyed.
309
310
311 EINVAL The mutex pointed to by mp was previously initialized with a
312 different set of attribute flags.
313
314
315
316 The mutex_trylock() function will fail if:
317
318 EBUSY The mutex pointed to by mp is already locked.
319
320
321
322 The mutex_lock() and mutex_trylock() functions will fail for a
323 LOCK_RECURSIVE mutex if:
324
325 EAGAIN The mutex could not be acquired because the maximum number of
326 recursive locks for the mutex has been reached.
327
328
329
330 The mutex_lock() function will fail for a LOCK_ERRORCHECK and non-
331 LOCK_RECURSIVE mutex if:
332
333 EDEADLK The caller already owns the mutex.
334
335
336
337 The mutex_lock() function may fail for a non-LOCK_ERRORCHECK and non-
338 LOCK_RECURSIVE mutex if:
339
340 EDEADLK The caller already owns the mutex.
341
342
343
344 The mutex_unlock() function will fail for a LOCK_ERRORCHECK mutex if:
345
346 EPERM The caller does not own the mutex.
347
348
349
350 The mutex_lock() or mutex_trylock() functions will fail for
351 LOCK_ROBUST type mutex if:
352
353 EOWNERDEAD The last owner of this mutex died while holding the
354 mutex. This mutex is now owned by the caller. The
355 caller must now attempt to make the state protected
356 by the mutex consistent. If it is able to clean up
357 the state, then it should restore the state of the
358 mutex by calling mutex_consistent() and unlock the
359 mutex. Subsequent calls to mutex_lock() will behave
360 normally, as before. If the caller is not able to
361 clean up the state, mutex_consistent() should not be
362 called but the mutex should be unlocked. Subsequent
363 calls to mutex_lock() will fail to acquire the
364 mutex, returning with the error value ENOTRECOVER‐
365 ABLE. If the owner who acquired the lock with EOWN‐
366 ERDEAD dies, the next owner will acquire the lock
367 with EOWNERDEAD.
368
369
370 ENOTRECOVERABLE The mutex trying to be acquired was protecting the
371 state that has been left unrecoverable when the
372 mutex's last owner could not make the state pro‐
373 tected by the mutex consistent. The mutex has not
374 been acquired. This condition occurs when the lock
375 was previously acquired with EOWNERDEAD and the
376 owner was not able to clean up the state and
377 unlocked the mutex without calling mutex_consis‐
378 tent().
379
380
381
382 The mutex_consistent() function will fail if:
383
384 EINVAL The caller does not own the mutex or the mutex is not a
385 LOCK_ROBUST mutex having an inconsistent state (EOWNERDEAD).
386
387
389 Single Gate
390 The following example uses one global mutex as a gate-keeper to permit
391 each thread exclusive sequential access to the code within the user-
392 defined function "change_global_data." This type of synchronization
393 will protect the state of shared data, but it also prohibits parallel‐
394 ism.
395
396 /* cc thisfile.c -lthread */
397 #define _REENTRANT
398 #include <stdio.h>
399 #include <thread.h>
400 #define NUM_THREADS 12
401 void *change_global_data(void *); /* for thr_create() */
402 main(int argc,char * argv[]) {
403 int i=0;
404 for (i=0; i< NUM_THREADS; i++) {
405 thr_create(NULL, 0, change_global_data, NULL, 0, NULL);
406 }
407 while ((thr_join(NULL, NULL, NULL) == 0));
408 }
409
410 void * change_global_data(void *null){
411 static mutex_t Global_mutex;
412 static int Global_data = 0;
413 mutex_lock(&Global_mutex);
414 Global_data++;
415 sleep(1);
416 printf("%d is global data\n",Global_data);
417 mutex_unlock(&Global_mutex);
418 return NULL;
419 }
420
421
422 Multiple Instruction Single Data
423 The previous example, the mutex, the code it owns, and the data it pro‐
424 tects was enclosed in one function. The next example uses C++ features
425 to accommodate many functions that use just one mutex to protect one
426 data:
427
428 /* CC thisfile.c -lthread use C++ to compile*/
429
430 #define _REENTRANT
431 #include <stdlib.h>
432 #include <stdio.h>
433 #include <thread.h>
434 #include <errno.h>
435 #include <iostream.h>
436 #define NUM_THREADS 16
437 void *change_global_data(void *); /* for thr_create() */
438
439 class Mutected {
440 private:
441 static mutex_t Global_mutex;
442 static int Global_data;
443 public:
444 static int add_to_global_data(void);
445 static int subtract_from_global_data(void);
446 };
447
448 int Mutected::Global_data = 0;
449 mutex_t Mutected::Global_mutex;
450
451 int Mutected::add_to_global_data() {
452 mutex_lock(&Global_mutex);
453 Global_data++;
454 mutex_unlock(&Global_mutex);
455 return Global_data;
456 }
457
458 int Mutected::subtract_from_global_data() {
459 mutex_lock(&Global_mutex);
460 Global_data--;
461 mutex_unlock(&Global_mutex);
462 return Global_data;
463 }
464
465 void
466 main(int argc,char * argv[]) {
467 int i=0;
468 for (i=0;i< NUM_THREADS;i++) {
469 thr_create(NULL,0,change_global_data,NULL,0,NULL);
470 }
471 while ((thr_join(NULL,NULL,NULL) == 0));
472 }
473
474 void * change_global_data(void *) {
475 static int switcher = 0;
476 if ((switcher++ % 3) == 0) /* one-in-three threads subtracts */
477 cout << Mutected::subtract_from_global_data() << endl;
478 else
479 cout << Mutected::add_to_global_data() << endl;
480 return NULL;
481 }
482
483
484 Interprocess Locking
485 A mutex can protect data that is shared among processes. The mutex
486 would need to be initialized as USYNC_PROCESS. One process initializes
487 the process-shared mutex and writes it to a file to be mapped into
488 memory by all cooperating processes (see mmap(2)). Afterwards, other
489 independent processes can run the same program (whether concurrently or
490 not) and share mutex-protected data.
491
492 /* cc thisfile.c -lthread */
493 /* To execute, run the command line "a.out 0 &; a.out 1" */
494
495 #define _REENTRANT
496 #include <sys/types.h>
497 #include <sys/mman.h>
498 #include <sys/stat.h>
499 #include <fcntl.h>
500 #include <stdio.h>
501 #include <thread.h>
502 #define INTERPROCESS_FILE "ipc-sharedfile"
503 #define NUM_ADDTHREADS 12
504 #define NUM_SUBTRACTTHREADS 10
505 #define INCREMENT '0'
506 #define DECREMENT '1'
507 typedef struct {
508 mutex_t Interprocess_mutex;
509 int Interprocess_data;
510 } buffer_t;
511 buffer_t *buffer;
512
513 void *add_interprocess_data(), *subtract_interprocess_data();
514 void create_shared_memory(), test_argv();
515 int zeroed[sizeof(buffer_t)];
516 int ipc_fd, i=0;
517
518 void
519 main(int argc,char * argv[]){
520 test_argv(argv[1]);
521
522 switch (*argv[1]) {
523 case INCREMENT:
524 /* Initializes the process-shared mutex */
525 /* Should be run prior to running a DECREMENT process */
526 create_shared_memory();
527 ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
528 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
529 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
530 buffer->Interprocess_data = 0;
531 mutex_init(&buffer->Interprocess_mutex, USYNC_PROCESS,0);
532 for (i=0; i< NUM_ADDTHREADS; i++)
533 thr_create(NULL, 0, add_interprocess_data, argv[1],
534 0, NULL);
535 break;
536
537 case DECREMENT:
538 /* Should be run after the INCREMENT process has run. */
539 while(ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
540 sleep(1);
541 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
542 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
543 for (i=0; i< NUM_SUBTRACTTHREADS; i++)
544 thr_create(NULL, 0, subtract_interprocess_data, argv[1],
545 0, NULL);
546 break;
547 } /* end switch */
548
549 while ((thr_join(NULL,NULL,NULL) == 0));
550 } /* end main */
551
552 void *add_interprocess_data(char argv_1[]){
553 mutex_lock(&buffer->Interprocess_mutex);
554 buffer->Interprocess_data++;
555 sleep(2);
556 printf("%d is add-interprocess data, and %c is argv1\n",
557 buffer->Interprocess_data, argv_1[0]);
558 mutex_unlock(&buffer->Interprocess_mutex);
559 return NULL;
560 }
561
562 void *subtract_interprocess_data(char argv_1[]) {
563 mutex_lock(&buffer->Interprocess_mutex);
564 buffer->Interprocess_data--;
565 sleep(2);
566 printf("%d is subtract-interprocess data, and %c is argv1\n",
567 buffer->Interprocess_data, argv_1[0]);
568 mutex_unlock(&buffer->Interprocess_mutex);
569 return NULL;
570 }
571
572 void create_shared_memory(){
573 int i;
574 ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR );
575 for (i=0; i<sizeof(buffer_t); i++){
576 zeroed[i] = 0;
577 write(ipc_fd, &zeroed[i],2);
578 }
579 close(ipc_fd);
580 chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
581 }
582
583 void test_argv(char argv1[]) {
584 if (argv1 == NULL) {
585 printf("use 0 as arg1 for initial process\n \
586 or use 1 as arg1 for the second process\n");
587 exit(NULL);
588 }
589 }
590
591
592 Solaris Interprocess Robust Locking
593 A mutex can protect data that is shared among processes robustly. The
594 mutex would need to be initialized as USYNC_PROCESS | LOCK_ROBUST. One
595 process initializes the robust process-shared mutex and writes it to a
596 file to be mapped into memory by all cooperating processes (see
597 mmap(2)). Afterwards, other independent processes can run the same pro‐
598 gram (whether concurrently or not) and share mutex-protected data.
599
600
601 The following example shows how to use a USYNC_PROCESS | LOCK_ROBUST
602 type mutex.
603
604 /* cc thisfile.c -lthread */
605 /* To execute, run the command line "a.out & a.out 1" */
606 #include <sys/types.h>
607 #include <sys/mman.h>
608 #include <fcntl.h>
609 #include <stdio.h>
610 #include <thread.h>
611 #define INTERPROCESS_FILE "ipc-sharedfile"
612 typedef struct {
613 mutex_t Interprocess_mutex;
614 int Interprocess_data;
615 } buffer_t;
616 buffer_t *buffer;
617 int make_date_consistent();
618 void create_shared_memory();
619 int zeroed[sizeof(buffer_t)];
620 int ipc_fd, i=0;
621 main(int argc,char * argv[]) {
622 int rc;
623 if (argc > 1) {
624 while((ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
625 sleep(1);
626 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
627 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
628 mutex_init(&buffer->Interprocess_mutex,
629 USYNC_PROCESS | LOCK_ROBUST,0);
630 } else {
631 create_shared_memory();
632 ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
633 buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
634 PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
635 buffer->Interprocess_data = 0;
636 mutex_init(&buffer->Interprocess_mutex,
637 USYNC_PROCESS | LOCK_ROBUST,0);
638 }
639 for(;;) {
640 rc = mutex_lock(&buffer->Interprocess_mutex);
641 switch (rc) {
642 case EOWNERDEAD:
643 /*
644 * The lock is acquired.
645 * The last owner died holding the lock.
646 * Try to make the state associated with
647 * the mutex consistent.
648 * If successful, make the robust lock consistent.
649 */
650 if (make_data_consistent())
651 mutex_consistent(&buffer->Interprocess_mutex);
652 mutex_unlock(&buffer->Interprocess_mutex);
653 break;
654 case ENOTRECOVERABLE:
655 /*
656 * The lock is not acquired.
657 * The last owner got the mutex with EOWNERDEAD
658 * and failed to make the data consistent.
659 * There is no way to recover, so just exit.
660 */
661 exit(1);
662 case 0:
663 /*
664 * There is no error - data is consistent.
665 * Do something with data.
666 */
667 mutex_unlock(&buffer->Interprocess_mutex);
668 break;
669 }
670 }
671 } /* end main */
672 void create_shared_memory() {
673 int i;
674 ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR );
675 for (i=0; i<sizeof(buffer_t); i++) {
676 zeroed[i] = 0;
677 write(ipc_fd, &zeroed[i],2);
678 }
679 close(ipc_fd);
680 chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
681 }
682
683 /* return 1 if able to make data consistent, otherwise 0. */
684 int make_data_consistent () {
685 buffer->Interprocess_data = 0;
686 return (1);
687 }
688
689
690 Dynamically Allocated Mutexes
691 The following example allocates and frees memory in which a mutex is
692 embedded.
693
694 struct record {
695 int field1;
696 int field2;
697 mutex_t m;
698 } *r;
699 r = malloc(sizeof(struct record));
700 mutex_init(&r->m, USYNC_THREAD, NULL);
701 /*
702 * The fields in this record are accessed concurrently
703 * by acquiring the embedded lock.
704 */
705
706
707
708 The thread execution in this example is as follows:
709
710 Thread 1 executes: Thread 2 executes:
711
712 ... ...
713 mutex_lock(&r->m); mutex_lock(&r->m);
714 r->field1++; localvar = r->field1;
715 mutex_unlock(&r->m); mutex_unlock(&r->m);
716 ... ...
717
718
719
720 Later, when a thread decides to free the memory pointed to by r, the
721 thread should call mutex_destroy() on the mutexes in this memory.
722
723
724 In the following example, the main thread can do a thr_join() on both
725 of the above threads. If there are no other threads using the memory in
726 r, the main thread can now safely free r:
727
728 for (i = 0; i < 2; i++)
729 thr_join(0, 0, 0);
730 mutex_destroy(&r->m); /* first destroy mutex */
731 free(r); /* then free memory */
732
733
734
735 If the mutex is not destroyed, the program could have memory leaks.
736
738 See attributes(5) for descriptions of the following attributes:
739
740
741
742
743 ┌─────────────────────────────┬─────────────────────────────┐
744 │ ATTRIBUTE TYPE │ ATTRIBUTE VALUE │
745 ├─────────────────────────────┼─────────────────────────────┤
746 │Interface Stability │Stable │
747 ├─────────────────────────────┼─────────────────────────────┤
748 │MT-Level │MT-Safe │
749 └─────────────────────────────┴─────────────────────────────┘
750
752 mmap(2), shmop(2), pthread_mutexattr_getprioceiling(3C), pthread_mutex‐
753 attr_getprotocol(3C), pthread_mutexattr_getrobust(3C), pthread_mutex‐
754 attr_gettype(3C), pthread_mutex_getprioceiling(3C),
755 pthread_mutex_init(3C), attributes(5), mutex(5), standards(5)
756
758 Previous releases of Solaris provided the USYNC_PROCESS_ROBUST mutex
759 type. This type is now deprecated but is still supported for source and
760 binary compatibility. When passed to mutex_init(), it is transformed
761 into (USYNC_PROCESS | LOCK_ROBUST). The former method for restoring a
762 USYNC_PROCESS_ROBUST mutex to a consistent state was to reinitialize it
763 by calling mutex_init(). This method is still supported for source and
764 binary compatibility, but the proper method is to call mutex_consis‐
765 tent().
766
767
768 The USYNC_PROCESS_ROBUST type permitted an alternate error value,
769 ELOCKUNMAPPED, to be returned by mutex_lock() if the process containing
770 a locked robust mutex unmapped the memory containing the mutex or per‐
771 formed one of the exec(2) functions. The ELOCKUNMAPPED error value
772 implies all of the consequences of the EOWNERDEAD error value and as
773 such is just a synonym for EOWNERDEAD. For full source and binary com‐
774 patibility, the ELOCKUNMAPPED error value is still returned from
775 mutex_lock() in these circumstances, but only if the mutex was initial‐
776 ized with the USYNC_PROCESS_ROBUST type. Otherwise, EOWNERDEAD is
777 returned in these circumstances.
778
779
780 The mutex_lock(), mutex_unlock(), and mutex_trylock() functions do not
781 validate the mutex type. An uninitialized mutex or a mutex with an
782 invalid type does not return EINVAL. Interfaces for mutexes with an
783 invalid type have unspecified behavior.
784
785
786 Uninitialized mutexes that are allocated locally could contain junk
787 data. Such mutexes need to be initialized using mutex_init().
788
789
790 By default, if multiple threads are waiting for a mutex, the order of
791 acquisition is undefined.
792
793
794
795SunOS 5.11 5 Jun 2007 mutex_init(3C)