|
Threads Library Functions | cond_init(3THR) |
| cond_init, cond_wait, cond_timedwait, cond_reltimedwait, cond_signal, cond_broadcast, cond_destroy - condition variables |
SYNOPSIS
|
cc -mt [ flag... ] file... [ library... ]
#include <thread.h>
#include <synch.h> int cond_init(cond_t *cvp, int type, void *arg); |
| int cond_wait(cond_t *cvp, mutex_t *mp); |
| int cond_timedwait(cond_t *cvp, mutex_t *mp, timestruc_t *abstime); |
| int cond_reltimedwait(cond_t *cvp, mutex_t *mp, timestruc_t *reltime); |
| int cond_signal(cond_t *cvp); |
| int cond_broadcast(cond_t *cvp); |
| int cond_destroy(cond_t *cvp); |
|
Initialize
|
Condition variables and mutexes should be global. Condition variables that are allocated in writable memory can synchronize threads among processes if they are shared
by the cooperating processes (see mmap(2)) and are initialized for this purpose.
The scope of a condition variable is either intra-process or inter-process. This is dependent upon whether the argument is passed implicitly or explicitly to the initialization of that condition variable. A condition variable does not need to be explicitly initialized. A condition variable is initialized
with all zeros, by default, and its scope is set to within the calling process. For inter-process synchronization, a condition variable must be initialized once, and only once, before use.
A condition variable must not be simultaneously initialized by multiple threads or re-initialized while in use by other threads.
Attributes of condition variables can be set to the default or customized at initialization.
The cond_init() function initializes the condition variable pointed to by cvp. A condition variable can have several different types of behavior, specified by type. No current type uses arg although a future
type may specify additional behavior parameters with arg. The type argument c take one of the following values:
-
USYNC_THREAD
- The condition variable can synchronize threads only in this process. This is the default.
-
USYNC_PROCESS
- The condition variable can synchronize threads in this process and other processes. Only one process should initialize the condition variable. The object initialized with this attribute must be
allocated in memory shared between processes, either in System V shared memory (see shmop(2)) or in memory mapped to a file (see mmap(2)). It is illegal to initialize the object this way and to not allocate it in such shared memory.
Initializing condition variables can also be accomplished by allocating in zeroed memory, in which case, a type of USYNC_THREAD is assumed.
If default condition variable attributes are used, statically allocated condition variables can be initialized by the macro DEFAULTCV.
Default condition variable initialization (intra-process):
|
cond_t cvp;
cond_init(&cvp, NULL, NULL); /*initialize condition variable with default*/
|
or
|
cond_init(&cvp, USYNC_THREAD, NULL);
|
or
Customized condition variable initialization (inter-process):
|
cond_init(&cvp, USYNC_PROCESS, NULL); /* initialize cv with
inter-process scope */
|
|
Condition Wait
|
The condition wait interface allows a thread to wait for a condition and atomically release the associated mutex that it needs to hold to check the condition. The
thread waits for another thread to make the condition true and that thread's resulting call to signal and wakeup the waiting thread.
The cond_wait() function atomically releases the mutex pointed to by mp and causes the calling thread to block on the condition variable pointed to by cvp. The blocked thread may be awakened by cond_signal(), cond_broadcast(), or when interrupted by delivery of a UNIX signal or a fork().
The cond_wait(), cond_timedwait(), and cond_reltimedwait() functions always return with the mutex locked and owned by the calling thread even when returning an error, except when the mutex is of USYNC_PROCESS_ROBUST type
and has been left irrecoverable by the mutex's last owner. The cond_wait(), cond_timedwait(), and cond_reltimedwait() functions return the appropriate error value if they fail to internally reacquire the mutex.
|
Condition Signaling
|
A condition signal allows a thread to unblock a single thread waiting on the condition variable, whereas a condition broadcast allows a thread to unblock all
threads waiting on the condition variable.
The cond_signal() function unblocks one thread that is blocked on the condition variable pointed to by cvp.
The cond_broadcast() function unblocks all threads that are blocked on the condition variable pointed to by cvp.
If no threads are blocked on the condition variable, then cond_signal() and cond_broadcast() have no effect.
Both functions should be called under the protection of the same mutex that is used with the condition variable being signaled. Otherwise, the condition variable may be signaled between the test of the associated condition and blocking in cond_wait(). This can cause an infinite
wait.
|
Destroy
|
The condition destroy functions destroy any state, but not the space, associated with the condition variable.
The cond_destroy() function destroys any state associated with the condition variable pointed to by cvp. The space for storing the condition variable is not freed.
|
|
|
Upon successful completion, these functions return 0. Otherwise, a non-zero value is returned to indicate the error.
|
|
These functions may fail if:
-
EFAULT
- The cond, attr, cvp, arg, abstime, or mutex argument points to an illegal address.
-
EINVAL
- Invalid argument. For cond_init(), type is not a recognized type. For cond_timedwait(), the specified number of seconds, abstime, is greater
than current_time + 100,000,000, where current_time is the current time, or the number of nanoseconds is greater than or equal to 1,000,000,000.
-
ELOCKUNMAPPED
- The last owner of this mutex unmapped the mutex while holding the mutex. This mutex is now owned by the caller. See the description of the mutex_lock() function on the mutex_init(3THR) manual page.
-
ENOTRECOVERABLE
- The mutex pointed to by mp is protecting the state that has been left irrecoverable when the mutex's last owner was not able to clean up the state. The mutex has not been acquired. See the description
of the mutex_lock() function on the mutex_init(3THR) manual page.
-
EOWNERDEAD
- The last owner of the mutex pointed to by mp died while holding the mutex. The mutex has been acquired. See the description of the mutex_lock() function on the mutex_init(3THR) manual page.
The cond_timedwait() and cond_reltimedwait() functions will fail if:
-
ETIME
- The time specified by abstime or reltime has passed.
The cond_wait() function may fail if:
-
EINTR
- Interrupted. The calling thread was awakened by the delivery of a UNIX signal.
|
| Example 1. Use cond_wait in a loop to test some condition.
|
The cond_wait() functin is normally used in a loop testing some condition, as follows:
|
(void) mutex_lock(mp);
while (cond == FALSE) {
(void) cond_wait(cvp, mp);
}
(void) mutex_unlock(mp);
|
|
Example 2. Use cond_timedwait in a loop to test some condition.
|
The cond_timedwait() function is normally used in a loop testing some condition. It uses an absolute timeout value as follows:
|
timestruc_t to;
...
(void) mutex_lock(mp);
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;
while (cond == FALSE) {
err = cond_timedwait(cvp, mp, &to);
if (err == ETIME) {
/* timeout, do something */
break;
}
}
(void) mutex_unlock(mp);
|
|
Example 3. Use cond_reltimedwait in a loop to test some condition.
|
The cond_reltimedwait() function is normally used in a loop testing in some condition. It uses a relative timeout value as follows:
|
timestruc_t to;
...
(void) mutex_lock(mp);
while (cond == FALSE) {
to.tv_sec = TIMEOUT;
to.tv_nsec = 0;
err = cond_reltimedwait(cvp, mp, &to);
if (err == ETIME) {
/* timeout, do something */
break;
}
}
(void) mutex_unlock(mp);
|
|
|
|
See attributes(5) for descriptions of the following attributes:
ATTRIBUTE TYPE | ATTRIBUTE VALUE |
MT-Level | MT-Safe |
|
|
The only policy currently supported is SCHED_OTHER. In Solaris, under the SCHED_OTHER policy, there is no established order in which threads are unblocked.
If more than one thread is blocked on a condition variable, the order in which threads are unblocked is determined by the scheduling policy. When each thread, unblocked as a result of a cond_signal() or cond_broadcast(), returns from its call to cond_wait() or cond_timedwait() , the thread owns the mutex with which it called cond_wait(), cond_timedwait(), or cond_reltimedwait(). The thread(s) that are unblocked compete for the mutex according to the scheduling policy
and as if each had called mutex_lock(3THR).
When cond_wait() returns the value of the condition is indeterminate and must be reevaluated.
The cond_timedwait() and cond_reltimedwait() functions are similar to cond_wait(), except that the calling thread will not wait for the condition to become true past the absolute time specified by abstime or the relative
time specified by reltime. Note that cond_timedwait() or cond_reltimedwait() might continue to block as it trys to reacquire the mutex pointed to by mp, which may be locked by another thread. If either cond_timedwait() or cond_reltimedwait() returns because of a timeout, it returns the error value ETIME.
|
| |