cyg_flag_init, cyg_flag_destroy, cyg_flag_setbits, cyg_flag_maskbits, cyg_flag_wait, cyg_flag_timed_wait, cyg_flag_poll, cyg_flag_peek, cyg_flag_waiting — Synchronization primitive


#include <cyg/kernel/kapi.h>
void cyg_flag_init (cyg_flag_t* flag );
void cyg_flag_destroy (cyg_flag_t* flag );
void cyg_flag_setbits (cyg_flag_t* flag ,
 cyg_flag_value_t value );
void cyg_flag_maskbits (cyg_flag_t* flag ,
 cyg_flag_value_t value );
cyg_flag_value_t cyg_flag_wait (cyg_flag_t* flag ,
 cyg_flag_value_t pattern ,
 cyg_flag_mode_t mode );
cyg_flag_value_t cyg_flag_timed_wait (cyg_flag_t* flag ,
 cyg_flag_value_t pattern ,
 cyg_flag_mode_t mode ,
 cyg_tick_count_t abstime );
cyg_flag_value_t cyg_flag_poll (cyg_flag_t* flag ,
 cyg_flag_value_t pattern ,
 cyg_flag_mode_t mode );
cyg_flag_value_t cyg_flag_peek (cyg_flag_t* flag );
cyg_bool_t cyg_flag_waiting (cyg_flag_t* flag );


Event flags allow a consumer thread to wait for one of several different types of event to occur. Alternatively it is possible to wait for some combination of events. The implementation is relatively straightforward. Each event flag contains a 32-bit integer. Application code associates these bits with specific events, so for example bit 0 could indicate that an I/O operation has completed and data is available, while bit 1 could indicate that the user has pressed a start button. A producer thread or a DSR can cause one or more of the bits to be set, and a consumer thread currently waiting for these bits will be woken up.

Unlike semaphores no attempt is made to keep track of event counts. It does not matter whether a given event occurs once or multiple times before being consumed, the corresponding bit in the event flag will change only once. However semaphores cannot easily be used to handle multiple event sources. Event flags can often be used as an alternative to condition variables, although they cannot be used for completely arbitrary conditions and they only support the equivalent of condition variable broadcasts, not signals.

Before an event flag can be used it must be initialized by a call to cyg_flag_init. This takes a pointer to a cyg_flag_t data structure, which can be part of a larger structure. All 32 bits in the event flag will be set to 0, indicating that no events have yet occurred. If an event flag is no longer required it can be cleaned up with a call to cyg_flag_destroy, allowing the memory for the cyg_flag_t structure to be re-used.

A consumer thread can wait for one or more events by calling cyg_flag_wait. This takes three arguments. The first identifies a particular event flag. The second is some combination of bits, indicating which events are of interest. The final argument should be one of the following:

The call to cyg_flag_wait will block until all the specified event bits are set. The event flag is not cleared when the wait succeeds, in other words all the bits remain set.
The call will block until at least one of the specified event bits is set. The event flag is not cleared on return.
The call will block until all the specified event bits are set, and the entire event flag is cleared when the call succeeds. Note that if this mode of operation is used then a single event flag cannot be used to store disjoint sets of events, even though enough bits might be available. Instead each disjoint set of events requires its own event flag.
The call will block until at least one of the specified event bits is set, and the entire flag is cleared when the call succeeds.

A call to cyg_flag_wait normally blocks until the required condition is satisfied. It will return the value of the event flag at the point that the operation succeeded, which may be a superset of the requested events. If cyg_thread_release is used to unblock a thread that is currently in a wait operation, the cyg_flag_wait call will instead return 0.

cyg_flag_timed_wait is a variant of cyg_flag_wait which adds a timeout: the wait operation must succeed within the specified number of ticks, or it will fail with a return value of 0. The number of ticks is specified as an absolute, not relative tick count, and so in order to wait for a relative number of ticks, the return value of the cyg_current_time() function should be added to determine the absolute number of ticks. cyg_flag_poll is a non-blocking variant: if the wait operation can succeed immediately it acts like cyg_flag_wait, otherwise it returns immediately with a value of 0.

cyg_flag_setbits is called by a producer thread or from inside a DSR when an event occurs. The specified bits are or'd into the current event flag value. This may cause one or more waiting threads to be woken up, if their conditions are now satisfied. How many threads are awoken depends on the use of CYG_FLAG_WAITMODE_CLR. The queue of threads waiting on the flag is walked to find threads which now have their wake condition fulfilled. If the awoken thread has passed CYG_FLAG_WAITMODE_CLR the walking of the queue is terminated, otherwise the walk continues. Thus if no threads have passed CYG_FLAG_WAITMORE_CLR all threads with fulfilled conditions will be awoken. If CYG_FLAG_WAITMODE_CLR is passed by threads with fulfilled conditions, the number of awoken threads will depend on the order the threads are in the queue.

cyg_flag_maskbits can be used to clear one or more bits in the event flag. This can be called from a producer when a particular condition is no longer satisfied, for example when the user is no longer pressing a particular button. It can also be used by a consumer thread if CYG_FLAG_WAITMODE_CLR was not used as part of the wait operation, to indicate that some but not all of the active events have been consumed. If there are multiple consumer threads performing wait operations without using CYG_FLAG_WAITMODE_CLR then typically some additional synchronization such as a mutex is needed to prevent multiple threads consuming the same event.

Two additional functions are provided to query the current state of an event flag. cyg_flag_peek returns the current value of the event flag, and cyg_flag_waiting can be used to find out whether or not there are any threads currently blocked on the event flag. Both of these functions must be used with care because other threads may be operating on the event flag.

Valid contexts

cyg_flag_init is typically called during system initialization but may also be called in thread context. The same applies to cyg_flag_destroy. cyg_flag_wait and cyg_flag_timed_wait may only be called from thread context. The remaining functions may be called from thread or DSR context.