Document revision date: 19 July 1999 | |
Previous | Contents | Index |
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.
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:
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.
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.
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. |
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:
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)) |
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:
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:
There are two exceptions to the logical name translation method discussed in this section:
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).
STATUS = SYS$ASCEFC (%VAL(96), 2 'CLUSTER',,) STATUS = SYS$CLREF (%VAL(98)) |
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:
INTEGER*4 BASE, 2 OFFSET PARAMETER (BASE = 96) OFFSET=2 STATUS = SYS$ASCEFC (%VAL(BASE), 2 'CLUSTER',,) STATUS = SYS$CLREF (%VAL(BASE+OFFSET)) |
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 |
privacy and legal statement | ||
5841PRO_048.HTML |