↑ On-the-Shelf Software ↑

GEONius.com
20-Jan-2023
 E-mail 

ef_util - Event Flag Utilities

The functions in this file implement VMS-like event flags under VxWorks. Applications can

An event flag cluster can be accessed by any task on a CPU; when the utilities are built with the "VxMP" CPP symbol defined, clusters can be shared across CPUs.

Event flag clusters are implemented by storing the name of the cluster in the named object database (which is implemented using the system symbol table or the VxMP shared name database). The value of the named object is the address of a cluster structure allocated on the heap (or from shared memory under VxMP). The cluster structure contains an N-bit long word whose bits represent event flags 0 through N-1 of the cluster. The structure also contains the IDs of two semaphores (shared under VxMP): a mutual exclusion semaphore used to prevent multiple tasks from modifying the event flags at the same time, and a change semaphore used to signal waiting tasks that the state of the event flags has changed.

Before accessing the event flags in a cluster, a task must "create" the cluster:

    #include  "ef_util.h"			-- Event flag definitions.
    EfCluster  cluster ;
    ...
    ef_create ("name", 0, debug, &cluster) ;

The first task to call ef_create() actually creates the cluster; later tasks simply "attach" to the cluster. To guard against name conflicts, the cluster name has _efc appended to it before being entered into the named object database.

Event flags can be set or reset by calling ef_change(). For example, the following call simultaneously sets event flags 2 and 4 and clears event flags 3 and 5:

    long  flags = 0x0000003C ;
    long  state = 0x00000014 ;
    ...
    ef_change (cluster, flags, state) ;

Alternatively, you can use the macros ef_set() and ef_clear (defined in ef_util.h):

    ef_set (cluster, 0x00000014) ;		-- Set event flags 2 and 4.
    ef_clear (cluster, 0x00000028) ;		-- Clear event flags 3 and 5.

The current state of the events flags in a cluster can be polled with the ef_read() function. The following example tests if event flag 2 is set and 3 is clear:

    long  state ;
    ...
    ef_read (cluster, &state) ;
    if ((state & 0x00000004) &&			-- Event flag 2 is set?
        !(state & 0x00000008))			-- Event flag 3 is clear?
        ...

There are two means of waiting on event flags. First, a task can wait for all of the selected event flags to reach the desired states. In the following example, the task waits for event flags 2 and 4 to be set and event flags 3 and 5 to be clear:

    long  flags = 0x0000003C ;
    long  state = 0x00000014 ;
    ...
    ef_wait_all (cluster, flags, state, -1.0) ;

Second, a task can wait for any of the selected event flags to reach their desired states. For example, the following call suspends its task until event flag 2 or 4 is set or event flag 3 or 5 is clear:

    long  flags = 0x0000003C ;
    long  state = 0x00000014 ;
    ...
    ef_wait_any (cluster, flags, state, -1.0) ;

The event flag waits are implemented by suspending the task on the cluster's change semaphore. Whenever the event flags are modified, the change semaphore is flushed, awakening any task waiting on the event flags in the cluster. These tasks then check the state of the flags; if the flags are not yet in the desired state, the tasks suspend on the semaphore again.

When a task terminates, it should "delete" the cluster:

    ef_delete (cluster) ;

The cluster isn't actually deleted from the system until the last process using it deletes it.

Notes

Richard Neitzel of the National Center for Atmospheric Research wrote a C++ class (available in the VxWorks archive there) that uses somewhat the same approach to implementing event flags.

There is a possible timing problem in the ef_wait_xxx() functions. These functions check the event flags immediately before waiting on a cluster's change semaphore. Suppose a task were interrupted after checking the flags but before waiting on the change semaphore. If the "signalling" task manages to change the event flags and flush any tasks waiting on the change semaphore before the first task has a chance to resume execution, the first task will miss the change and potentially wait forever (if another change never comes). To catch one such "straggler", the signalling task signals the change semaphore after flushing any pending tasks. However, could there be more than one straggler?

The name/cluster mappings and reference counts are stored in the named object database (see nob_util.c). Processes should delete all clusters before exiting; if a process exits prematurely, the named object database could be left in an inconsistent state.


Public Procedures

ef_change() - modifies (sets or clears) one or more event flags in a cluster.
ef_clear() - clears one or more event flags in a cluster.
ef_create() - creates a cluster of event flags.
ef_delete() - deletes a cluster of event flags.
ef_read() - reads the current state of the event flags in a cluster.
ef_set() - sets one or more event flags in a cluster.
ef_wait() - waits for one event flag in a cluster to be set.
ef_wait_all() - waits on all of a selected group of event flags in a cluster.
ef_wait_any() - waits on any of a selected group of event flags in a cluster.

Source Files

ef_util.c
ef_util.h

Alex Measday  /  E-mail