Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

OpenVMS Programming Concepts Manual


Previous Contents Index

16.6 Using Event Flags

Event flags are maintained by the operating system for general programming use in coordinating thread execution with asynchronous events. Programs can use event flags to perform a variety of signaling functions. Event flag services clear, set, and read event flags. They also place a thread in a wait state pending the setting of an event flag or flags.

Table 16-1 shows the two usage styles of event flags.

Table 16-1 Usage Styles of Event Flags
Style Meaning
Explicit Uses SET, CLEAR, and READ functions that are commonly used when one thread deals with multiple asynchronous events.
Implicit Uses the SYS$SYNCH and wait form of system services when one or more threads wish to wait for a particular event. For multithreaded applications, only the implicit use of event flags is recommended.

The wait form of system services is a variant of asynchronous services; there is a service request and then a wait for the completion of the request. For reliable operation in most applications, WAIT form services must specify an I/O status block (IOSB). The IOSB prevents the service from completing prematurely and also provides status information.

16.6.1 General Guidelines for Using Event Flags

Explicit use of event flags follows these general steps:

  1. Allocate or choose local event flags or associate common event flags for your use.
  2. Set or clear the event flag.
  3. Read the event flag.
  4. Suspend thread execution until an event flag is set.
  5. Deallocate the local event flags or disassociate common event flags when they are no longer needed.

Implicit use of event flags may involve only step 4, or steps 1, 4, and 5.

Use run-time library routines and system services to accomplish these event flag tasks. Table 16-2 summarizes the event flag routines and services.

Table 16-2 Event Flag Routines and Services
Routine or Service Task
LIB$FREE_EF Deallocate a local event flag
LIB$GET_EF Allocate any local event flag
LIB$RESERVE_EF Allocate a specific local event flag
SYS$ASCEFC Associate a common event flag cluster
SYS$CLREF Clear a local or common event flag
SYS$DACEFC Disassociate a common event flag cluster
SYS$DLCEFC Delete a common event flag cluster
SYS$READEF Read a local or common event flag
SYS$SETEF Set a local or common event flag
SYS$SYNCH Wait for a local or common event flag to be set and for nonzero I/O status block---recommended to be used with threads
SYS$WAITFR Wait for a specific local or common event flag to be set---not recommended to be used with threads
SYS$WFLAND Wait for several local or common event flags to be set---logical AND of event flags
SYS$WFLOR Wait for one of several local or common event flags to be set---logical OR of event flags

Some system services set an event flag to indicate the completion or the occurrence of an event; the calling program can test the flag. Other system services use event flags to signal events to the calling process, such as SYS$ENQ(W), SYS$QIO(W), or SYS$SETIMR.

16.6.2 Introducing Local and Common Event Flag Numbers and Event Flag Clusters

Each event flag has a unique number; event flag arguments in system service calls refer to these numbers. For example, if you specify event flag 1 in a call to the SYS$QIO system service, then event flag 1 is set when the I/O operation completes.

To allow manipulation of groups of event flags, the flags are ordered in clusters of 32 numbers corresponding to bits 0 through 31 (<31:0>) in a longword. The clusters are also numbered from 0 to 4. The range of event flag numbers encompasses the flags in all clusters: event flag 0 is the first flag in cluster 0, event flag 32 is the first flag in cluster 1, and so on.

Event flags are divided into five clusters: two for local event flags and two for common event flags. There is also a special local cluster 4 that supports EFN 128.

Table 16-3 summarizes the ranges of event flag numbers and the clusters to which they belong.

The same system services manipulate flags in either local and common event flag clusters. Because the event flag number implies the cluster number, you need not specify the cluster number when you call a system service that refers to an event flag.

When a system service requires an event flag cluster number as an argument, you need only specify the number of any event flag in the cluster. Thus, to read the event flags in cluster 1, you could specify any number in the range 32 through 63.

Table 16-3 Event Flags
Cluster Number Flag Number Type Usage
0 0 Local Default flag used by system routines.
0 1 to 23 Local May be used in system routines. When an event flag is requested, it is not returned unless it has been previously and specifically freed by calls to LIB$FREE_EF.
0 24 to 31 Local Reserved for Compaq use only.
1 32 to 63 Local Available for general use.
2 64 to 95 Common Available for general use.
3 96 to 127 Common Available for general use.
4 128 Local Available for general use without explicit allocation.

16.6.3 Using Event Flag Zero (0)

Event flag 0 is the default event flag. Whenever a process requests a system service with an event flag number argument, but does not specify a particular flag, event flag 0 is used. Therefore, event flag 0 is more likely than other event flags to be used incorrectly for multiple concurrent requests.

Code which uses any event flag should be able to tolerate spurious sets, assuming that the only real danger is a spurious clear that causes a thread to miss an event. Since any system service which uses an event flag clears the flag, there is a danger than an event which has occured but has not been responded to is masked which can result in a hang. For further information, see the SYS$SYNCH system service in OpenVMS System Services Reference Manual: GETQUI--Z.

16.6.4 Using EFN$C_ENF Local Event Flag

It is intended that the combination of EFN$C_ENF and a status block be used with the wait form of system services, or with SYS$SYNCH system service. EFN$C_ENF does not need to be initialized, nor does it need to be reserved or freed. Multiple threads of execution may concurrently use EFN$C_ENF without interference as long as they use a unique status block for each concurrent asynchronous service. When EFN$C_ENF is used with explicit event flag system services, it performs as if always set. It is recommended that ERN$C_ENF be used to eliminate the chance for event flag overlap.

16.6.5 Using Local Event Flags

Local event flags are automatically available to each program. They are not automatically initialized. However, if an event flag is passed to a system service such as SYS$GETJPI, the service initializes the flag before using it.

When using local event flags, use the event flag routines as follows:

  1. To ensure that the event flag you are using is not accessed and changed by other users, allocate local event flags. The OpenVMS RTL Library (LIB$) Manual describes routines you can use to allocate an arbitrary event flag (LIB$GET_EF), and to allocate a particular event flag (LIB$RESERVE_EF) from the processwide pool of available local event flags. Similar routines do not exist for common event flags.
    The LIB$GET_EF routine by default allocates flags from event flag cluster 1 (event flags 32 through 63). Event flags 1 through 32 (in event flag cluster 0) can also optionally be allocated by calls to LIB$GET_EF. To maintain compatibility with older application software that used event flags 1 through 23 in an uncoordinated fashion, these event flags must be initially marked as free by application calls to the LIB$FREE_EF routine before these flags can be allocated by subsequent calls to the LIB$GET_EF routine.
  2. Before using the event flag, initialize it using the SYS$CLREF system service, unless you pass the event flag to a routine that clears it for you.
  3. When an event that is relevant to other program components is completed, set the event flag with the SYS$SETEF system service.
  4. A program component can read the event flag to determine what has happened and act accordingly. Use the SYS$READEF system service to read the event flag.
  5. The program components that evaluate event flag status can be placed in a wait state. Then, when the event flag is set, execution is resumed. Use the SYS$WAITFR, SYS$WFLOR, SYS$WFLAND, or SYS$SYNCH routine to accomplish this task.
  6. When a local event flag is no longer required, free it by using the LIB$FREE_EF routine.

The following Fortran example uses LIB$GET_EF to choose a local event flag and then uses SYS$CLREF to set the event flag to 0 (clear the event flag). (Note that run-time library routines require an event flag number to be passed by reference, and system services require an event flag number to be passed by value.)


INTEGER FLAG, 
2       STATUS, 
2       LIB$GET_EF, 
2       SYS$CLREF 
 
STATUS = LIB$GET_EF (FLAG) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
STATUS = SYS$CLREF (%VAL(FLAG)) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 

16.6.5.1 Example of Event Flag Services

Local event flags are used most commonly in conjunction with other system services. For example, you can use the Set Timer (SYS$SETIMR) system service to request that an event flag be set at a specific time of day or after a specific interval of time has passed. If you want to place a process in a wait state for a specified period of time, specify an event flag number for the SYS$SETIMR service and then use the Wait for Single Event Flag (SYS$WAITFR) system service, as shown in the C example that follows:


 
   .
   .
   .
main() { 
 
        unsigned int status, daytim[1], efn=3; 
 
/* Set the timer */     
        status = SYS$SETIMR( efn,  /* efn - event flag */ 
                   &daytim,        /* daytim - expiration time */ 
                   0,              /* astadr - AST routine */ 
                   0,              /* reqidt - timer request id */ 
                   0);             /* flags */ 
        if ((status & 1) != 1) 
                LIB$SIGNAL( status ); 
   .
   .
   .
 
/* Wait until timer expires */ 
        status = SYS$WAITFR( efn ); 
        if ((status & 1) != 1) 
                LIB$SIGNAL( status ); 
   .
   .
   .
} 
 
 

In this example, the daytim argument refers to a 64-bit time value. For details about how to obtain a time value in the proper format for input to this service, see Chapter 6.

16.6.6 Using Common Event Flags

Common event flags are manipulated like local event flags. However, before a process can use event flags in a common event flag cluster, the cluster must be created. The Associate Common Event Flag Cluster (SYS$ASCEFC) system service creates a common event flag cluster. ( Section 16.6.6.1 explains the format of this string.) By calling SYS$ASCEFC, other processes in the same UIC group can establish their association with the cluster so they can access flags in it. Each process that associates with the cluster must use the same name to refer to it; the SYS$ASCEFC system service establishes correspondence between the cluster name and the cluster number that a process assigns to the cluster.

The first program to name a common event flag cluster creates it; all flags in a newly created cluster are clear. Other processes on the same OpenVMS cluster node that have the same UIC group number as the creator of the cluster can reference the cluster by invoking SYS$ASCEFC and specifying the cluster name.

Different processes may associate the same name with different common event flag numbers; as long as the name and UIC group are the same, the processes reference the same cluster.

Common event flags act as a communication mechanism between images executing in different processes in the same group on the same OpenVMS cluster node. Common event flags are often used as a synchronization tool for other, more complicated communication techniques, such as logical names and global sections. For more information about using event flags to synchronize communication between processes, see Chapter 2.

If every cooperating process that is going to use a common event flag cluster has the necessary privilege or quota to create a cluster, the first process to call the SYS$ASCEFC system service creates the cluster.

The following example shows how a process might create a common event flag cluster named COMMON_CLUSTER and assign it a cluster number of 2:


 
   .
   .
   .
#include <descrip.h> 
   .
   .
   .
        unsigned int status, efn=65; 
        $DESCRIPTOR(name,"COMMON_CLUSTER"); /* Cluster name */ 
   .
   .
   .
/* Create cluster 2 */ 
        status = SYS$ASCEFC( efn, &name, 0, 0); 
 
 
 
 

Other processes in the same group can now associate with this cluster. Those processes must use the same character string name to refer to the cluster; however, the cluster numbers they assign do not have to be the same.

16.6.6.1 Using the name Argument with SYS$ASCEFC

The name argument to the Associate Common Event Flag Cluster (SYS$ASCEFC) system service identifies the cluster that the process is creating or associating with. The name argument specifies a descriptor pointing to a character string.

Translation of the name argument proceeds in the following manner:

  1. CEF$ is prefixed to the current name string, and the result is subjected to logical name translation.
  2. If the result is a logical name, step 1 is repeated until translation does not succeed or until the number of translations performed exceeds the number 10.
  3. The CEF$ prefix is stripped from the current name string that could not be translated. This current string is the cluster name.

For example, assume that you have made the following logical name assignment:


$ DEFINE CEF$CLUS_RT CLUS_RT_001

Assume also that your program contains the following statements:


 
#include <ssdef.h> 
#include <descrip.h> 
   .
   .
   .
        unsigned int status; 
        $DESCRIPTOR(name,"CLUS_RT"); /* Logical name of cluster */ 
   .
   .
   .
        status = SYS$ASCEFC(...,&name,...); 
 
 
 

The following logical name translation takes place:

  1. CEF$ is prefixed to CLUS_RT.
  2. CEF$CLUS_RT is translated to CLUS_RT_001. (Further translation is unsuccessful. When logical name translation fails, the string is passed to the service.)

There are two exceptions to the logical name translation method discussed in this section:

16.6.6.2 Temporary Common Event Flag Clusters

Common event flag clusters are either temporary or permanent. The perm argument to the SYS$ASCEFC system service defines whether the cluster is temporary or permanent.

Temporary clusters require an element of the creating process's quota for timer queue entries (TQELM quota). They are deleted automatically when all processes associated with the cluster have disassociated. Disassociation can be performed explicitly with the Disassociate Common Event Flag Cluster (SYS$DACEFC) system service, or implicitly when the image that called SYS$ASCEFC exits.

16.6.6.3 Permanent Common Event Flag Clusters

If you have the PRMCEB privilege, you can create a permanent common event flag cluster (set the perm argument to 1 when you invoke SYS$ASCEFC). A permanent event flag cluster continues to exist until it is marked explicitly for deletion with the Delete Common Event Flag Cluster (SYS$DLCEFC) system service (requires the PRMCEB privilege). Once a permanent cluster is marked for deletion, it is like a temporary cluster; when the last process that associated with the cluster disassociates from it, the cluster is deleted.

In the following examples, the first program segment associates common event flag cluster 3 with the name CLUSTER and then clears the second event flag in the cluster. The second program segment associates common event flag cluster 2 with the name CLUSTER and then sets the second event flag in the cluster (the flag cleared by the first program segment).

Example 1


STATUS = SYS$ASCEFC (%VAL(96), 
2                   'CLUSTER',,) 
STATUS = SYS$CLREF (%VAL(98)) 

Example 2


STATUS = SYS$ASCEFC (%VAL(64), 
2                   'CLUSTER',,) 
STATUS = SYS$SETEF (%VAL(66)) 

For clearer code, rather than using a specific event flag number, use one variable to contain the bit offset you need and one variable to contain the number of the first bit in the common event flag cluster that you are using. To reference the common event flag, add the offset to the number of the first bit. The following examples accomplish the same result as the preceding two examples:

Example 1


INTEGER*4 BASE, 
2         OFFSET 
PARAMETER (BASE = 96) 
 
OFFSET=2 
STATUS = SYS$ASCEFC (%VAL(BASE), 
2                   'CLUSTER',,) 
STATUS = SYS$CLREF (%VAL(BASE+OFFSET)) 

Example 2


INTEGER*4 BASE, 
2         OFFSET 
PARAMETER (BASE = 64) 
 
OFFSET=2 
STATUS = SYS$ASCEFC (%VAL(BASE), 
2                   'CLUSTER',,) 
STATUS = SYS$SETEF (%VAL(BASE+OFFSET)) 

Common event flags are often used for communicating between a parent process and a created subprocess. The following parent process associates the name CLUSTER with a common event flag cluster, creates a subprocess, and then waits for the subprocess to set event flag 64:


INTEGER*4 BASE, 
2         OFFSET 
PARAMETER (BASE   = 64, 
2          OFFSET = 0) 
   .
   .
   .
! Associate common event flag cluster with name 
STATUS = SYS$ASCEFC (%VAL(BASE), 
2                    'CLUSTER',,) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
 
! Create subprocess to execute concurrently 
MASK = IBSET (MASK,0) 
STATUS = LIB$SPAWN ('RUN REPORTSUB', ! Image 
2                   'INPUT.DAT',     ! SYS$INPUT 
2                   'OUTPUT.DAT',    ! SYS$OUTPUT 
2                   MASK) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
 
! Wait for response from subprocess 
STATUS = SYS$WAITFR (%VAL(BASE+OFFSET)) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
   .
   .
   .

REPORTSUB, the program executing in the subprocess, associates the name CLUSTER with a common event flag cluster, performs some set of operations, sets event flag 64 (allowing the parent to continue execution), and continues executing:


INTEGER*4 BASE, 
2         OFFSET 
PARAMETER (BASE   = 64, 
2          OFFSET = 0) 
   .
   .
   .
                     ! Do operations necessary for 
                     ! continuation of parent process 
   .
   .
   .
! Associate common event flag cluster with name 
STATUS = SYS$ASCEFC (%VAL(BASE), 
2                    'CLUSTER',,) 
IF (.NOT. STATUS) 
2  CALL LIB$SIGNAL (%VAL(STATUS)) 
 
! Set flag for parent process to resume 
STATUS = SYS$SETEF (%VAL(BASE+OFFSET)) 
   .
   .
   .


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5841PRO_048.HTML