Synchronization

Semaphores

The semaphores defined by the type cyg_sem_t are counting semaphores. These objects are not referred to by handles, but rather by the pointer to the variable in which the semaphore is created.

void cyg_semaphore_init(cyg_sem_t *sem, cyg_ucount32 val);

Initializes a semaphore. The initial semaphore count is set to val.

void cyg_semaphore_destroy(cyg_sem_t *sem);

Destroys a semaphore. This must not be done while there are any threads waiting on it.

void cyg_semaphore_wait(cyg_sem_t *sem);

If the semaphore count is zero, the current thread will wait on the semaphore. If the count is non-zero, it will be decremented and the thread will continue running.

cyg_bool_t cyg_semaphore_trywait(cyg_sem_t *sem);

A non-blocking version of cyg_semaphore_wait(). This attempts to decrement the semaphore count. If the count is positive, then the semaphore is decremented and true is returned. If the count is zero then the semaphore remains unchanged, and false is returned, but the current thread continues to run.

cyg_bool_t cyg_semaphore_timed_wait(cyg_sem_t *sem, cyg_tick_count_t abstime);

A time-out version of cyg_semaphore_wait(). This attempts to decrement the semaphore count. If the count is positive, then the semaphore is decremented and true is returned. If the count is zero, it will wait for the semaphore to increment. If however the abstime time-out is reached first, it will return false without changing state, and the current thread will continue to run.

cyg_semaphore_timed_wait() is only available if the configuration option CYGFUN_KERNEL_THREADS_TIMER (the section called Option: Allow per-thread timers in Chapter 17) is set.

void cyg_semaphore_post(cyg_sem_t *sem);

If there are threads waiting on this semaphore this will wake exactly one of them. Otherwise it simply increments the semaphore count.

void cyg_semaphore_peek(cyg_sem_t *sem, cyg_ucount32 *val);

Returns the current semaphore count in the variable pointed to by val.

Mutexes

Mutexes (mutual exclusion locks) are used in a similar way to semaphores. A mutex only has two states, locked and unlocked. Mutexes are used to protect accesses to shared data or resources. When a thread locks a mutex it becomes the owner. Only the mutex"s owner may unlock it. While a mutex remains locked, the owner should not lock it again, as the behavior is undefined and probably dangerous.

If non-owners try to lock the mutex, they will be suspended until the mutex is available again, at which point they will own the mutex.

void cyg_mutex_init(cyg_mutex_t *mutex);

Initializes a mutex. It is initialized in the unlocked state.

void cyg_mutex_destroy(cyg_mutex_t *mutex);

Destroys a mutex. A mutex should not be destroyed in the locked state, as the behavior is undefined.

cyg_bool_t cyg_mutex_lock(cyg_mutex_t *mutex);

Changes the nutex from the unlocked state to the locked state. When this happens the mutex becomes owned by the current thread. If the mutex is locked, the current thread will wait until the mutex becomes unlocked before performing this operation. The result of this function will be TRUE if the mutex has been locked, or FALSE if it has not. A FALSE result can result if the thread has been released from its wait by a call to cyg_thread_release() or cyg_mutex_release().

void cyg_mutex_unlock(cyg_mutex_t *mutex);

Changes the mutex from the locked state to the unlocked state. This function may only be called by the thread which locked the mutex, and should not be called on an unlocked mutex.

void cyg_mutex_release(cyg_mutex_t *mutex);

Release all threads waiting on the mutex pointed to by the mutex argument. These threads will return from cyg_mutex_lock() with a FALSE result and will not have claimed the mutex. This function has no effect on any thread that may haev the mutex claimed.

Condition Variables

Condition variables are a synchronization mechanism which (used with a mutex) grants several threads mutually exclusive access to shared data and to broadcast availability of that data to all the other threads.

A typical example of the use of condition variables is when one thread (the producer) is producing data and several other (consumer) threads are waiting for that data to be ready. The consumers will wait by invoking cyg_cond_wait(). The producer will lock access to the data with a mutex, and when it has generated enough data for the other processes to consume, it will invoke cyg_cond_broadcast() to wake up the consumers. The Getting Started with eCos book has example programs which use condition variables to implement a simple message passing system between threads.

void cyg_cond_init(cyg_cond_t *cond, cyg_mutex_t *mutex);

Initializes the condition variable. A condition variable is attached to a specific mutex.

void cyg_cond_destroy(cyg_cond_t *cond);

Destroys the condition variable cond. This must not be done on a condition variable which is in use. After it has been destroyed, it may be subsequently reinitialized.

void cyg_cond_wait(cyg_cond_t *cond);

Causes the current thread to wait on the condition variable, while simultaneously unlocking the corresponding mutex. cyg_cond_wait() may be called by a thread which has the corresponding mutex locked.

The thread can only be awakened by a call to cyg_cond_signal() or cyg_cond_broadcast() on the same condition variable. When the thread is awakened, the mutex will be reclaimed before this function proceeds. Since it may have to wait for this, cyg_cond_wait() should only be used in a loop since the condition may become false in the meantime. This is shown in the following example:


extern cyg_mutex_t mutex;
extern cyg_cond_t cond;

cyg_mutex_lock( &mutex );
...

while( condition_not_true )
{
 cyg_cond_wait( &cond );
}

...

cyg_mutex_unlock( &mutex );

cyg_bool_t cyg_cond_timed_wait(cyg_cond_t *cond, cyg_tick_count_t abstime);

A time-out version of cyg_cond_wait() which waits for a signal or broadcast. If a signal or broadcast is received it returns true, but if one is not received by abstime, it returns false.

cyg_cond_timed_wait() is only available if the configuration option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT (the section called Option: Condition variable timed-wait support in Chapter 17) is set.

void cyg_cond_signal(cyg_cond_t *cond);

Wakes up at least one thread which is waiting on the condition variable. When a thread is awakened it will become the owner of the mutex. cyg_cond_signal() may be called by the thread which currently owns the mutex to which the condition variable is attached.

void cyg_cond_broadcast(cyg_cond_t *cond);

Wakes all the threads waiting on the condition variable. Each time a thread is awakened it will become the current owner of the mutex.