Condition Variables

A condition variable is a synchronization primitive that enables threads to wait until a particular condition occurs.

Concepts

Any number of condition variables can be defined (limited only by available RAM). Each condition variable is referenced by its memory address.

To wait for a condition to become true, a thread can make use of a condition variable.

A condition variable is basically a queue of threads that threads can put themselves on when some state of execution (i.e., some condition) is not as desired (by waiting on the condition). The function k_condvar_wait() performs atomically the following steps;

  1. Releases the last acquired mutex.

  2. Puts the current thread in the condition variable queue.

Some other thread, when it changes said state, can then wake one (or more) of those waiting threads and thus allow them to continue by signaling on the condition using k_condvar_signal() or k_condvar_broadcast() then it:

  1. Re-acquires the mutex previously released.

  2. Returns from k_condvar_wait().

A condition variable must be initialized before it can be used.

Implementation

Defining a Condition Variable

A condition variable is defined using a variable of type k_condvar. It must then be initialized by calling k_condvar_init().

The following code defines a condition variable:

struct k_condvar my_condvar;

k_condvar_init(&my_condvar);

Alternatively, a condition variable can be defined and initialized at compile time by calling K_CONDVAR_DEFINE.

The following code has the same effect as the code segment above.

K_CONDVAR_DEFINE(my_condvar);

Waiting on a Condition Variable

A thread can wait on a condition by calling k_condvar_wait().

The following code waits on the condition variable.

K_MUTEX_DEFINE(mutex);
K_CONDVAR_DEFINE(condvar)

int main(void)
{
    k_mutex_lock(&mutex, K_FOREVER);

    /* block this thread until another thread signals cond. While
     * blocked, the mutex is released, then re-acquired before this
     * thread is woken up and the call returns.
     */
    k_condvar_wait(&condvar, &mutex, K_FOREVER);
    ...
    k_mutex_unlock(&mutex);
}

Signaling a Condition Variable

A condition variable is signaled on by calling k_condvar_signal() for one thread or by calling k_condvar_broadcast() for multiple threads.

The following code builds on the example above.

void worker_thread(void)
{
    k_mutex_lock(&mutex, K_FOREVER);

    /*
     * Do some work and fulfill the condition
     */
    ...
    ...
    k_condvar_signal(&condvar);
    k_mutex_unlock(&mutex);
}

Suggested Uses

Use condition variables with a mutex to signal changing states (conditions) from one thread to another thread. Condition variables are not the condition itself and they are not events. The condition is contained in the surrounding programming logic.

Mutexes alone are not designed for use as a notification/synchronization mechanism. They are meant to provide mutually exclusive access to a shared resource only.

Configuration Options

Related configuration options:

  • None.

API Reference

group condvar_apis

Defines

K_CONDVAR_DEFINE(name)

Statically define and initialize a condition variable.

The condition variable can be accessed outside the module where it is defined using:

extern struct k_condvar <name>; 
Parameters:
  • name – Name of the condition variable.

Functions

int k_condvar_init(struct k_condvar *condvar)

Initialize a condition variable.

Parameters:
  • condvar – pointer to a k_condvar structure

Return values:

0 – Condition variable created successfully

int k_condvar_signal(struct k_condvar *condvar)

Signals one thread that is pending on the condition variable.

Parameters:
  • condvar – pointer to a k_condvar structure

Return values:

0 – On success

int k_condvar_broadcast(struct k_condvar *condvar)

Unblock all threads that are pending on the condition variable.

Parameters:
  • condvar – pointer to a k_condvar structure

Returns:

An integer with number of woken threads on success

int k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, k_timeout_t timeout)

Waits on the condition variable releasing the mutex lock.

Atomically releases the currently owned mutex, blocks the current thread waiting on the condition variable specified by condvar, and finally acquires the mutex again.

The waiting thread unblocks only after another thread calls k_condvar_signal, or k_condvar_broadcast with the same condition variable.

Parameters:
  • condvar – pointer to a k_condvar structure

  • mutex – Address of the mutex.

  • timeout – Waiting period for the condition variable or one of the special values K_NO_WAIT and K_FOREVER.

Return values:
  • 0 – On success

  • -EAGAIN – Waiting period timed out.