## NAME

pthread_cond_init, pthread_cond_destroy, pthread_condattr_init, pthread_condattr_destroy, pthread_cond_wait, pthread_cond_signal, pthread_cond_broadcast

## SYNOPSIS

#include <sys.h>

int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);

int pthread_cond_destroy (pthread_cond_t *cond);

int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

int pthread_cond_signal (pthread_cond_t *cond);

int pthread_cond_broadcast (pthread_cond_t *cond);

int pthread_condattr_init(pthread_condattr_t *attr);

int pthread_condattr_destroy(pthread_condattr_t *attr);

## DESCRIPTION

The functions for conditional variables are easy to use if you understand why they were created and the automatic nature of some of the calls. While mutexes implement synchronization by controlling thread access to data, condition variables allow threads to synchronize based upon the actual value of data. A condition variable is always used in conjunction with a mutex lock.

The most general case for use is to first have a main thread declare and initialize global variables, declare and initialize a condition variable object and declare and initialize an associated mutex. The main thread then creates threads A and B to do the work.

Thread A does the following:

- Does work up to the point where a certain condition must be met.
- Lock associated mutex and check value of global variable.
- Call pthread_cond_wait() to perform a blocking wait for the signal from thread B, automatically and atomically unlocking the mutex so thread B may get access.
- When signaled, wake up. The mutex has been automatically and atomically relocked.
- Unlock the mutex.
- Continue

Thread B does the following:

- Do work.
- Lock associated mutex.
- Change the value of the global variable that thread A is waiting upon.
- Check the value of the global thread A wait variable. If it fulfills the desired condition, signal thread A. This signal is done with pthread_cond_signal or pthread_cond_broadcast.
- Unlock the mutex.
- Continue

Without condition variables, the programmer would need to have threads continually polling (possibly in a critical section), to check if the condition is met. This can be very resource consuming since the thread would be continuously busy in this activity. A condition variable is a way to achieve the same goal without polling.

If more than one thread is waiting for the condition variable, then the signaling thread must use pthread_cond_broadcast rather than using pthread_cond_signal.

The functions pthread_condattr_init() and pthread_condattr_destroy() are not used in the current implementation and simply return zero. This should not be surprising since the attr is for multiple process sharing of condition variables and the implementation is one of single process multiple threads.

## RETURN VALUES

All functions return zero with the exception of pthread_cond_wait and pthread_cond_timedwait.

pthread_cond_wait and pthread_cond_timedwait return either zero with success or one of the following error values.

## ERRORS

- EINVAL - returned if the timer value or another parameter is invalid.
- ETIMEDOUT - returned if the timer expires.

## EXAMPLES

    #include <pthread.h>
    #include <stdio.h>

    #define NUM_THREADS  3
    #define TCOUNT 10
    #define COUNT_LIMIT 12

    int     count = 0;
    pthread_mutex_t count_mutex;
    pthread_cond_t count_threshold_cv;

    void *inc_count(void *t)
    {
      int i;
      long my_id = (long)t;

      for (i=0; i < TCOUNT; i++) {
        pthread_mutex_lock(&count_mutex);
        count++;

        /*
        Check the value of count and signal waiting thread when condition is
        reached.  Note that this occurs while mutex is locked.
        */
        if (count == COUNT_LIMIT) {
          printf("inc_count(): thread %ld, count = %d  Threshold reached. ",
                 my_id, count);
          pthread_cond_signal(&count_threshold_cv);
          printf("Just sent signal.\n");
          }
        printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
    	   my_id, count);
        pthread_mutex_unlock(&count_mutex);

        /* Do some work so threads can alternate on mutex lock */
        sleep(1);
        }
      pthread_exit(NULL);
    }

    void *watch_count(void *t)
    {
      long my_id = (long)t;

      printf("Starting watch_count(): thread %ld\n", my_id);

      /*
      Lock mutex and wait for signal.  Note that the pthread_cond_wait routine
      will automatically and atomically unlock mutex while it waits.
      Also, note that if COUNT_LIMIT is reached before this routine is run by
      the waiting thread, the loop will be skipped to prevent pthread_cond_wait
      from never returning.
      */
      pthread_mutex_lock(&count_mutex);
      if (count < COUNT_LIMIT) {
        printf("watch_count(): thread %ld going into wait...\n", my_id);
        pthread_cond_wait(&count_threshold_cv, &count_mutex);
        printf("watch_count(): thread %ld Condition signal received.\n", my_id);
        count += 125;
        printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
        }
      pthread_mutex_unlock(&count_mutex);
      pthread_exit(NULL);
    }

    THREAD Main(void *)
    {
      int i, rc;
      long t1=1, t2=2, t3=3;
      pthread_t threads[3];
      pthread_attr_t attr;

      /* Initialize mutex and condition variable objects */
      pthread_mutex_init(&count_mutex, NULL);
      pthread_cond_init (&count_threshold_cv, NULL);

      /* For portability, explicitly create threads in a joinable state */
      pthread_attr_init(&attr);
      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
      pthread_create(&threads[0], &attr, watch_count, (void *)t1);
      pthread_create(&threads[1], &attr, inc_count, (void *)t2);
      pthread_create(&threads[2], &attr, inc_count, (void *)t3);

      /* Wait for all threads to complete */
      for (i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
      }
      printf ("Main(): Waited on %d threads. Final value of count = %d. Done.\n",
              NUM_THREADS, count);

      /* Clean up and exit */
      pthread_attr_destroy(&attr);
      pthread_mutex_destroy(&count_mutex);
      pthread_cond_destroy(&count_threshold_cv);
      pthread_exit (NULL);

    }

## NOTES

Remember the kernel implementation is a single process, multiple threads. For this reason, pthread_cond_attr has no real use and is not used.

## SEE ALSO

For a tutorial with discussion and examples, see the Unison or DSPnano Programmer's Guides and the demo directory.

#### Home page (Kernel)

## < Copyright Rowebots Research Inc. and Multiprocessor Toolsmiths Inc. 1987-2018 >