Use mutual exclusion locks (mutexes) to serialize thread execution. Mutual exclusion locks synchronize threads, usually by ensuring that only one thread at a time executes a critical section of code. Mutex locks can also preserve single-threaded code.
To change the default mutex attributes, you can declare and initialize an attribute object. Often, the mutex attributes are set in one place at the beginning of the application so they can be located quickly and modified easily. Table 4-1 lists the functions discussed in this section that manipulate mutex attributes.
Table 4-1 Mutex Attributes Routines
Operation |
Destination Discussion | |
---|---|---|
Initialize a mutex mttribute object | ||
Destroy a mutex attribute object | ||
Set the scope of a mutex | ||
Get the scope of a mutex | ||
Set the mutex type attribute | ||
Get the mutex type attribute | ||
Set mutex attribute's protocol | ||
Get mutex attribute's protocol | ||
Set mutex attribute's priority ceiling | ||
Get mutex attribute's priority ceiling | ||
Set mutex's priority ceiling | ||
Get mutex's priority ceiling | ||
Set mutex's robust attribute | ||
Get mutex's robust attribute |
The differences between Solaris threads and POSIX threads, when defining the scope of a mutex, are shown in Table 4-2.
Table 4-2 Mutex Scope Comparison
Solaris |
POSIX |
Definition |
---|---|---|
USYNC_PROCESS |
PTHREAD_PROCESS_SHARED |
Use to synchronize threads in this and other processes |
USYNC_PROCESS_ROBUST |
No POSIX equivalent |
Use to robustly synchronize threads between processes |
USYNC_THREAD |
PTHREAD_PROCESS_PRIVATE |
Use to synchronize threads in this process only |
Use pthread_mutexattr_init(3THR) to initialize attributes associated with this object to their default values. Storage for each attribute object is allocated by the threads system during execution.
The default value of the pshared attribute when this function is called is PTHREAD_PROCESS_PRIVATE, which means that the initialized mutex can be used within a process.
Prototype: int pthread_mutexattr_init(pthread_mutexattr_t *mattr);
#include <pthread.h> pthread_mutexattr_t mattr; int ret; /* initialize an attribute to default value */ ret = pthread_mutexattr_init(&mattr);
mattr is an opaque
type that contains a system-allocated attribute object. The possible values of mattr's scope are PTHREAD_PROCESS_PRIVATE (the default) and PTHREAD_PROCESS_SHARED.
Before a mutex attribute object can be reinitialized, it must first be destroyed by a call to pthread_mutexattr_destroy(3T). The pthread_mutexattr_init() call results in the allocation of an opaque object. If the object is not destroyed, a memory leak will result.
Returns zero after completing successfully. Any other returned value indicates that an error occurred. If either of the following conditions occurs, the function fails and returns the corresponding value.
pthread_mutexattr_destroy(3THR) deallocates the storage space used to maintain the attribute object created by pthread_mutexattr_init().
Prototype: int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)
#include <pthread.h> pthread_mutexattr_t mattr; int ret; /* destroy an attribute */ ret = pthread_mutexattr_destroy(&mattr);
pthread_mutexattr_destroy() returns zero after completing successfully. Any other returned value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
pthread_mutexattr_setpshared(3THR) sets the scope of the mutex variable.
The scope of a mutex variable can be either process private (intraprocess) or system wide (interprocess). If the mutex is created with the pshared attribute set to the PTHREAD_PROCESS_SHARED state, and it exists in shared memory, it can be shared among threads from more than one process. This is equivalent to the USYNC_PROCESS flag in mutex_init() in the original Solaris threads.
Prototype: int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared);
#include <pthread.h> pthread_mutexattr_t mattr; int ret; ret = pthread_mutexattr_init(&mattr); /* * resetting to its default value: private */ ret = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE);
If the mutex pshared attribute is set to PTHREAD_PROCESS_PRIVATE, only those threads created by the same process can operate on the mutex.
Returns zero after completing successfully. Any other returned value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
pthread_mutexattr_getpshared(3THR) returns the scope of the mutex variable defined by pthread_mutexattr_setpshared().
Prototype: int pthread_mutexattr_getpshared(pthread_mutexattr_t *mattr, int *pshared);
#include <pthread.h> pthread_mutexattr_t mattr; int pshared, ret; /* get pshared of mutex */ ret = pthread_mutexattr_getpshared(&mattr, &pshared);
Get the current value of pshared for the attribute object mattr. It is either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE.
Returns zero after completing successfully. Any other returned value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
#include <pthread.h> int pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type);
pthread_mutexattr_settype(3THR) sets the mutex type attribute. The default value of the type attribute is PTHREAD_MUTEX_DEFAULT.
The type argument specifies the type of mutex. Valid mutex types include:
PTHREAD_MUTEX_NORMAL
This type of mutex does not detect deadlock. A thread attempting to relock this mutex without first unlocking it will deadlock. Attempting to unlock a mutex locked by a different thread results in undefined behavior. Attempting to unlock an unlocked mutex results in undefined behavior.
PTHREAD_MUTEX_ERRORCHECK
This type of mutex provides error checking. A thread attempting to relock this mutex without first unlocking it will return with an error. A thread attempting to unlock a mutex which another thread has locked will return with an error. A thread attempting to unlock an unlocked mutex will return with an error.
PTHREAD_MUTEX_RECURSIVE
A thread attempting to relock this mutex without first unlocking it will succeed in locking the mutex. The relocking deadlock which can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple locks of this mutex require the same number of unlocks to release the mutex before another thread can acquire the mutex. A thread attempting to unlock a mutex which another thread has locked will return with an error. A thread attempting to unlock an unloc ked mutex will return with an error. This type of mutex is only supported for mutexes whose process shared attribute is PTHREAD_PROCESS_PRIVATE.
PTHREAD_MUTEX_DEFAULT
Attempting to recursively lock a mutex of this type results in undefined behaviour. Attempting to unlock a mutex of this type which was not locked by the calling thread results in undefined behaviour. Attempting to unlock a mutex of this type which is not locked results in undefined behaviour. An implementation is allowed to map this mutex to one of the other mutex types. (For Solaris threads, PTHREAD_PROCESS_DEFAULT is mapped to PTHREAD_PROCESS_NORMAL.)
If successful, the pthread_mutexattr_settype function returns zero. Otherwise, an error number is returned to indicate the error.
EINVAL
The value type is invalid.
EINVAL
The value specified by attr is invalid.
#include <pthread.h> int pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type);
pthread_mutexattr_gettype(3THR) gets the mutex type attribute set by pthread_mutexattr_settype(). The default value of the type attribute is PTHREAD_MUTEX_DEFAULT.
The type argument specifies the type of mutex. Valid mutex types include:
PTHREAD_MUTEX_NORMAL
PTHREAD_MUTEX_ERRORCHECK
PTHREAD_MUTEX_RECURSIVE
PTHREAD_MUTEX_DEFAULT
For a description of each type, see "pthread_mutexattr_settype(3THR)".
pthread_mutexattr_setprotocol(3T) sets the protocol attribute of a mutex attribute object.
#include <pthread.h> int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol);
attr points to a mutex attribute object created by an earlier call to pthread_mutexattr_init().
protocol defines the protocol applied to the mutex attribute object.
The value of protocol, defined in pthread.h, can be: PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT.
PTHREAD_PRIO_NONE
A thread's priority and scheduling are not affected by the mutex ownership.
PTHREAD_PRIO_INHERIT
This protocol value affects a thread's (such as thrd1) priority and scheduling when higher-priority threads block on one or more mutexes owned by thrd1 where those mutexes are initialized with PTHREAD_PRIO_INHERIT. thrd1 runs with the higher of its priority or the highest priority of any thread waiting on any of the mutexes owned by thrd1.
If thrd1 blocks on a mutex owned by another thread, thrd3, the same priority inheritance effect recursively propagates to thrd3.
Use PTHREAD_PRIO_INHERIT to avoid priority inversion. Priority inversion occurs when a low-priority thread holds a lock that a higher-priority thread wants. Because the higher-priority thread cannot continue until the lower-priority thread releases the lock, each thread is treated as if it had the inverse of its intended priority.
If the symbol _POSIX_THREAD_PRIO_INHERIT is defined, for a mutex initialized with the protocol attribute value PTHREAD_PRIO_INHERIT, the following actions occur in the Solaris Operating Environment when the owner of that mutex dies:
The behavior on owner death depends on the value of the robustness argument of pthread_mutexattr_setrobust_np().
The mutex is unlocked.
The next owner of the mutex acquires it with an error return of EOWNERDEAD.
The next owner of the mutex should try to make the state protected by the mutex consistent--the state might have been left inconsistent when the previous owner died. If the owner is successful in making the state consistent, call pthread_mutex_init() for the mutex and unlock the mutex.
If pthread_mutex_init() is called on a previously initialized, but not yet destroyed mutex, the mutex is not reiintialized.
If the owner is unable to make the state consistent, do not call pthread_mutex_init(), but unlock the mutex. In this event, all waiters will be woken up and all subsequent calls to pthread_mutex_lock() will fail to acquire the mutex and return an error code of ENOTRECOVERABLE. You can now make the mutex state consistent by calling pthread_mutex_destroy() to uninitialize the mutex and calling pthread_mutex_init() to reinitialize it.
If the thread that acquired the lock with EOWNERDEAD dies, the next owner acquires the lock with an error code of EOWNERDEAD.
PTHREAD_PRIO_PROTECT
This protocol value affects a thread's (such as thrd2) priority and scheduling when the thread owns one or more mutexes initialized with PTHREAD_PRIO_PROTECT. thrd2 runs with the higher of its priority or the highest-priority ceiling of all mutexes it owns. Higher-priority threads blocked on any of the mutexes, owned by thrd2, have no effect on the scheduling of thrd2.
When a thread owns a mutex that is intialized with PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT, and that thread's original priority changes, such as by a call to sched_setparam(), the scheduler does not move the thread to the tail of the scheduling queue at it's new priority. Similarly, when a thread unlocks a mutex that is intialized with PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT, and that thread's original priority changes, the scheduler does not move the thread to the tail of the scheduling queue at it's new priority.
If a thread simultaneously owns several mutexes initialized with a mix of PTHREAD_PRIO_INHERIT and PTHREAD_PRIO_PROTECT, it executes at the highest priority obtained by either of these protocols.
On successful completion, pthread_mutexattr_setprotocol() returns 0. Any other returned value indicates that an error occurred.
If either of the following conditions occurs, pthread_mutexattr_setprotocol() fails and returns the corresponding value.
Neither of the options _POSIX_THREAD_PRIO_INHERIT and _POSIX_THREAD_PRIO_PROTECT is defined and the implementation does not support the function.
The value specified by protocol is an unsupported value.
If either of the following conditions occurs, pthread_mutexattr_setprotocol() might fail and return the corresponding value.
The value specified by attr or protocol is not valid.
The caller does not have the privilege to perform the operation.
pthread_mutexattr_getprotocol(3T) gets the protocol attribute of a mutex attribute object.
#include <pthread.h> int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol);
attr points to a mutex attribute object created by an earlier call to pthread_mutexattr_init().
protocol contains the protocol attribute: PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT.
On successful completion, pthread_mutexattr_getprotocol() returns 0. Any other returned value indicates that an error occurred.
If the following condition occurs, pthread_mutexattr_getprotocol() fails and returns the corresponding value.
Neither of the options, _POSIX_THREAD_PRIO_INHERIT nor _POSIX_THREAD_PRIO_PROTECT is defined and the implementation does not support the function.
If either of the following conditions occurs, pthread_mutexattr_getprotocol() might fail and return the corresponding value.
The value specified by attr is invalid.
The caller does not have the privilege to perform the operation.
pthread_mutexattr_setprioceiling(3T) sets the priority ceiling attribute of a mutex attribute object.
#include <pthread.h> int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling, int *oldceiling);
attr points to a mutex attribute object created by an earlier call to pthread_mutexattr_init().
The attr mutex attribute object includes the priority ceiing attribute only if the symbol _POSIX_THREAD_PRIO_PROTECT is defined.
prioceiling specifies the priority ceiling of initialized mutexes. The ceiling defines the minimum priority level at which the critical section guarded by the mutex is executed. prioceiling will be within the maximum range of priorities defined by SCHED_FIFO. To avoid priority inversion, prioceiling will be set to a priority higher than or equal to the highest priority of all the threads that might lock the particular mutex.
oldceiling contains the old priority ceiling value.
On successful completion, pthread_mutexattr_setprioceiling() returns 0. Any other returned value indicates that an error occurred.
If any of the following conditions occurs, pthread_mutexattr_setprioceiling() fails and returns the corresponding value.
The option _POSIX_THREAD_PRIO_PROTECT is not defined and the implementation does not support the function.
If either of the following conditions occurs, pthread_mutexattr_setprioceiling() might fail and return the corresponding value.
The value specified by attr or prioceiling is invalid.
The caller does not have the privilege to perform the operation.
pthread_mutexattr_getprioceiling(3T) gets the priority ceiling attribute of a mutex attribute object.
#include <pthread.h> int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling);
attr designates the attribute object created by an earlier call to pthread_mutexattr_init().
The attr mutex attribute object includes the priority ceiing attribute only if the symbol _POSIX_THREAD_PRIO_PROTECT is defined.
pthread_mutexattr_getprioceiling() returns the priority ceiling of initialized mutexes in prioceiling. The ceiling defines the minimum priority level at which the critical section guarded by the mutex is executed. prioceiling will be within the maximum range of priorities defined by SCHED_FIFO. To avoid priority inversion, prioceiling will be set to a priority higher than or equal to the highest priority of all the threads that might lock the particular mutex.
On successful completion, pthread_mutexattr_getprioceiling() returns 0. Any other returned value indicates that an error occurred.
If any of the following conditions occurs, pthread_mutexattr_getprioceiling() fails and returns the corresponding value.
The option _POSIX_THREAD_PRIO_PROTECT is not defined and the implementation does not support the function.
If either of the following conditions occurs, pthread_mutexattr_getprioceiling() might fail and return the corresponding value.
The value specified by attr is invalid.
The caller does not have the privilege to perform the operation.
pthread_mutex_setprioceiling(3T) sets the priority ceiling of a mutex.
#include <pthread.h> int pthread_mutex_setprioceiling(pthread_mutexatt_t *mutex, int prioceiling, int *old_ceiling);
pthread_mutex_setprioceiling() changes the priority ceiling, prioceiling, of a mutex, mutex. pthread_mutex_setprioceiling() locks the mutex if it is unlocked, or blocks until it can successfully lock the mutex, changes the priority celing of the mutex and releases the mutex. The process of locking the mutex need not adhere to the priority protect protocol.
The mutex attribute object, mutex, includes the priority ceiing attribute only if the symbol _POSIX_THREAD_PRIO_PROTECT is defined.
If pthread_mutex_setprioceiling() succeeds, the previous value of the priority ceiling is returned in old_ceiling. If pthread_mutex_setprioceiling() fails, the mutex priority ceiling remains unchanged.
On successful completion, pthread_mutex_setprioceiling() returns 0. Any other returned value indicates that an error occurred.
If the following condition occurs, pthread_mutexatt_setprioceiling() fails and returns the corresponding value.
The option _POSIX_THREAD_PRIO_PROTECT is not defined and the implementation does not support the function.
If any of the following conditions occurs, pthread_mutex_setprioceiling() might fail and return the corresponding value.
The priority requested by prioceiling is out of range.
The value specified by mutex does not refer to a currently existing mutex.
The implementation does not support the priority ceiling protocol for mutexes.
The caller does not have the privilege to perform the operation.
pthread_mutex_getprioceiling(3T) gets the priority ceiling of a mutex.
#include <pthread.h> int pthread_mutex_getprioceiling(const pthread_mutexatt_t *mutex, int *prioceiling);
pthread_mutex_getprioceiling() returns the priority ceiling, prioceiling of a mutex mutex.
On successful completion, pthread_mutex_getprioceiling() returns 0. Any other returned value indicates that an error occurred.
If any of the following conditions occurs, pthread_mutexatt_getprioceiling() fails and returns the corresponding value.
The option _POSIX_THREAD_PRIO_PROTECT is not defined and the implementation does not support the function.
If any of the following conditions occurs, pthread_mutex_getprioceiling() might fail and return the corresponding value.
The value specified by mutex does not refer to a currently existing mutex.
The implementation does not support the priority ceiling protocol for mutexes.
The caller does not have the privilege to perform the operation.
pthread_mutexattr_setrobust_np(3T) sets the robust attribute of a mutex attribute object.
#include <pthread.h> int pthread_mutexattr_setrobust_np(pthread_mutexatt_t *attr, int *robustness);
pthread_mutexattr_setrobust_np() applies only if the symbol _POSIX_THREAD_PRIO_INHERIT is defined.
attr points to the mutex attribute object previously created by a call to pthread_mutexattr_init().
robustness defines the behavior when the owner of the mutex dies. The value of robustness, defined in pthread.h, is PTHREAD_MUTEX_ROBUST_NP or PTHREAD_MUTEX_STALLED_NP. The default value is PTHREAD_MUTEX_STALLED_NP.
PTHREAD_MUTEX_ROBUST_NP
When the owner of the mutex dies, all subsequent calls to pthread_mutex_lock() are blocked from progress in an unspecified manner.
PTHREAD_MUTEX_STALLED_NP
When the owner of the mutex dies, the mutex is unlocked. The next owner of this mutex acquires it with an error return of EOWNWERDEAD.
Your application must check the return code from pthread_mutex_lock() for a mutex of this type.
The new owner of this mutex should make the state protected by the mutex consistent; this state might have been left inconsistent when the previous owner died.
If the new owner is able to make the state consistent, call pthread_mutex_consistent_np() for the mutex, and unlock the mutex.
If the new owner is not able to make the state consistent, do not call pthread_mutex_consistent_np() for the mutex, but unlock the mutex.
All waiters are woken up and all subsequent calls to pthread_mutex_lock() fail to acquire the mutex. The return code is ENOTRECOVERABLE. The mutex can be made consistent by calling pthread_mutex_destroy() to unitialize the mutex, and calling pthread_mutex_int() to reinitialize it.
If the thread that acquire the lock with EOWNERDEAD died, the next owner acquires the lock with an EOWNERDEAD return code.
On successful completion, pthread_mutexattr_setrobust_np() returns 0. Any other returned value indicates that an error occurred.
If any of the following conditions occurs, pthread_mutexattr_setrobust_np() fails and returns the corresponding value.
The option _POSIX_THREAD_PRIO__INHERIT is not defined or the implementation does not support pthread_mutexattr_setrobust_np().
The value specified by robustness is not supported.
pthread_mutexattr_setrobust_np() might fail if:
pthread_mutexattr_getrobust_np(3T) gets the robust attribute of a mutex attribute object.
#include <pthread.h> int pthread_mutexattr_getrobust_np(pthread_mutexatt_t *attr, int *robustness);
pthread_mutexattr_getrobust_np() applies only if the symbol _POSIX_THREAD_PRIO_INHERIT is defined.
attr points to the mutex attribute object previously created by a call to pthread_mutexattr_init().
robustness is the value of the robust attribute of a mutex attribute object.
On successful completion, pthread_mutexattr_getrobust_np() returns 0. Any other returned value indicates that an error occurred.
If any of the following conditions occurs, pthread_mutexattr_getrobust_np() fails and returns the corresponding value.
The option _POSIX_THREAD_PRIO__INHERIT is not defined or the implementation does not support pthread_mutexattr_getrobust_np().
The value specified by robustness is not supported.
pthread_mutexattr_getrobust_np() might fail if: