mutex_lock(3c) 맨 페이지 - 윈디하나의 솔라나라

개요

섹션
맨 페이지 이름
검색(S)

mutex_lock(3c)

mutex_init(3C)           Standard C Library Functions           mutex_init(3C)

NAME
       mutex_init,  mutex_lock, mutex_trylock, mutex_unlock, mutex_consistent,
       mutex_destroy - mutual exclusion locks

SYNOPSIS
       #include <synch.h>

       int mutex_init(mutex_t *mp, int type, void *arg);


       int mutex_lock(mutex_t *mp);


       int mutex_trylock(mutex_t *mp);


       int mutex_unlock(mutex_t *mp);


       int mutex_consistent(mutex_t *mp);


       int mutex_destroy(mutex_t *mp);

DESCRIPTION
       Mutual exclusion locks (mutexes) prevent multiple threads from simulta‐
       neously executing critical sections of code  that  access  shared  data
       (that  is, mutexes are used to serialize the execution of threads). All
       mutexes must be global. A successful call for a mutex lock  by  way  of
       mutex_lock()  will cause another thread that is also trying to lock the
       same mutex to block until the owner thread unlocks it  by  way  of  mu‐
       tex_unlock(). Threads within the same process or within other processes
       can share mutexes.


       Mutexes  can  synchronize  threads  within the same process or in other
       processes. Mutexes can be used to synchronize threads between processes
       if the mutexes are allocated in writable memory and  shared  among  the
       cooperating processes (see mmap(2)), and have been initialized for this
       task.

   Initialize
       Mutexes  are  either intra-process or inter-process, depending upon the
       argument passed implicitly or explicitly to the initialization of  that
       mutex. A statically allocated mutex does not need to be explicitly ini‐
       tialized;  by default, a statically allocated mutex is initialized with
       all zeros and its scope is set to be within the calling process.


       For inter-process synchronization, a mutex needs  to  be  allocated  in
       memory  shared between these processes. Since the memory for such a mu‐
       tex must be allocated dynamically, the mutex  needs  to  be  explicitly
       initialized using mutex_init().


       The  mutex_init()  function initializes the mutex referenced by mp with
       the type specified by type. Upon successful initialization the state of
       the mutex becomes initialized and unlocked.  Only  the  attribute  type
       LOCK_PRIO_PROTECT  uses  arg. The type argument must be one of the fol‐
       lowing:

       USYNC_THREAD

           The mutex can synchronize threads only in this process.


       USYNC_PROCESS

           The mutex  can  synchronize  threads  in  this  process  and  other
           processes. The object initialized with this attribute must be allo‐
           cated in memory shared between processes, either in System V shared
           memory  (see shmop(2)) or in memory mapped to a file (see mmap(2)).
           If the object is not allocated in such shared memory, it  will  not
           be shared between processes.



       The  type argument can be augmented by the bitwise-inclusive-OR of zero
       or more of the following flags:

       LOCK_ROBUST

           The mutex can synchronize threads robustly. At the time  of  thread
           or  process death, either by calling thr_exit() or exit() or due to
           process abnormal termination, the lock is unlocked if  is  held  by
           the  thread or process. The next owner of the mutex will acquire it
           with an error return of EOWNERDEAD.  The  application  must  always
           check  the return value from mutex_lock() for a mutex of this type.
           The new owner of this mutex should then attempt to make  the  state
           protected by the mutex consistent, since this state could have been
           left  inconsistent  when  the  last owner died. If the new owner is
           able to make the state consistent,  it  should  call  mutex_consis‐
           tent() to restore the state of the mutex and then unlock the mutex.
           All  subsequent  calls  to  mutex_lock() will then behave normally.
           Only the new owner can make the mutex consistent. If for any reason
           the new owner is not able to make the state consistent,  it  should
           not call mutex_consistent() but should simply unlock the mutex. All
           waiting  processes will be awakened and all subsequent calls to mu‐
           tex_lock() will fail in acquiring the mutex with an error value  of
           ENOTRECOVERABLE.  If  the  thread or process that acquired the lock
           with EOWNERDEAD terminates without unlocking the  mutex,  the  next
           owner will acquire the lock with an error value of EOWNERDEAD.

           The  memory  for  the  object to be initialized with this attribute
           must be zeroed before initialization. Any thread or process  inter‐
           ested  in the robust lock can call mutex_init() to potentially ini‐
           tialize it, provided that all such callers of mutex_init()  specify
           the same set of attribute flags. In this situation, if mutex_init()
           is  called  on  a previously initialized robust mutex, mutex_init()
           will not reinitialize the mutex and will  return  the  error  value
           EBUSY.


       LOCK_RECURSIVE

           A thread attempting to relock this mutex without first unlocking it
           will  succeed  in  locking the mutex. The mutex must be unlocked as
           many times as it is locked.


       LOCK_ERRORCHECK

           Unless LOCK_RECURSIVE is also set, a thread  attempting  to  relock
           this  mutex  without  first  unlocking it will return with an error
           rather than deadlocking itself. A thread attempting to unlock  this
           mutex without first owning it will return with an error.


       LOCK_PRIO_INHERIT

           When a thread is blocking higher priority threads because of owning
           one  or  more mutexes with the LOCK_PRIO_INHERIT attribute, it exe‐
           cutes at the higher of its priority or the priority of the  highest
           priority  thread waiting on any of the mutexes owned by this thread
           and initialized with this attribute.


       LOCK_PRIO_PROTECT

           When a thread  owns  one  or  more  mutexes  initialized  with  the
           LOCK_PRIO_PROTECT  attribute, it executes at the higher of its pri‐
           ority or the highest of the priority ceilings of  all  the  mutexes
           owned  by  this thread and initialized with this attribute, regard‐
           less of whether other threads are blocked on any of these  mutexes.
           When this attribute is specified, arg must point to an int contain‐
           ing the priority ceiling.



       See  pthread_mutexattr_getrobust(3C)  for more information about robust
       mutexes. The LOCK_ROBUST attribute is the same as the POSIX PTHREAD_MU‐
       TEX_ROBUST attribute.


       See pthread_mutexattr_settype(3C) for more information on recursive and
       error checking mutex types. The combination (LOCK_RECURSIVE |  LOCK_ER‐
       RORCHECK) is the same as the POSIX PTHREAD_MUTEX_RECURSIVE type. By it‐
       self, LOCK_ERRORCHECK is the same as the POSIX PTHREAD_MUTEX_ERRORCHECK
       type.


       The   LOCK_PRIO_INHERIT   attribute   is   the   same   as   the  POSIX
       PTHREAD_PRIO_INHERIT attribute. The LOCK_PRIO_PROTECT attribute is  the
       same  as  the  POSIX PTHREAD_PRIO_PROTECT attribute. See pthread_mutex‐
       attr_getprotocol(3C),     pthread_mutexattr_getprioceiling(3C),     and
       pthread_mutex_getprioceiling(3C)    for    a   full   discussion.   The
       LOCK_PRIO_INHERIT and LOCK_PRIO_PROTECT attributes are mutually  exclu‐
       sive.  Specifying  both of these attributes causes mutex_init() to fail
       with EINVAL.


       Initializing mutexes can also be accomplished by allocating  in  zeroed
       memory  (default),  in which case a type of USYNC_THREAD is assumed. In
       general, the following rules apply to mutex initialization:

           o      The same mutex must not  be  simultaneously  initialized  by
                  multiple threads.


           o      A mutex lock must not be reinitialized while in use by other
                  threads.



       These  rules  do  not apply to LOCK_ROBUST mutexes. See the description
       for LOCK_ROBUST above. If default mutex attributes are used, the  macro
       DEFAULTMUTEX  can be used to initialize mutexes that are statically al‐
       located.


       Default mutex initialization (intra-process):

         mutex_t mp;
         mutex_init(&mp, USYNC_THREAD, NULL);



       or

         mutex_t mp = DEFAULTMUTEX;



       Customized mutex initialization (inter-process):

         mutex_init(&mp, USYNC_PROCESS, NULL);



       Customized mutex initialization (inter-process robust):

         mutex_init(&mp, USYNC_PROCESS | LOCK_ROBUST, NULL);



       Statically allocated mutexes can also be initialized with macros speci‐
       fying LOCK_RECURSIVE and/or LOCK_ERRORCHECK:

       mutex_t mp = RECURSIVEMUTEX;

           Same as (USYNC_THREAD | LOCK_RECURSIVE)


       mutex_t mp = ERRORCHECKMUTEX;

           Same as (USYNC_THREAD | LOCK_ERRORCHECK)


       mutex_t mp = RECURSIVE_ERRORCHECKMUTEX;

           Same as (USYNC_THREAD | LOCK_RECURSIVE | LOCK_ERRORCHECK)


   Lock and Unlock
       A critical section of code is enclosed by a the call to lock the  mutex
       and the call to unlock the mutex to protect it from simultaneous access
       by multiple threads. Only one thread at a time may possess mutually ex‐
       clusive  access to the critical section of code that is enclosed by the
       mutex-locking call and the mutex-unlocking call,  whether  the  mutex's
       scope  is  intra-process or inter-process. A thread calling to lock the
       mutex either gets exclusive access to the code starting from  the  suc‐
       cessful  locking  until its call to unlock the mutex, or it waits until
       the mutex is unlocked by the thread that locked it.


       Mutexes have ownership, unlike semaphores. Although any thread,  within
       the  scope of a mutex, can get an unlocked mutex and lock access to the
       same critical section of code, only the  thread  that  locked  a  mutex
       should unlock it.


       If a thread waiting for a mutex receives a signal, upon return from the
       signal  handler,  the  thread resumes waiting for the mutex as if there
       was no interrupt. A mutex protects code, not data; therefore,  strongly
       bind  a  mutex with the data by putting both within the same structure,
       or at least within the same procedure.


       A call to mutex_lock() locks the mutex object referenced by mp. If  the
       mutex  is  already locked, the calling thread blocks until the mutex is
       freed; this will return with the mutex object referenced by mp  in  the
       locked state with the calling thread as its owner. If the current owner
       of a mutex tries to relock the mutex, it will result in deadlock.


       The mutex_trylock() function is the same as mutex_lock(), respectively,
       except  that  if  the  mutex  object referenced by mp is locked (by any
       thread, including the current thread),  the  call  returns  immediately
       with an error.


       The mutex_unlock() function are called by the owner of the mutex object
       referenced  by mp to release it. The mutex must be locked and the call‐
       ing thread must be the one that last locked the mutex (the  owner).  If
       there are threads blocked on the mutex object referenced by mp when mu‐
       tex_unlock() is called, the mp is freed, and the scheduling policy will
       determine which thread gets the mutex. If the calling thread is not the
       owner of the lock, no error status is returned, and the behavior of the
       program is undefined.

   Destroy
       The  mutex_destroy()  function  destroys the mutex object referenced by
       mp. The mutex object becomes uninitialized. The space used by  the  de‐
       stroyed  mutex  variable  is  not  freed. It needs to be explicitly re‐
       claimed.

RETURN VALUES
       If successful, these functions return 0. Otherwise, an error number  is
       returned.

ERRORS
       The mutex_init() function will fail if:

       EINVAL              The  value  specified  by  type  is invalid, or the
                           LOCK_PRIO_INHERIT and LOCK_PRIO_PROTECT  attributes
                           are both specified.



       The mutex_init() function will fail for LOCK_ROBUST type mutex if:

       EBUSY               The  mutex pointed to by mp was previously initial‐
                           ized and has not yet been destroyed.


       EINVAL              The mutex pointed to by mp was previously  initial‐
                           ized with a different set of attribute flags.



       The mutex_trylock() function will fail if:

       EBUSY               The mutex pointed to by mp is already locked.



       The mutex_lock() and mutex_trylock() functions will fail for a LOCK_RE‐
       CURSIVE mutex if:

       EAGAIN              The mutex could not be acquired because the maximum
                           number  of  recursive  locks for the mutex has been
                           reached.



       The mutex_lock() function will fail  for  a  LOCK_ERRORCHECK  and  non-
       LOCK_RECURSIVE mutex if:

       EDEADLK             The caller already owns the mutex.



       The  mutex_lock()  function may fail for a non-LOCK_ERRORCHECK and non-
       LOCK_RECURSIVE mutex if:

       EDEADLK             The caller already owns the mutex.



       The mutex_unlock() function will fail for a LOCK_ERRORCHECK mutex if:

       EPERM               The caller does not own the mutex.



       The mutex_lock() or mutex_trylock() functions will fail for LOCK_ROBUST
       type mutex if:

       EOWNERDEAD          The last owner of this mutex died while holding the
                           mutex. This mutex is now owned by the  caller.  The
                           caller must now attempt to make the state protected
                           by  the mutex consistent. If it is able to clean up
                           the state, then it should restore the state of  the
                           mutex  by calling mutex_consistent() and unlock the
                           mutex. Subsequent calls to mutex_lock() will behave
                           normally, as before. If the caller is not  able  to
                           clean  up  the state, mutex_consistent() should not
                           be called but the mutex should be unlocked.  Subse‐
                           quent  calls  to  mutex_lock() will fail to acquire
                           the mutex, returning with the error  value  ENOTRE‐
                           COVERABLE.  If the owner who acquired the lock with
                           EOWNERDEAD dies, the next owner  will  acquire  the
                           lock with EOWNERDEAD.


       ENOTRECOVERABLE     The  mutex trying to be acquired was protecting the
                           state that has been left unrecoverable when the mu‐
                           tex's last owner could not make the state protected
                           by the mutex consistent. The mutex has not been ac‐
                           quired. This condition occurs  when  the  lock  was
                           previously  acquired  with EOWNERDEAD and the owner
                           was not able to clean up the state and unlocked the
                           mutex without calling mutex_consistent().



       The mutex_consistent() function will fail if:

       EINVAL              The caller does not own the mutex or the  mutex  is
                           not  a  LOCK_ROBUST  mutex  having  an inconsistent
                           state (EOWNERDEAD).


EXAMPLES
       Example 1 Single Gate



       The following example uses one global mutex as a gate-keeper to  permit
       each thread exclusive sequential access to the code within the user-de‐
       fined  function change_global_data(). This type of synchronization will
       protect the state of shared data, but it also prohibits parallelism.


         /* cc thisfile.c */
         #include <stdio.h>
         #include <thread.h>

         #define NUM_THREADS 12

         void *change_global_data(void *);     /*  for thr_create()   */

         void main(int argc, char *argv[]) {
                int i;
                for (i = 0; i < NUM_THREADS; i++) {
                        thr_create(NULL, 0, change_global_data, NULL, 0, NULL);
                }
                while ((thr_join(NULL, NULL, NULL) == 0));
         }

         void *change_global_data(void *null) {
                static mutex_t   Global_mutex;
                static int       Global_data = 0;

                mutex_lock(&Global_mutex);
                Global_data++;
                sleep(1);
                printf("%d is global data\n", Global_data);
                mutex_unlock(&Global_mutex);
                return NULL;
         }


       Example 2 Multiple Instruction Single Data



       In the previous example, the mutex, the code it owns, and the  data  it
       protects  were  all enclosed in one function. The next example uses C++
       features to accommodate many functions that use just one mutex to  pro‐
       tect one data:


         /* CC thisfile.c   use C++ to compile */

         #include <stdlib.h>
         #include <stdio.h>
         #include <thread.h>
         #include <errno.h>
         #include <iostream.h>

         #define NUM_THREADS 16
         void *change_global_data(void *);     /*  for thr_create()   */

         class Mutected {
                private:
                        static mutex_t      Global_mutex;
                        static int          Global_data;
                public:
                        static int          add_to_global_data(void);
                        static int          subtract_from_global_data(void);
         };

         int Mutected::Global_data = 0;
         mutex_t Mutected::Global_mutex;

         int Mutected::add_to_global_data() {
                mutex_lock(&Global_mutex);
                Global_data++;
                mutex_unlock(&Global_mutex);
                return Global_data;
         }

         int Mutected::subtract_from_global_data() {
                mutex_lock(&Global_mutex);
                Global_data--;
                mutex_unlock(&Global_mutex);
                return Global_data;
         }

         void
         main(int argc, char *argv[]) {
                int i;
                for (i = 0; i < NUM_THREADS; i++)  {
                     thr_create(NULL, 0, change_global_data, NULL, 0, NULL);
                }
                while ((thr_join(NULL, NULL, NULL) == 0));
         }

         void *change_global_data(void *) {
                static int switcher = 0;
                if ((switcher++ % 3) == 0) /* one-in-three threads subtracts */
                        cout << Mutected::subtract_from_global_data() << endl;
                else
                        cout << Mutected::add_to_global_data() << endl;
                return NULL;
         }


       Example 3 Interprocess Locking



       A  mutex  can  protect  data  that is shared among processes. The mutex
       would need to be initialized as USYNC_PROCESS. One process  initializes
       the process-shared mutex and writes it to a file to be mapped into mem‐
       ory  by all cooperating processes (see mmap(2)). Afterward, other inde‐
       pendent processes can run the same  program  (whether  concurrently  or
       not) and share mutex-protected data.


         /* cc thisfile.c */
         /* To execute, run the command line "a.out 0 &; a.out 1" */

         #include <sys/types.h>
         #include <sys/mman.h>
         #include <sys/stat.h>
         #include <fcntl.h>
         #include <stdio.h>
         #include <thread.h>

         #define INTERPROCESS_FILE "ipc-sharedfile"
         #define NUM_ADDTHREADS 12
         #define NUM_SUBTRACTTHREADS 10
         #define INCREMENT '0'
         #define DECREMENT '1'

         typedef struct {
             mutex_t     Interprocess_mutex;
             int         Interprocess_data;
         } buffer_t;
         buffer_t *buffer;

         void *add_interprocess_data(char argv_1[]);
         void *subtract_interprocess_data(char argv_1[]);
         void create_shared_memory(void), test_argv(char argv1[]);
         int zeroed[sizeof(buffer_t)];
         int ipc_fd, i=0;

         void
         main(int argc, char *argv[]) {
             test_argv(argv[1]);

             switch (*argv[1])  {
             case INCREMENT:
                  /* Initializes the process-shared mutex */
                  /* Should be run prior to running a DECREMENT process */
                  create_shared_memory();
                  ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
                  buffer = (buffer_t *) mmap(NULL, sizeof(buffer_t),
                      PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
                  buffer->Interprocess_data = 0;
                  mutex_init(&buffer->Interprocess_mutex, USYNC_PROCESS, 0);
                  for (i = 0; i < NUM_ADDTHREADS; i++)
                      thr_create(NULL, 0, add_interprocess_data, argv[1],
                                 0, NULL);
                  break;

             case DECREMENT:
                  /* Should be run after the INCREMENT process has run. */
                  while (ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
                      sleep(1);
                  buffer = (buffer_t *) mmap(NULL, sizeof(buffer_t),
                      PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
                  for (i = 0; i < NUM_SUBTRACTTHREADS; i++)
                      thr_create(NULL, 0, subtract_interprocess_data, argv[1],
                                 0, NULL);
                  break;
             } /* end switch */

             while ((thr_join(NULL, NULL, NULL) == 0));
         } /* end main */

         void *add_interprocess_data(char argv_1[]) {
             mutex_lock(&buffer->Interprocess_mutex);
             buffer->Interprocess_data++;
             sleep(2);
             printf("%d is add-interprocess data, and %c is argv1\n",
                 buffer->Interprocess_data, argv_1[0]);
             mutex_unlock(&buffer->Interprocess_mutex);
             return NULL;
         }

         void *subtract_interprocess_data(char argv_1[]) {
             mutex_lock(&buffer->Interprocess_mutex);
             buffer->Interprocess_data--;
             sleep(2);
             printf("%d is subtract-interprocess data, and %c is argv1\n",
                 buffer->Interprocess_data, argv_1[0]);
             mutex_unlock(&buffer->Interprocess_mutex);
             return NULL;
         }

         void create_shared_memory(void) {
             int i;
             ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR);
             for (i = 0; i < sizeof(buffer_t); i++){
                 zeroed[i] = 0;
                 write(ipc_fd, &zeroed[i], 2);
             }
             close(ipc_fd);
             chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
         }

         void test_argv(char argv1[]) {
             if (argv1 == NULL)   {
                 printf("use 0 as arg1 for initial process\n"
                     "or use 1 as arg1 for the second process\n");
                 exit(NULL);
             }
         }


       Example 4 Solaris Interprocess Robust Locking



       A  mutex  can protect data that is shared among processes robustly. The
       mutex would need to be initialized as USYNC_PROCESS | LOCK_ROBUST.  One
       process  initializes the robust process-shared mutex and writes it to a
       file to be  mapped  into  memory  by  all  cooperating  processes  (see
       mmap(2)).  Afterward, other independent processes can run the same pro‐
       gram (whether concurrently or not) and share mutex-protected data.



       The following example shows how to use a  USYNC_PROCESS  |  LOCK_ROBUST
       type mutex.


         /* cc thisfile.c */
         /* To execute, run the command line "a.out & a.out 1" */
         #include <sys/types.h>
         #include <sys/mman.h>
         #include <fcntl.h>
         #include <stdio.h>
         #include <thread.h>

         #define INTERPROCESS_FILE "ipc-sharedfile"

         typedef struct {
             mutex_t   Interprocess_mutex;
             int       Interprocess_data;
         } buffer_t;
         buffer_t *buffer;

         int make_data_consistent(void);
         void create_shared_memory(void);
         int zeroed[sizeof(buffer_t)];
         int ipc_fd, i = 0;

         void main(int argc, char *argv[]) {
             int rc;
             if (argc > 1) {
                 while((ipc_fd = open(INTERPROCESS_FILE, O_RDWR)) == -1)
                     sleep(1);
                 buffer = (buffer_t *) mmap(NULL, sizeof(buffer_t),
                          PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
                 mutex_init(&buffer->Interprocess_mutex,
                            USYNC_PROCESS | LOCK_ROBUST, 0);
             } else {
                 create_shared_memory();
                 ipc_fd = open(INTERPROCESS_FILE, O_RDWR);
                 buffer = (buffer_t *) mmap(NULL, sizeof(buffer_t),
                          PROT_READ | PROT_WRITE, MAP_SHARED, ipc_fd, 0);
                 buffer->Interprocess_data = 0;
                 mutex_init(&buffer->Interprocess_mutex,
                            USYNC_PROCESS | LOCK_ROBUST, 0);
             }
             for(;;) {
                 rc = mutex_lock(&buffer->Interprocess_mutex);
                 switch (rc) {
                     case EOWNERDEAD:
                       /*
                        * The lock is acquired.
                        * The last owner died holding the lock.
                        * Try to make the state associated with
                        * the mutex consistent.
                        * If successful, make the robust lock consistent.
                        */
                       if (make_data_consistent())
                           mutex_consistent(&buffer->Interprocess_mutex);
                       mutex_unlock(&buffer->Interprocess_mutex);
                       break;
                     case ENOTRECOVERABLE:
                       /*
                        * The lock is not acquired.
                        * The last owner got the mutex with EOWNERDEAD
                        * and failed to make the data consistent.
                        * There is no way to recover, so just exit.
                        */
                       exit(1);
                     case 0:
                       /*
                        * There is no error - data is consistent.
                        * Do something with data.
                        */
                       mutex_unlock(&buffer->Interprocess_mutex);
                       break;
                }
           }
         } /* end main */

         void create_shared_memory(void) {
              int i;
              ipc_fd = creat(INTERPROCESS_FILE, O_CREAT | O_RDWR);
              for (i = 0; i < sizeof(buffer_t); i++) {
                   zeroed[i] = 0;
                   write(ipc_fd, &zeroed[i], 2);
              }
              close(ipc_fd);
              chmod(INTERPROCESS_FILE, S_IRWXU | S_IRWXG | S_IRWXO);
         }

         /* return 1 if able to make data consistent, otherwise 0. */
         int make_data_consistent (void) {
             buffer->Interprocess_data = 0;
             return (1);
         }


       Example 5 Dynamically Allocated Mutexes



       The  following  example  allocates and frees memory in which a mutex is
       embedded.


         struct record {
                 int field1;
                 int field2;
                 mutex_t m;
         } *r;
         r = malloc(sizeof(struct record));
         mutex_init(&r->m, USYNC_THREAD, NULL);
          /*
           * The fields in this record are accessed concurrently
           * by acquiring the embedded lock.
           */




       The thread execution in this example is as follows:


         Thread 1 executes:                 Thread 2 executes:

         ...                                ...
         mutex_lock(&r->m);                 mutex_lock(&r->m);
         r->field1++;                       localvar = r->field1;
         mutex_unlock(&r->m);               mutex_unlock(&r->m);
         ...                                ...




       Later, when a thread decides to free the memory pointed to  by  r,  the
       thread should call mutex_destroy() on the mutexes in this memory.



       In  the  following example, the main thread can do a thr_join() on both
       of the above threads. If there are no other threads using the memory in
       r, the main thread can now safely free r:


         for (i = 0; i < 2; i++)
                thr_join(0, 0, 0);
         mutex_destroy(&r->m);   /* first destroy mutex */
         free(r);                /* then free memory */




       If the mutex is not destroyed, the program could have memory leaks.

ATTRIBUTES
       See attributes(7) for descriptions of the following attributes:

       tab() box; cw(2.75i) |cw(2.75i) lw(2.75i) |lw(2.75i) ATTRIBUTE  TYPEAT‐
       TRIBUTE VALUE _ Interface StabilityCommitted _ MT-LevelMT-Safe


SEE ALSO
       mmap(2),    shmop(2),   pthread_mutex_getprioceiling(3C),   pthread_mu‐
       tex_init(3C),   pthread_mutexattr_getprioceiling(3C),    pthread_mutex‐
       attr_getprotocol(3C),  pthread_mutexattr_getrobust(3C),  pthread_mutex‐
       attr_gettype(3C), attributes(7), mutex(7), standards(7)

NOTES
       Previous releases of Solaris provided  the  USYNC_PROCESS_ROBUST  mutex
       type. This type is now deprecated but is still supported for source and
       binary  compatibility.  When  passed to mutex_init(), it is transformed
       into (USYNC_PROCESS | LOCK_ROBUST). The former method for  restoring  a
       USYNC_PROCESS_ROBUST mutex to a consistent state was to reinitialize it
       by  calling mutex_init(). This method is still supported for source and
       binary compatibility, but the proper method is  to  call  mutex_consis‐
       tent().


       The  USYNC_PROCESS_ROBUST  type  permitted  an  alternate  error value,
       ELOCKUNMAPPED, to be returned by mutex_lock() if the process containing
       a locked robust mutex unmapped the memory containing the mutex or  per‐
       formed  one of the exec(2) functions. The ELOCKUNMAPPED error value im‐
       plies all of the consequences of the EOWNERDEAD error value and as such
       is just a synonym for EOWNERDEAD. For full source and  binary  compati‐
       bility,  the  ELOCKUNMAPPED  error  value  is  still  returned from mu‐
       tex_lock() in these circumstances, but only if the mutex  was  initial‐
       ized  with  the USYNC_PROCESS_ROBUST type. Otherwise, EOWNERDEAD is re‐
       turned in these circumstances.


       The mutex_lock(), mutex_unlock(), and mutex_trylock() functions do  not
       validate  the mutex type. An uninitialized mutex or a mutex with an in‐
       valid type does not return EINVAL. Interfaces for mutexes with  an  in‐
       valid type have unspecified behavior.


       Uninitialized  mutexes  that  are  allocated locally could contain junk
       data. Such mutexes need to be initialized using mutex_init().


       By default, if multiple threads are waiting for a mutex, the  order  of
       acquisition is undefined.

HISTORY
       The  mutex_consistent()  function  was added in Solaris 10 8/08 (Update
       6).


       The mutex_init(), mutex_destroy(), mutex_lock(),  mutex_trylock(),  and
       mutex_unlock() functions were added in Solaris 2.3.


       Definitions  for  the  following  type  values are available in Solaris
       starting with the listed release:

       tab() box; cw(3.67i)  |cw(1.83i)  lw(3.67i)  |lw(1.83i)  TYPERELEASE  _
       LOCK_ROBUST10  8/08  (Update 6) _ T{ LOCK_PRIO_NONE, LOCK_PRIO_INHERIT,
       LOCK_PRIO_PROTECT,  LOCK_ROBUST_NP  T}8  _   T{   USYNC_PROCESS_ROBUST,
       LOCK_ERRORCHECK, LOCK_RECURSIVE T}7 _ USYNC_PROCESS, USYNC_THREAD2.3



       USYNC_PROCESS_ROBUST  was  deprecated  and  replaced by USYNC_PROCESS |
       LOCK_ROBUST in Solaris 10 8/08 (Update 6).

Oracle Solaris 11.4               27 Aug 2025                   mutex_init(3C)
맨 페이지 내용의 저작권은 맨 페이지 작성자에게 있습니다.
RSS ATOM XHTML 5 CSS3