8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / man / man3c / mutex_init.3c
bloba9b75a41551879e52ba8dc55de33dcc24896da47
1 '\" te
2 .\" Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
3 .\" Copyright (c) 2007, Sun Microsystems, Inc.  All Rights Reserved.
4 .\" Portions Copyright (c) 2001, the Institute of Electrical and Electronics Engineers, Inc. and The Open Group. All Rights Reserved.
5 .\" Portions Copyright (c) 1995 IEEE  All Rights Reserved.
6 .\" 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
7 .\" http://www.opengroup.org/bookstore/.
8 .\" 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.
9 .\"  This notice shall appear on any product containing this material.
10 .\" 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.
11 .\" 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.
12 .\" 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]
13 .TH MUTEX_INIT 3C "Sep 7, 2015"
14 .SH NAME
15 mutex_init, mutex_lock, mutex_trylock, mutex_unlock, mutex_consistent,
16 mutex_destroy \- mutual exclusion locks
17 .SH SYNOPSIS
18 .LP
19 .nf
20 cc -mt [ \fIflag\fR... ] \fIfile\fR... [ \fIlibrary\fR... ]
21 #include <thread.h>
22 #include <synch.h>
24 \fBint\fR \fBmutex_init\fR(\fBmutex_t *\fR\fImp\fR, \fBint\fR \fItype\fR, \fBvoid *\fR\fIarg\fR);
25 .fi
27 .LP
28 .nf
29 \fBint\fR \fBmutex_lock\fR(\fBmutex_t *\fR\fImp\fR);
30 .fi
32 .LP
33 .nf
34 \fBint\fR \fBmutex_trylock\fR(\fBmutex_t *\fR\fImp\fR);
35 .fi
37 .LP
38 .nf
39 \fBint\fR \fBmutex_unlock\fR(\fBmutex_t *\fR\fImp\fR);
40 .fi
42 .LP
43 .nf
44 \fBint\fR \fBmutex_consistent\fR(\fBmutex_t *\fR\fImp\fR);
45 .fi
47 .LP
48 .nf
49 \fBint\fR \fBmutex_destroy\fR(\fBmutex_t *\fR\fImp\fR);
50 .fi
52 .SH DESCRIPTION
53 .LP
54 Mutual exclusion locks (mutexes) prevent multiple threads from simultaneously
55 executing critical sections of code that access shared data (that is, mutexes
56 are used to serialize the execution of threads). All mutexes must be global. A
57 successful call for a mutex lock by way of  \fBmutex_lock()\fR will cause
58 another thread that is also trying to lock the same mutex to block until the
59 owner thread unlocks it by way of  \fBmutex_unlock()\fR. Threads within the
60 same process or within other processes can share mutexes.
61 .sp
62 .LP
63 Mutexes can synchronize threads within the same process or in other  processes.
64 Mutexes can be used to synchronize threads between processes if the mutexes are
65 allocated in writable memory and shared among the cooperating processes (see
66 \fBmmap\fR(2)), and have been initialized for this task.
67 .SS "Initialize"
68 .LP
69 Mutexes are either intra-process or inter-process, depending  upon the argument
70 passed implicitly or explicitly  to the initialization of that mutex. A
71 statically allocated mutex does not need to be explicitly  initialized; by
72 default, a statically allocated mutex is initialized  with all zeros and its
73 scope is set to be within the calling process.
74 .sp
75 .LP
76 For inter-process synchronization, a mutex needs to be allocated  in memory
77 shared between these processes. Since the memory for such a mutex must be
78 allocated dynamically,  the mutex needs to be explicitly initialized using
79 \fBmutex_init()\fR.
80 .sp
81 .LP
82 The  \fBmutex_init()\fR function initializes the mutex referenced by \fImp\fR
83 with the type specified by  \fItype\fR. Upon successful initialization the
84 state of the mutex becomes initialized and unlocked. Only the attribute type
85 \fBLOCK_PRIO_PROTECT\fR uses \fIarg\fR. The \fItype\fR argument must be one of
86 the following:
87 .sp
88 .ne 2
89 .na
90 \fB\fBUSYNC_THREAD\fR\fR
91 .ad
92 .sp .6
93 .RS 4n
94 The mutex can synchronize threads only in this process.
95 .RE
97 .sp
98 .ne 2
99 .na
100 \fB\fBUSYNC_PROCESS\fR\fR
102 .sp .6
103 .RS 4n
104 The mutex can synchronize threads in this process and other processes. The
105 object initialized with this attribute must be allocated in memory shared
106 between processes, either in System V shared memory (see  \fBshmop\fR(2)) or in
107 memory mapped to a file (see  \fBmmap\fR(2)). If the object is not allocated in
108 such shared memory, it will not be shared between processes.
113 The \fItype\fR argument can be augmented by the bitwise-inclusive-\fBOR\fR of
114 zero or more of the following flags:
116 .ne 2
118 \fB\fBLOCK_ROBUST\fR\fR
120 .sp .6
121 .RS 4n
122 The mutex can synchronize threads robustly. At the time of thread or process
123 death, either by calling \fBthr_exit()\fR or \fBexit()\fR or due to process
124 abnormal termination, the lock is unlocked if is held by the thread or process.
125 The next owner of the mutex will acquire it with an error return of
126 \fBEOWNERDEAD\fR. The application must always check the return value from
127 \fBmutex_lock()\fR for a mutex of this type. The new owner of this mutex should
128 then attempt to make the state protected by the mutex consistent, since this
129 state could have been left inconsistent when the last owner died. If the new
130 owner is able to make the state consistent, it should call
131 \fBmutex_consistent()\fR to restore the state of the mutex and then unlock the
132 mutex. All subsequent calls to \fBmutex_lock()\fR will then behave normally.
133 Only the new owner can make the mutex consistent. If for any reason the new
134 owner is not able to make the state consistent, it should not call
135 \fBmutex_consistent()\fR but should simply unlock the mutex. All waiting
136 processes will be awakened and all subsequent calls to \fBmutex_lock()\fR will
137 fail in acquiring the mutex with an error value of \fBENOTRECOVERABLE\fR. If
138 the thread or process that acquired the lock with \fBEOWNERDEAD\fR terminates
139 without unlocking the mutex, the next owner will acquire the lock with an error
140 value of \fBEOWNERDEAD\fR.
142 The memory for the object to be initialized with this attribute must be zeroed
143 before initialization. Any thread or process interested in the robust lock can
144 call \fBmutex_init()\fR to potentially initialize it, provided that all such
145 callers of \fBmutex_init()\fR specify the same set of attribute flags. In this
146 situation, if  \fBmutex_init()\fR is called on a previously initialized robust
147 mutex, \fBmutex_init()\fR will not reinitialize the mutex and will return the
148 error value \fBEBUSY\fR.
152 .ne 2
154 \fB\fBLOCK_RECURSIVE\fR\fR
156 .sp .6
157 .RS 4n
158 A thread attempting to relock this mutex without first unlocking it will
159 succeed in locking the mutex. The mutex must be unlocked as many times as it is
160 locked.
164 .ne 2
166 \fB\fBLOCK_ERRORCHECK\fR\fR
168 .sp .6
169 .RS 4n
170 Unless \fBLOCK_RECURSIVE\fR is also set, a thread attempting to relock this
171 mutex without first unlocking it will return with an error rather than
172 deadlocking itself.  A thread attempting to unlock this mutex without first
173 owning it will return with an error.
177 .ne 2
179 \fB\fBLOCK_PRIO_INHERIT\fR\fR
181 .sp .6
182 .RS 4n
183 When a thread is blocking higher priority threads because of owning one or more
184 mutexes with the \fBLOCK_PRIO_INHERIT\fR attribute, it executes at the higher
185 of its priority or the priority of the highest priority thread waiting on any
186 of the mutexes owned by this thread and initialized with this attribute.
190 .ne 2
192 \fB\fBLOCK_PRIO_PROTECT\fR\fR
194 .sp .6
195 .RS 4n
196 When a thread owns one or more mutexes initialized with the
197 \fBLOCK_PRIO_PROTECT\fR attribute, it executes at the higher of its priority or
198 the highest of the priority ceilings of all the mutexes owned by this thread
199 and initialized with this attribute, regardless of whether other threads are
200 blocked on any of these mutexes.  When this attribute is specified, \fIarg\fR
201 must point to an \fBint\fR containing the priority ceiling.
206 See \fBpthread_mutexattr_getrobust\fR(3C) for more information about robust
207 mutexes. The \fBLOCK_ROBUST\fR attribute is the same as the POSIX
208 \fBPTHREAD_MUTEX_ROBUST\fR attribute.
211 See \fBpthread_mutexattr_settype\fR(3C) for more information on recursive and
212 error checking mutex types. The combination (\fBLOCK_RECURSIVE\fR |
213 \fBLOCK_ERRORCHECK\fR) is the same as the POSIX \fBPTHREAD_MUTEX_RECURSIVE\fR
214 type. By itself, \fBLOCK_ERRORCHECK\fR is the same as the \fBPOSIX
215 PTHREAD_MUTEX_ERRORCHECK\fR type.
218 The \fBLOCK_PRIO_INHERIT\fR attribute is the same as the POSIX
219 \fBPTHREAD_PRIO_INHERIT\fR attribute. The \fBLOCK_PRIO_PROTECT\fR attribute is
220 the same as the POSIX \fBPTHREAD_PRIO_PROTECT\fR attribute. See
221 \fBpthread_mutexattr_getprotocol\fR(3C),
222 \fBpthread_mutexattr_getprioceiling\fR(3C), and
223 \fBpthread_mutex_getprioceiling\fR(3C) for a full discussion. The
224 \fBLOCK_PRIO_INHERIT\fR and \fBLOCK_PRIO_PROTECT\fR attributes are mutually
225 exclusive. Specifying both of these attributes causes \fBmutex_init()\fR to
226 fail with \fBEINVAL\fR.
229 Initializing mutexes can also be accomplished  by allocating in zeroed memory
230 (default), in which case a \fItype\fR of \fBUSYNC_THREAD\fR is assumed. In
231 general, the following rules apply to mutex initialization:
232 .RS +4
234 .ie t \(bu
235 .el o
236 The same mutex must not be simultaneously initialized by multiple threads.
238 .RS +4
240 .ie t \(bu
241 .el o
242 A mutex lock must not be reinitialized while in use by other threads.
246 These rules do not apply to \fBLOCK_ROBUST\fR mutexes. See the description for
247 \fBLOCK_ROBUST\fR above. If default mutex attributes are used, the macro
248 \fBDEFAULTMUTEX\fR can be used to initialize mutexes that are statically
249 allocated.
252 Default mutex initialization (intra-process):
254 .in +2
256 mutex_t mp;
257 mutex_init(&mp, USYNC_THREAD, NULL);
259 .in -2
265 .in +2
267 mutex_t  mp  =  DEFAULTMUTEX;
269 .in -2
273 Customized mutex initialization (inter-process):
275 .in +2
277 mutex_init(&mp, USYNC_PROCESS, NULL);
279 .in -2
283 Customized mutex initialization (inter-process robust):
285 .in +2
287 mutex_init(&mp, USYNC_PROCESS | LOCK_ROBUST, NULL);
289 .in -2
293 Statically allocated mutexes can also be initialized with macros specifying
294 \fBLOCK_RECURSIVE\fR and/or \fBLOCK_ERRORCHECK\fR:
296 .ne 2
298 \fB\fBmutex_t mp = RECURSIVEMUTEX;\fR\fR
300 .sp .6
301 .RS 4n
302 Same as (\fBUSYNC_THREAD\fR | \fBLOCK_RECURSIVE\fR)
306 .ne 2
308 \fB\fBmutex_t mp = ERRORCHECKMUTEX;\fR\fR
310 .sp .6
311 .RS 4n
312 Same as (\fBUSYNC_THREAD\fR | \fBLOCK_ERRORCHECK\fR)
316 .ne 2
318 \fB\fBmutex_t mp = RECURSIVE_ERRORCHECKMUTEX;\fR\fR
320 .sp .6
321 .RS 4n
322 Same as (\fBUSYNC_THREAD\fR | \fBLOCK_RECURSIVE\fR | \fBLOCK_ERRORCHECK\fR)
325 .SS "Lock and Unlock"
327 A critical section of code is enclosed by  a the call to lock the mutex and the
328 call to unlock the mutex to protect it from simultaneous access by multiple
329 threads. Only one thread at a time may possess mutually exclusive access to
330 the critical section of code that is enclosed by the mutex-locking call and the
331 mutex-unlocking call, whether the mutex's scope  is intra-process or
332 inter-process. A thread calling to lock the mutex either gets exclusive  access
333 to the code starting from the successful locking until its call to unlock the
334 mutex, or it waits until the mutex is unlocked by the thread that locked it.
337 Mutexes have ownership, unlike semaphores. Although any thread, within the
338 scope of a mutex, can get an unlocked mutex and lock access to the same
339 critical section of code, only the thread that locked a mutex should unlock it.
342 If a thread waiting for a mutex receives a signal, upon return from the signal
343 handler, the thread resumes waiting for the mutex as if there was no interrupt.
344 A mutex protects code, not data; therefore, strongly bind a mutex  with the
345 data by putting both within the same structure, or at least within the same
346 procedure.
349 A call to \fBmutex_lock()\fR locks the mutex object referenced by \fImp\fR. If
350 the mutex is already locked, the calling thread blocks until the mutex is
351 freed; this will return with the mutex object referenced by \fImp\fR in the
352 locked state with the calling thread as its owner. If the current owner of a
353 mutex tries to relock the mutex, it will result in deadlock.
356 The \fBmutex_trylock()\fR function is the same as \fBmutex_lock()\fR,
357 respectively, except that if the mutex object referenced by \fImp\fR is locked
358 (by any thread, including the current thread), the call returns immediately
359 with an error.
362 The \fBmutex_unlock()\fR function are called by the owner of the mutex object
363 referenced by \fImp\fR to release it. The mutex must be locked and the calling
364 thread must be the one that last locked the mutex (the owner). If there are
365 threads blocked on the mutex object referenced by \fImp\fR when
366 \fBmutex_unlock()\fR is called, the \fImp\fR is freed, and the scheduling
367 policy will determine which thread gets the mutex. If the calling thread is not
368 the owner of the lock, no error status is returned, and the behavior of the
369 program is undefined.
370 .SS "Destroy"
372 The \fBmutex_destroy()\fR function destroys the mutex object referenced by
373 \fImp\fR. The mutex object becomes uninitialized. The space used by the
374 destroyed mutex variable is not freed. It needs to be explicitly reclaimed.
375 .SH RETURN VALUES
377 If successful, these functions return \fB0\fR. Otherwise, an error number is
378 returned.
379 .SH ERRORS
381 The \fBmutex_init()\fR function will fail if:
383 .ne 2
385 \fB\fBEINVAL\fR\fR
387 .RS 10n
388 The value specified by \fItype\fR is invalid, or the \fBLOCK_PRIO_INHERIT\fR
389 and \fBLOCK_PRIO_PROTECT\fR attributes are both specified.
394 The \fBmutex_init()\fR function will fail for  \fBLOCK_ROBUST\fR type mutex if:
396 .ne 2
398 \fB\fBEBUSY\fR\fR
400 .RS 10n
401 The mutex pointed to by  \fImp\fR was previously initialized and has not yet
402 been destroyed.
406 .ne 2
408 \fB\fBEINVAL\fR\fR
410 .RS 10n
411 The mutex pointed to by \fImp\fR was previously initialized with a different
412 set of attribute flags.
417 The \fBmutex_trylock()\fR function will fail if:
419 .ne 2
421 \fB\fBEBUSY\fR\fR
423 .RS 9n
424 The mutex pointed to by \fImp\fR is already locked.
429 The \fBmutex_lock()\fR and \fBmutex_trylock()\fR functions will fail for a
430 \fBLOCK_RECURSIVE\fR mutex if:
432 .ne 2
434 \fB\fBEAGAIN\fR\fR
436 .RS 10n
437 The mutex could not be acquired because the maximum number of recursive locks
438 for the mutex has been reached.
443 The \fBmutex_lock()\fR function will fail for a \fBLOCK_ERRORCHECK\fR and
444 non-\fBLOCK_RECURSIVE\fR mutex if:
446 .ne 2
448 \fB\fBEDEADLK\fR\fR
450 .RS 11n
451 The caller already owns the mutex.
456 The \fBmutex_lock()\fR function may fail for a non-\fBLOCK_ERRORCHECK\fR and
457 non-\fBLOCK_RECURSIVE\fR mutex if:
459 .ne 2
461 \fB\fBEDEADLK\fR\fR
463 .RS 11n
464 The caller already owns the mutex.
469 The \fBmutex_unlock()\fR function will fail for a \fBLOCK_ERRORCHECK\fR mutex
472 .ne 2
474 \fB\fBEPERM\fR\fR
476 .RS 9n
477 The caller does not own the mutex.
482 The \fBmutex_lock()\fR or \fBmutex_trylock()\fR functions will fail for
483 \fBLOCK_ROBUST\fR type mutex if:
485 .ne 2
487 \fB\fBEOWNERDEAD\fR\fR
489 .RS 19n
490 The last owner of this mutex died while holding the mutex. This mutex is now
491 owned by the caller. The caller must now attempt to make the state protected by
492 the mutex consistent. If it is able to clean up the state, then it should
493 restore the state of the mutex by calling \fBmutex_consistent()\fR and unlock
494 the mutex. Subsequent calls to \fBmutex_lock()\fR will behave normally, as
495 before. If the caller is not able to clean up the state,
496 \fBmutex_consistent()\fR should not be called but the mutex should be unlocked.
497 Subsequent calls to \fBmutex_lock()\fR will fail to acquire the mutex,
498 returning with the error value \fBENOTRECOVERABLE\fR. If the owner who acquired
499 the lock with  \fBEOWNERDEAD\fR dies, the next owner will acquire the lock with
500 \fBEOWNERDEAD\fR.
504 .ne 2
506 \fB\fBENOTRECOVERABLE\fR\fR
508 .RS 19n
509 The mutex trying to be acquired was protecting the state that has been left
510 unrecoverable when the mutex's last owner could not make the state protected by
511 the mutex consistent. The mutex has not been acquired. This condition occurs
512 when the lock was previously acquired with \fBEOWNERDEAD\fR and the owner was
513 not able to clean up the state and unlocked the mutex without calling
514 \fBmutex_consistent()\fR.
519 The \fBmutex_consistent()\fR function will fail if:
521 .ne 2
523 \fB\fBEINVAL\fR\fR
525 .RS 10n
526 The caller does not own the mutex or the mutex is not a \fBLOCK_ROBUST\fR mutex
527 having an inconsistent state (\fBEOWNERDEAD\fR).
530 .SH EXAMPLES
531 .SS "Single Gate"
533 The following example uses one global mutex as a gate-keeper to permit each
534 thread exclusive sequential access to the code within the user-defined
535 function "change_global_data." This type of synchronization will protect the
536 state of shared data,  but it also prohibits parallelism.
538 .in +2
540 /* cc thisfile.c -lthread */
541 #define _REENTRANT
542 #include <stdio.h>
543 #include <thread.h>
544 #define NUM_THREADS 12
545 void *change_global_data(void *);     /*  for thr_create()   */
546 main(int argc,char * argv[])    {
547        int i=0;
548        for (i=0; i< NUM_THREADS; i++)   {
549                thr_create(NULL, 0, change_global_data, NULL, 0, NULL);
550        }
551        while ((thr_join(NULL, NULL, NULL) == 0));
554 void * change_global_data(void *null){
555        static mutex_t   Global_mutex;
556        static int       Global_data = 0;
557        mutex_lock(&Global_mutex);
558        Global_data++;
559        sleep(1);
560        printf("%d is global data\en",Global_data);
561        mutex_unlock(&Global_mutex);
562        return NULL;
565 .in -2
567 .SS "Multiple Instruction Single Data"
569 The previous example, the mutex, the code it owns, and the data it protects was
570 enclosed in one function. The next example uses C++ features to accommodate
571 many functions that use just one mutex to protect one data:
573 .in +2
575 /* CC thisfile.c -lthread   use C++ to compile*/
577 #define _REENTRANT
578 #include <stdlib.h>
579 #include <stdio.h>
580 #include <thread.h>
581 #include <errno.h>
582 #include <iostream.h>
583 #define NUM_THREADS 16
584 void *change_global_data(void *);     /*  for thr_create()   */
586 class Mutected {
587        private:
588                static mutex_t      Global_mutex;
589                static int          Global_data;
590        public:
591                static int          add_to_global_data(void);
592                static int          subtract_from_global_data(void);
595 int Mutected::Global_data = 0;
596 mutex_t Mutected::Global_mutex;
598 int Mutected::add_to_global_data()  {
599        mutex_lock(&Global_mutex);       
600        Global_data++;
601        mutex_unlock(&Global_mutex);     
602        return Global_data;
605 int Mutected::subtract_from_global_data()   {
606        mutex_lock(&Global_mutex);       
607        Global_data--;
608        mutex_unlock(&Global_mutex);
609        return Global_data;
612 void
613 main(int argc,char * argv[])  {
614        int i=0;
615        for (i=0;i< NUM_THREADS;i++)  {
616             thr_create(NULL,0,change_global_data,NULL,0,NULL);
617        }
618        while ((thr_join(NULL,NULL,NULL) == 0));
621 void * change_global_data(void *)       {
622        static int switcher = 0;
623        if ((switcher++ % 3) == 0)   /* one-in-three threads subtracts */
624                cout << Mutected::subtract_from_global_data() << endl;   
625        else
626                cout << Mutected::add_to_global_data() << endl;          
627        return NULL;
630 .in -2
632 .SS "Interprocess Locking"
634 A mutex can protect data that is shared among processes. The mutex would need
635 to be initialized as  \fBUSYNC_PROCESS\fR. One process initializes the
636 process-shared mutex and writes it to a file to be  mapped into memory by all
637 cooperating processes (see \fBmmap\fR(2)). Afterwards, other independent
638 processes can run the same program (whether concurrently or not) and share
639 mutex-protected data.
641 .in +2
643 /* cc thisfile.c -lthread */
644 /* To execute, run the command line "a.out 0 &; a.out 1" */
646 #define _REENTRANT
647 #include <sys/types.h>
648 #include <sys/mman.h>
649 #include <sys/stat.h>
650 #include <fcntl.h>
651 #include <stdio.h>
652 #include <thread.h>
653 #define INTERPROCESS_FILE "ipc-sharedfile"
654 #define NUM_ADDTHREADS 12
655 #define NUM_SUBTRACTTHREADS 10
656 #define INCREMENT '0'
657 #define DECREMENT '1'
658 typedef struct {
659                mutex_t     Interprocess_mutex;
660                int         Interprocess_data;
661 } buffer_t;
662 buffer_t *buffer;
664 void *add_interprocess_data(), *subtract_interprocess_data();
665 void create_shared_memory(), test_argv();
666 int zeroed[sizeof(buffer_t)];
667 int ipc_fd, i=0;
669 void
670 main(int argc,char * argv[]){
671     test_argv(argv[1]);
673     switch (*argv[1])  {
674     case INCREMENT:
675          /* Initializes the process-shared mutex */
676          /* Should be run prior to running a DECREMENT process */
677          create_shared_memory();
678          ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
679          buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
680              PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
681          buffer->Interprocess_data = 0;
682          mutex_init(&buffer->Interprocess_mutex, USYNC_PROCESS,0);
683          for (i=0; i< NUM_ADDTHREADS; i++)
684          thr_create(NULL, 0, add_interprocess_data, argv[1],
685              0, NULL);
686          break;
688     case DECREMENT:
689          /* Should be run after the INCREMENT process has run. */
690          while(ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
691              sleep(1);
692          buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
693              PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
694          for (i=0; i< NUM_SUBTRACTTHREADS; i++)
695          thr_create(NULL, 0, subtract_interprocess_data, argv[1],
696              0, NULL);
697          break;
698     } /* end switch */
700     while ((thr_join(NULL,NULL,NULL) == 0));
701 } /* end main */
703 void *add_interprocess_data(char argv_1[]){
704     mutex_lock(&buffer->Interprocess_mutex);
705     buffer->Interprocess_data++;
706     sleep(2);
707     printf("%d is add-interprocess data, and %c is argv1\en",
708         buffer->Interprocess_data, argv_1[0]);
709     mutex_unlock(&buffer->Interprocess_mutex);
710     return NULL;
713 void *subtract_interprocess_data(char argv_1[]) {
714     mutex_lock(&buffer->Interprocess_mutex);
715     buffer->Interprocess_data--;
716     sleep(2);
717     printf("%d is subtract-interprocess data, and %c is argv1\en",
718         buffer->Interprocess_data, argv_1[0]);
719     mutex_unlock(&buffer->Interprocess_mutex);
720     return NULL;
723 void create_shared_memory(){
724     int i;
725     ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR );
726     for (i=0; i<sizeof(buffer_t); i++){
727         zeroed[i] = 0;
728         write(ipc_fd, &zeroed[i],2);
729     }
730     close(ipc_fd);
731     chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
734 void test_argv(char argv1[])   {
735     if (argv1 == NULL)   {
736     printf("use 0 as arg1 for initial process\en \e
737     or use 1 as arg1 for the second process\en");
738     exit(NULL);
739     }
742 .in -2
744 .SS "Solaris Interprocess Robust Locking"
746 A mutex can protect data that is shared among processes robustly. The mutex
747 would need to be initialized as \fBUSYNC_PROCESS\fR | \fBLOCK_ROBUST\fR. One
748 process initializes the robust process-shared mutex and writes it to a file to
749 be mapped into memory by all cooperating processes (see \fBmmap\fR(2)).
750 Afterwards, other independent processes can run the same program (whether
751 concurrently or not) and share mutex-protected data.
754 The following example shows how to use a \fBUSYNC_PROCESS\fR |
755 \fBLOCK_ROBUST\fR type mutex.
757 .in +2
759 /* cc thisfile.c -lthread */
760  /* To execute, run the command line "a.out & a.out 1" */
761  #include <sys/types.h>
762  #include <sys/mman.h>
763  #include <fcntl.h>
764  #include <stdio.h>
765  #include <thread.h>
766  #define INTERPROCESS_FILE "ipc-sharedfile"
767  typedef struct {
768            mutex_t   Interprocess_mutex;
769            int       Interprocess_data;
770  } buffer_t;
771  buffer_t *buffer;
772  int make_date_consistent();
773  void create_shared_memory();
774  int zeroed[sizeof(buffer_t)];
775  int ipc_fd, i=0;
776  main(int argc,char * argv[])  {
777      int rc;
778      if (argc > 1) {
779          while((ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
780              sleep(1);
781          buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
782                    PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
783          mutex_init(&buffer->Interprocess_mutex,
784                      USYNC_PROCESS | LOCK_ROBUST, 0);
785      } else {
786          create_shared_memory();
787          ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
788          buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
789                PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
790          buffer->Interprocess_data = 0;
791          mutex_init(&buffer->Interprocess_mutex,
792                      USYNC_PROCESS | LOCK_ROBUST, 0);
793      }
794      for(;;) {
795          rc = mutex_lock(&buffer->Interprocess_mutex);
796          switch (rc) {
797              case EOWNERDEAD:
798                /*
799                 * The lock is acquired.
800                 * The last owner died holding the lock.
801                 * Try to make the state associated with
802                 * the mutex consistent.
803                 * If successful, make the robust lock consistent.
804                 */
805                if (make_data_consistent())
806                    mutex_consistent(&buffer->Interprocess_mutex);
807                    mutex_unlock(&buffer->Interprocess_mutex);
808                    break;
809              case ENOTRECOVERABLE:
810                /*
811                 * The lock is not acquired.
812                 * The last owner got the mutex with EOWNERDEAD
813                 * and failed to make the data consistent.
814                 * There is no way to recover, so just exit.
815                 */
816                exit(1);
817              case 0:
818                /*
819                 * There is no error - data is consistent.
820                 * Do something with data.
821                 */
822                mutex_unlock(&buffer->Interprocess_mutex);
823                break;
824         }
825    }
826 } /* end main */
827 void create_shared_memory() {
828       int i;
829       ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR );
830       for (i=0; i<sizeof(buffer_t); i++) {
831            zeroed[i] = 0;
832            write(ipc_fd, &zeroed[i],2);
833       }
834       close(ipc_fd);
835       chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
838  /* return 1 if able to make data consistent, otherwise 0. */
839  int make_data_consistent () {
840        buffer->Interprocess_data = 0;
841        return (1);
844 .in -2
846 .SS "Dynamically Allocated Mutexes"
848 The following example allocates and frees memory in which a mutex is embedded.
850 .in +2
852 struct record {
853         int field1;
854         int field2;
855         mutex_t m;
856 } *r;
857 r = malloc(sizeof(struct record));
858 mutex_init(&r->m, USYNC_THREAD, NULL);
860   * The fields in this record are accessed concurrently
861   * by acquiring the embedded lock.
862   */
864 .in -2
868 The thread execution in this example is as follows:
870 .in +2
872 \fIThread 1 executes:\fR                 \fIThread 2 executes:\fR
874 \&...                                ...
875 mutex_lock(&r->m);                 mutex_lock(&r->m);
876 r->field1++;                       localvar = r->field1;
877 mutex_unlock(&r->m);               mutex_unlock(&r->m);
878 \&...                                ...
880 .in -2
884 Later, when a thread decides to free the memory pointed to by  \fIr\fR, the
885 thread  should call  \fBmutex_destroy\fR(\|) on the mutexes in this memory.
888 In the following example, the main thread can do a  \fBthr_join\fR(\|) on both
889 of the above threads. If there are no other threads using the memory in
890 \fIr\fR, the main thread can now safely free \fIr\fR:
892 .in +2
894 for (i = 0; i < 2; i++)
895        thr_join(0, 0, 0);
896 mutex_destroy(&r->m);   /* first destroy mutex */
897 free(r);                /* then free memory */
899 .in -2
903 If the mutex is not destroyed, the program could have memory leaks.
904 .SH ATTRIBUTES
906 See \fBattributes\fR(5) for descriptions of the following attributes:
911 box;
912 c | c
913 l | l .
914 ATTRIBUTE TYPE  ATTRIBUTE VALUE
916 Interface Stability     Stable
918 MT-Level        MT-Safe
921 .SH SEE ALSO
923 \fBmmap\fR(2), \fBshmop\fR(2), \fBpthread_mutexattr_getprioceiling\fR(3C),
924 \fBpthread_mutexattr_getprotocol\fR(3C), \fBpthread_mutexattr_getrobust\fR(3C),
925 \fBpthread_mutexattr_gettype\fR(3C), \fBpthread_mutex_getprioceiling\fR(3C),
926 \fBpthread_mutex_init\fR(3C), \fBattributes\fR(5), \fBmutex\fR(5),
927 \fBstandards\fR(5)
928 .SH NOTES
930 Previous releases of Solaris provided the \fBUSYNC_PROCESS_ROBUST\fR mutex
931 type. This type is now deprecated but is still supported for source and binary
932 compatibility. When passed to \fBmutex_init()\fR, it is transformed into
933 (\fBUSYNC_PROCESS\fR | \fBLOCK_ROBUST\fR). The former method for restoring a
934 \fBUSYNC_PROCESS_ROBUST\fR mutex to a consistent state was to reinitialize it
935 by calling \fBmutex_init()\fR. This method is still supported for source and
936 binary compatibility, but the proper method is to call
937 \fBmutex_consistent()\fR.
940 The \fBUSYNC_PROCESS_ROBUST\fR type permitted an alternate error value,
941 \fBELOCKUNMAPPED\fR, to be returned by \fBmutex_lock()\fR if the process
942 containing a locked robust mutex unmapped the memory containing the mutex or
943 performed one of the \fBexec\fR(2) functions. The \fBELOCKUNMAPPED\fR error
944 value implies all of the consequences of the \fBEOWNERDEAD\fR error value and
945 as such is just a synonym for \fBEOWNERDEAD\fR. For full source and binary
946 compatibility, the \fBELOCKUNMAPPED\fR error value is still returned from
947 \fBmutex_lock()\fR in these circumstances, but only if the mutex was
948 initialized with the \fBUSYNC_PROCESS_ROBUST\fR type. Otherwise,
949 \fBEOWNERDEAD\fR is returned in these circumstances.
952 The \fBmutex_lock()\fR, \fBmutex_unlock()\fR, and \fBmutex_trylock()\fR
953 functions do not validate the mutex type. An uninitialized mutex or a mutex
954 with an invalid type does not return \fBEINVAL\fR. Interfaces for mutexes with
955 an invalid type have unspecified behavior.
958 Uninitialized mutexes that are allocated locally could contain junk data. Such
959 mutexes need to be initialized using \fBmutex_init()\fR.
962 By default, if multiple threads are waiting for a mutex, the order of
963 acquisition is undefined.