To fully understand event flags it will be helpful to read the previous blog entry on semaphores since both semaphores and event flags are techniques used by RTOSes for synchronizing tasks. Semaphores and event flags must have the inherent capability to capture and retain information about an event’s occurrence since the system may be otherwise occupied when the event happened.
Event flags are bits and the usual way of handling them is to group them into larger data elements. Different efficiencies can be obtained with different sizes, so it is not uncommon to see one RTOS that uses an event flag grouping of a byte and others that use a short or a word. Whatever the grouping, it is usually called an event group.
The application developer assigns the association of flags in the group to their related events. At time of initialization, the common procedure is to set all flags in an event group to a value, indicating that the associated events have not occurred. From there on, the content of the event group at any given moment is a joint effort between the tasks that use it and the operating system. The system may set a flag to indicate the event’s occurrence but it is usually the responsibility of the task to cause the flag to be reset. This shared responsibility exposes the vulnerability of event flags – if the task doesn’t reset the flag before the next event arrives, an event can be lost, which can have varying degrees of consequence.
While there is that glaring vulnerability, event flags still have some very attractive features. For one, it is very simple to perform logical testing of the flags. A task can test on a certain configuration of flags in an event group and wait if that condition is not met. Testing on the logical OR condition of a set of event flags allows a task to wait until any one of the events occurs and to identify which one simply and easily. In the same way a task can wait for a logical AND condition in which all of the event in a set must occur before the waiting task can proceed.
Event flags can be designed so that they are reset upon a trigger or left intact so that the testing task can determine which one of them happened. This is most likely to be the case when using a set of event flags in a logical OR manner. When the testing task has made its determination as to which event triggered the task’s release, it must issue a request to reset them in order to prepare for the next occurrences.
When the event flags are used in a logical AND condition, the task does not get triggered until all of the events in the set have occurred, leaving no question about which events happened. In this condition, resetting of the event flags can be managed by the system to reset on triggering, which is much less likely to run into the race condition one can easily encounter if the task resets the event flags in an Or condition. So within the boundaries of response time for the various events and their frequency of occurrence, event flags can be a very useful object for managing events and synchronizing with them.
While event flags are easy to use, one downside to their use is that it can be difficult to process an event deterministically. For system designs where the event groups are available to all tasks, it is possible (and quite likely) that a single event group may hold event flags that are tested by multiple tasks. Such usage demands that each task have a unique testing trigger set up for that event group. When any one of the events in the group occurs, the set of triggering conditions must be examined to see if any of the triggers have occurred. It might be a bounded operation dependent on the number of triggering conditions in action, but it is not deterministic.
Event flag objects can be included in an RTOS with a minor increase in code footprint. For that reason alone, they are worthwhile to include provided that the vulnerability to event loss is not a concern.