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