1mutex_init(3C)           Standard C Library Functions           mutex_init(3C)
2
3
4

NAME

6       mutex_init,  mutex_lock, mutex_trylock, mutex_unlock, mutex_consistent,
7       mutex_destroy - mutual exclusion locks
8

SYNOPSIS

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

DESCRIPTION

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

RETURN VALUES

293       If successful, these functions return 0. Otherwise, an error number  is
294       returned.
295

ERRORS

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

EXAMPLES

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

ATTRIBUTES

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

SEE ALSO

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

NOTES

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)
Impressum