Yolinux.com

pthread_mutex_destroy manpage

Search topic Section
Get manual page for the search topic
List all commands matching the search topic
List all topics in the manpage index

PTHREAD_MUTEX_DESTROY(P)   POSIX Programmer's Manual  PTHREAD_MUTEX_DESTROY(P)



PROLOG
       This  manual  page is part of the POSIX Programmer's Manual.  The Linux
       implementation of this interface may differ (consult the	 corresponding
       Linux  manual page for details of Linux behavior), or the interface may
       not be implemented on Linux.

NAME
       pthread_mutex_destroy, pthread_mutex_init - destroy  and	 initialize  a
       mutex

SYNOPSIS
       #include <pthread.h>

       int pthread_mutex_destroy(pthread_mutex_t *mutex);
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,
	      const pthread_mutexattr_t *restrict attr);
       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


DESCRIPTION
       The  pthread_mutex_destroy()  function  shall  destroy the mutex object
       referenced by mutex; the mutex object becomes,  in  effect,  uninitial-
       ized.  An  implementation  may cause pthread_mutex_destroy() to set the
       object referenced by mutex to  an  invalid  value.  A  destroyed	 mutex
       object  can be reinitialized using pthread_mutex_init(); the results of
       otherwise referencing the object after it has been destroyed are	 unde-
       fined.

       It  shall  be  safe  to	destroy an initialized mutex that is unlocked.
       Attempting to destroy a locked mutex results in undefined behavior.

       The pthread_mutex_init() function shall initialize the mutex referenced
       by  mutex  with	attributes  specified  by  attr.  If attr is NULL, the
       default mutex attributes are used; the effect  shall  be	 the  same  as
       passing the address of a default mutex attributes object. Upon success-
       ful initialization, the state of	 the  mutex  becomes  initialized  and
       unlocked.

       Only  mutex  itself  may	 be  used for performing synchronization.  The
       result	of   referring	 to   copies   of   mutex    in	   calls    to
       pthread_mutex_lock(),  pthread_mutex_trylock(), pthread_mutex_unlock(),
       and pthread_mutex_destroy() is undefined.

       Attempting to initialize an already initialized mutex results in	 unde-
       fined behavior.

       In  cases  where	 default  mutex	 attributes are appropriate, the macro
       PTHREAD_MUTEX_INITIALIZER can be used to initialize  mutexes  that  are
       statically  allocated.  The  effect shall be equivalent to dynamic ini-
       tialization by a call to pthread_mutex_init() with parameter attr spec-
       ified as NULL, except that no error checks are performed.

RETURN VALUE
       If  successful,	the  pthread_mutex_destroy()  and pthread_mutex_init()
       functions shall return  zero;  otherwise,  an  error  number  shall  be
       returned to indicate the error.

       The  [EBUSY]  and [EINVAL] error checks, if implemented, act as if they
       were performed immediately at the beginning of processing for the func-
       tion  and  shall	 cause an error return prior to modifying the state of
       the mutex specified by mutex.

ERRORS
       The pthread_mutex_destroy() function may fail if:

       EBUSY  The implementation has detected an attempt to destroy the object
	      referenced  by mutex while it is locked or referenced (for exam-
	      ple,  while  being  used	in   a	 pthread_cond_timedwait()   or
	      pthread_cond_wait()) by another thread.

       EINVAL The value specified by mutex is invalid.


       The pthread_mutex_init() function shall fail if:

       EAGAIN The system lacked the necessary resources (other than memory) to
	      initialize another mutex.

       ENOMEM Insufficient memory exists to initialize the mutex.

       EPERM  The caller does not have the privilege to perform the operation.


       The pthread_mutex_init() function may fail if:

       EBUSY  The  implementation  has detected an attempt to reinitialize the
	      object referenced by mutex, a previously	initialized,  but  not
	      yet destroyed, mutex.

       EINVAL The value specified by attr is invalid.


       These functions shall not return an error code of [EINTR].

       The following sections are informative.

EXAMPLES
       None.

APPLICATION USAGE
       None.

RATIONALE
   Alternate Implementations Possible
       This volume of IEEE Std 1003.1-2001 supports several alternative imple-
       mentations of mutexes. An implementation may store the lock directly in
       the  object  of type pthread_mutex_t.  Alternatively, an implementation
       may store the lock in the heap and merely store a pointer,  handle,  or
       unique  ID in the mutex object. Either implementation has advantages or
       may be required on certain hardware configurations.  So	that  portable
       code  can  be  written that is invariant to this choice, this volume of
       IEEE Std 1003.1-2001 does not define assignment or  equality  for  this
       type, and it uses the term "initialize" to reinforce the (more restric-
       tive) notion that the lock may actually	reside	in  the	 mutex	object
       itself.

       Note that this precludes an over-specification of the type of the mutex
       or condition variable and motivates the opaqueness of the type.

       An  implementation  is	permitted,   but   not	 required,   to	  have
       pthread_mutex_destroy()	store  an  illegal value into the mutex.  This
       may help detect erroneous programs that try to lock (or otherwise  ref-
       erence) a mutex that has already been destroyed.

   Tradeoff Between Error Checks and Performance Supported
       Many of the error checks were made optional in order to let implementa-
       tions trade off performance versus degree of error  checking  according
       to  the needs of their specific applications and execution environment.
       As a general rule, errors or conditions caused by the system  (such  as
       insufficient  memory)  always need to be reported, but errors due to an
       erroneously coded application (such as failing to provide adequate syn-
       chronization  to	 prevent  a mutex from being deleted while in use) are
       made optional.

       A wide range of implementations is thus made possible. For example,  an
       implementation  intended for application debugging may implement all of
       the error checks, but an implementation running a single, provably cor-
       rect  application under very tight performance constraints in an embed-
       ded computer might implement minimal checks.  An	 implementation	 might
       even be provided in two versions, similar to the options that compilers
       provide: a full-checking, but slower version; and  a  limited-checking,
       but faster version. To forbid this optionality would be a disservice to
       users.

       By carefully limiting the use of "undefined behavior"  only  to	things
       that  an	 erroneous (badly coded) application might do, and by defining
       that  resource-not-available  errors  are  mandatory,  this  volume  of
       IEEE Std 1003.1-2001  ensures  that  a  fully-conforming application is
       portable across the full range of implementations,  while  not  forcing
       all implementations to add overhead to check for numerous things that a
       correct program never does.

   Why No Limits are Defined
       Defining symbols for the maximum number of mutexes and condition	 vari-
       ables  was  considered but rejected because the number of these objects
       may change dynamically. Furthermore, many implementations  place	 these
       objects into application memory; thus, there is no explicit maximum.

   Static Initializers for Mutexes and Condition Variables
       Providing  for  static  initialization of statically allocated synchro-
       nization objects allows modules	with  private  static  synchronization
       variables  to avoid runtime initialization tests and overhead. Further-
       more, it simplifies the coding of self-initializing modules. Such  mod-
       ules  are  common  in C libraries, where for various reasons the design
       calls for self-initialization instead of requiring an  explicit	module
       initialization function to be called. An example use of static initial-
       ization follows.

       Without static initialization, a self-initializing routine foo()	 might
       look as follows:


	      static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
	      static pthread_mutex_t foo_mutex;


	      void foo_init()
	      {
		  pthread_mutex_init(&foo_mutex, NULL);
	      }


	      void foo()
	      {
		  pthread_once(&foo_once, foo_init);
		  pthread_mutex_lock(&foo_mutex);
		 /* Do work. */
		  pthread_mutex_unlock(&foo_mutex);
	      }

       With static initialization, the same routine could be coded as follows:


	      static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;


	      void foo()
	      {
		  pthread_mutex_lock(&foo_mutex);
		 /* Do work. */
		  pthread_mutex_unlock(&foo_mutex);
	      }

       Note that the static initialization both eliminates the	need  for  the
       initialization  test  inside pthread_once() and the fetch of &foo_mutex
       to  learn  the  address	to  be	passed	to   pthread_mutex_lock()   or
       pthread_mutex_unlock().

       Thus, the C code written to initialize static objects is simpler on all
       systems and is also faster on a large class of systems; those where the
       (entire) synchronization object can be stored in application memory.

       Yet  the	 locking  performance  question	 is  likely  to	 be raised for
       machines that require mutexes to be allocated out  of  special  memory.
       Such  machines  actually	 have  to  have mutexes and possibly condition
       variables contain pointers to the actual hardware  locks.   For	static
       initialization  to work on such machines, pthread_mutex_lock() also has
       to test whether or not the pointer to the actual lock  has  been	 allo-
       cated.  If it has not, pthread_mutex_lock() has to initialize it before
       use. The reservation of such resources can be made when the program  is
       loaded, and hence return codes have not been added to mutex locking and
       condition variable waiting to indicate failure to complete  initializa-
       tion.

       This  runtime  test  in	pthread_mutex_lock() would at first seem to be
       extra work; an extra test is required to see whether  the  pointer  has
       been  initialized.  On most machines this would actually be implemented
       as a fetch of the pointer, testing the pointer against zero,  and  then
       using  the  pointer  if it has already been initialized. While the test
       might seem to add extra work, the extra effort of testing a register is
       usually	negligible since no extra memory references are actually done.
       As more and more machines provide caches, the real expenses are	memory
       references, not instructions executed.

       Alternatively,  depending  on the machine architecture, there are often
       ways to eliminate all overhead in the most important case: on the  lock
       operations  that occur after the lock has been initialized. This can be
       done by shifting more overhead to the less frequent operation: initial-
       ization.	 Since out-of-line mutex allocation also means that an address
       has to be dereferenced to find the actual lock, one technique  that  is
       widely  applicable is to have static initialization store a bogus value
       for that address; in particular, an address that causes a machine fault
       to  occur. When such a fault occurs upon the first attempt to lock such
       a mutex, validity checks can be done, and then the correct address  for
       the  actual  lock can be filled in. Subsequent lock operations incur no
       extra overhead since they do not "fault".  This is merely one technique
       that  can be used to support static initialization, while not adversely
       affecting the performance of lock acquisition. No doubt there are other
       techniques that are highly machine-dependent.

       The locking overhead for machines doing out-of-line mutex allocation is
       thus similar for modules being  implicitly  initialized,	 where	it  is
       improved	 for those doing mutex allocation entirely inline.  The inline
       case is thus made much faster, and the out-of-line case is not signifi-
       cantly worse.

       Besides	the  issue of locking performance for such machines, a concern
       is raised that it is possible that threads would	 serialize  contending
       for  initialization locks when attempting to finish initializing stati-
       cally allocated mutexes. (Such finishing would typically involve taking
       an  internal  lock,  allocating	a  structure, storing a pointer to the
       structure in the mutex, and releasing the internal lock.)  First,  many
       implementations would reduce such serialization by hashing on the mutex
       address. Second, such serialization can only occur a bounded number  of
       times.  In particular, it can happen at most as many times as there are
       statically allocated  synchronization  objects.	Dynamically  allocated
       objects	 would	 still	be  initialized	 via  pthread_mutex_init()  or
       pthread_cond_init().

       Finally, if none of the above optimization techniques  for  out-of-line
       allocation  yields  sufficient  performance  for an application on some
       implementation, the application can avoid static	 initialization	 alto-
       gether  by explicitly initializing all synchronization objects with the
       corresponding pthread_*_init() functions, which are  supported  by  all
       implementations.	 An implementation can also document the tradeoffs and
       advise which initialization technique is more efficient for  that  par-
       ticular implementation.

   Destroying Mutexes
       A mutex can be destroyed immediately after it is unlocked. For example,
       consider the following code:


	      struct obj {
	      pthread_mutex_t om;
		  int refcnt;
		  ...
	      };


	      obj_done(struct obj *op)
	      {
		  pthread_mutex_lock(&op->om);
		  if (--op->refcnt == 0) {
		      pthread_mutex_unlock(&op->om);
	      (A)     pthread_mutex_destroy(&op->om);
	      (B)     free(op);
		  } else
	      (C)     pthread_mutex_unlock(&op->om);
	      }

       In this case obj is reference counted and obj_done() is called whenever
       a  reference to the object is dropped.  Implementations are required to
       allow an object to be destroyed and freed and potentially unmapped (for
       example,	 lines A and B) immediately after the object is unlocked (line
       C).

FUTURE DIRECTIONS
       None.

SEE ALSO
       pthread_mutex_getprioceiling()	   ,	  pthread_mutex_lock()	     ,
       pthread_mutex_timedlock()  ,  pthread_mutexattr_getpshared() , the Base
       Definitions volume of IEEE Std 1003.1-2001, <pthread.h>

COPYRIGHT
       Portions of this text are reprinted and reproduced in  electronic  form
       from IEEE Std 1003.1, 2003 Edition, Standard for Information Technology
       -- Portable Operating System Interface (POSIX),	The  Open  Group  Base
       Specifications  Issue  6,  Copyright  (C) 2001-2003 by the Institute of
       Electrical and Electronics Engineers, Inc and The Open  Group.  In  the
       event of any discrepancy between this version 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 .



IEEE/The Open Group		     2003	      PTHREAD_MUTEX_DESTROY(P)
YoLinux.com Home Page
YoLinux Tutorial Index
Privacy Policy | Advertise with us | Feedback Form |
Unauthorized copying or redistribution prohibited.
    Bookmark and Share