COND_INIT(3C) Standard C Library Functions COND_INIT(3C)


NAME


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);


DESCRIPTION


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

cond_t cond = DEFAULTCV;


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 has the LOCK_ROBUST
attribute 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.


The cond_signal() or cond_broadcast() functions can be called by a thread
whether or not it currently owns the mutex that threads calling
cond_wait(), cond_timedwait(), or cond_reltimedwait() have associated
with the condition variable during their waits. If, however, predictable
scheduling behavior is required, then that mutex should be locked by the
thread prior to calling cond_signal() or cond_broadcast().

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.

RETURN VALUES


Upon successful completion, these functions return 0. Otherwise, a non-
zero value is returned to indicate the error.

ERRORS


The cond_timedwait() and cond_reltimedwait() functions will fail if:

ETIME
The time specified by abstime or reltime has passed.


The cond_wait(), cond_timedwait(), and cond_reltimedwait() functions will
fail if:

EINTR
Interrupted. The calling thread was awakened by the delivery of
a UNIX signal.


If the mutex pointed to by mp is a robust mutex (initialized with the
LOCK_ROBUST attribute), the cond_wait(), cond_timedwait() and
cond_reltimedwait() functions will, under the specified conditions,
return the following error values. For complete information, see the
description of the mutex_lock() function on the mutex_init(3C) manual
page.

ENOTRECOVERABLE
The mutex was protecting the state that has now been
left irrecoverable. The mutex has not been acquired.


EOWNERDEAD
The last owner of the mutex died while holding the
mutex, possibly leaving the state it was protecting
inconsistent. The mutex is now owned by the caller.


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 number of nanoseconds is
greater than or equal to 1,000,000,000.


EXAMPLES


Example 1: Use cond_wait() in a loop to test some condition.




The cond_wait() function 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);


ATTRIBUTES


See attributes(5) for descriptions of the following attributes:


+---------------+-----------------+
|ATTRIBUTE TYPE | ATTRIBUTE VALUE |
+---------------+-----------------+
|MT-Level | MT-Safe |
+---------------+-----------------+

SEE ALSO


fork(2), mmap(2), setitimer(2), shmop(2), mutex_init(3C), signal(3C),
attributes(5), condition(5), mutex(5), standards(5)

NOTES


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(3C).


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.


February 15, 2020 COND_INIT(3C)