 |
OpenVMS Programming Concepts Manual
27.4.1 Setting Timer Requests with SYS$SETIMR
Timer requests made with the Set Timer (SYS$SETIMR) system service are
queued; that is, they are ordered for processing according to their
expiration times. The quota for timer queue entries (TQELM quota)
controls the number of entries a process can have pending in this timer
queue.
When you call the SYS$SETIMR system service, you can specify either an
absolute time or a delta time value. Depending on how you want the
request processed, you can specify either or both of the following:
- The number of an event flag to be set when the time expires. If you
do not specify an event flag, the system sets event flag 0.
- The address of an AST service routine to be executed when the time
expires.
Optionally, you can specify a request identification for the timer
request. You can use this identification to cancel the request, if
necessary. The request identification is also passed as the AST
parameter to the AST service routine, if one is specified, so that the
AST service routine can identify the timer request.
Example 27-2 and Example 27-3 show timer requests using event flags
and ASTs, respectively. Event flags, event flag services, and ASTs are
described in more detail in Chapter 8.
Example 27-2 Setting an Event Flag |
#include <stdio.h>
#include <ssdef.h>
#include <descrip.h>
/* Buffer to receive binary time */
struct {
unsigned int buff1, buff2;
}b30sec;
main() {
unsigned int efn = 4,status;
$DESCRIPTOR(a30sec,"0 00:00:30.00");
/* Convert time to binary format */
status = SYS$BINTIM( &a30sec, /* timbuf - ASCII time */
&b30sec);/* timadr - binary time */
if ((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Converting ASCII to binary time...\n");
/* Set timer to wait */
status = SYS$SETIMR( efn, /* efn - event flag */
&b30sec,/* daytim - binary time */
0, /* astadr - AST routine */
0, /* reqidt - timer request */
0); /* flags */ (1)
if ((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Request event flag be set in 30 seconds...\n");
/* Wait 30 seconds */
status = SYS$WAITFR( efn ); (2)
if ((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Timer expires...\n");
}
|
- The call to SYS$SETIMR requests that event
flag 4 be set in 30 seconds (expressed in the quadword B30SEC).
- The Wait for Single Event Flag (SYS$WAITFR)
system service places the process in a wait state until the event flag
is set. When the timer expires, the flag is set and the process
continues execution.
Example 27-3 Specifying an AST Service
Routine |
#include <stdio.h>
#include <descrip.h>
#define NOON 12
struct {
unsigned int buff1, buff2;
}bnoon;
/* Define the AST routine */
void astserv( int );
main() {
unsigned int status, reqidt=12;
$DESCRIPTOR(anoon,"-- 12:00:00.00");
/* Convert ASCII time to binary */
status = SYS$BINTIM(&anoon, /* timbuf - ASCII time */ (1)
&bnoon); /* timadr - binary time buffer */
if((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Converting ASCII to binary...\n");
/* Set timer */
status = SYS$SETIMR(0, /* efn - event flag */ (2)
&bnoon, /* daytim - timer expiration */
&astserv, /* astadr - AST routine */
reqidt, /* reqidt - timer request id */
0); /* cvtflg - conversion flags */
if((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Setting timer expiration...\n");
status = SYS$HIBER();
}
void astserv( int astprm ) { (3)
/* Do something if it's a "noon" request */
if (astprm == NOON)
printf("This is a noon AST request\n");
else
printf("Handling some other request\n");
status = SYS$SCHDWK(0, /* pidadr - process id */
0);/* prcnam - process name */
return;
}
|
- The call to SYS$BINTIM converts the ASCII
string representing 12:00 noon to format. The value returned in BNOON
is used as input to the SYS$SETIMR system service.
- The AST routine specified in the SYS$SETIMR
request will be called when the timer expires, at 12:00 noon. The
reqidt argument identifies the timer request. (This
argument is passed as the AST parameter and is stored at offset 4 in
the argument list. See Chapter 8.) The process continues execution;
when the timer expires, it is interrupted by the delivery of the AST.
Note that if the current time of day is past noon, the timer expires
immediately.
- This AST service routine checks the
parameter passed by the reqidt argument to determine
whether it must service the 12:00 noon timer request or another type of
request (identified by a different reqidt value). When
the AST service routine completes, the process continues execution at
the point of interruption.
27.4.2 Canceling a Timer Request with SYS$CANTIM
The Cancel Timer Request (SYS$CANTIM) system service cancels timer
requests that have not been processed. The SYS$CANTIM system service
removes the entries from the timer queue. Cancellation is based on the
request identification given in the timer request. For example, to
cancel the request illustrated in Example 27-3, you would use the
following call to SYS$CANTIM:
unsigned int status, reqidt=12;
.
.
.
status = SYS$CANTIM( reqidt, 0);
|
If you assign the same identification to more than one timer request,
all requests with that identification are canceled. If you do not
specify the reqidt argument, all your requests are
canceled.
27.4.3 Scheduling Wakeups with SYS$WAKE
Example 27-2 shows a process placing itself in a wait state using the
SYS$SETIMR and SYS$WAITFR services. A process can also make itself
inactive by hibernating. A process hibernates by issuing the Hibernate
(SYS$HIBER) system service. Hibernation is reversed by a wakeup
request, which can be put into effect immediately with the SYS$WAKE
system service or scheduled with the Schedule Wakeup (SYS$SCHDWK)
system service. For more information about the SYS$HIBER and SYS$WAKE
system services, see Chapter 4.
The following example shows a process scheduling a wakeup for itself
prior to hibernating:
#include <stdio.h>
#include <descrip.h>
struct {
unsigned int buff1, buff2;
}btensec;
main() {
unsigned int status;
$DESCRIPTOR(atensec,"0 00:00:10.00");
/* Convert time */
status = SYS$BINTIM(&atensec, /* timbuf - ASCII time */
&btensec);/* timadr - binary time */
if ((status & 1 ) != 1)
LIB$SIGNAL( status );
/* Schedule wakeup */
status = SYS$SCHDWK(0, /* pidadr - process id */
0, /* prcnam - process name */
&btensec, /* daytim - wake up time */
0); /* reptim - repeat interval */
if ((status & 1 ) != 1)
LIB$SIGNAL( status );
/* Sleep ten seconds */
status = SYS$HIBER();
if ((status & 1 ) != 1)
LIB$SIGNAL( status );
}
|
Note that a suitably privileged process can wake or schedule a wakeup
request for another process; thus, cooperating processes can
synchronize activity using hibernation and scheduled wakeups. Moreover,
when you use the SYS$SCHDWK system service in a program, you can
specify that the wakeup request be repeated at fixed time intervals.
See Chapter 4 for more information on hibernation and wakeup.
27.4.4 Canceling a Scheduled Wakeup with SYS$CANWAK
You can cancel scheduled wakeup requests that are pending but have not
yet been processed with the Cancel Wakeup (SYS$CANWAK) system service.
This service cancels a wakeup request for a specific kernel thread, if
a process ID is specified. If a process name is specified, then the
initial thread's wakeup request is canceled.
The following example shows the scheduling of wakeup requests for the
process CYGNUS and the subsequent cancellation of the wakeups. The
SYS$SCHDWK system service in this example specifies a delta time of 1
minute and an interval time of 1 minute; the wakeup is repeated every
minute until the requests are canceled.
#include <stdio.h>
#include <descrip.h>
/* Buffer to hold one minute */
struct {
unsigned int buff1, buff2;
}interval;
main() {
unsigned int status;
$DESCRIPTOR(one_min,"0 00:01:00.00"); /* One minute delta */
$DESCRIPTOR(cygnus, "CYGNUS"); /* Process name */
/* Convert time to binary */
status = SYS$BINTIM(&one_min, /* timbuf - ASCII delta time */
&interval); /* timadr - Buffer to hold binary time */
if((status & 1) != 1)
LIB$SIGNAL( status );
else
printf("Converting time to binary format...\n");
/* Schedule wakeup */
status = SYS$SCHDWK(0, /* pidadr - process id */
&cygnus, /* prcnam - process name */
&interval, /* daytim - time to be awakened */
&interval); /* reptim - repeat interval */
if((status & 1) != 1)
LIB$SIGNAL( status );
}
else
printf("Scheduling wakeup...\n");
/* Cancel wakeups */
status = SYS$CANWAK(0, /* pidadr - process id */
&cygnus); /* prcnam - process name */
}
|
27.4.5 Executing a Program at Timed Intervals
To execute a program at timed intervals, you can use either the
LIB$SPAWN routine or the SYS$CREPRC system service. With LIB$SPAWN, you
can create a subprocess that executes a command procedure containing
three commands: the DCL command WAIT, the command that invokes the
desired program, and a GOTO command that directs control back to the
WAIT command. To prevent the parent process from remaining in
hibernation until the subprocess executes, you should execute the
subprocess concurrently; that is, you should specify CLI$M_NOWAIT.
For more information about using LIB$SPAWN and SYS$CREPRC, see
Chapter 4.
27.5 Routines Used for Timer Statistics
This section presents information about the LIB$INIT_TIMER,
LIB$SHOW_TIMER, LIB$STAT_TIMER, and LIB$FREE_TIMER routines. By calling
these run-time library routines, you can collect the following timer
statistics from the system:
- Elapsed time---Actual time that has passed since setting a timer
- CPU time---CPU time that has passed since setting a timer
- Buffered I/O---Number of buffered I/O operations that have occurred
since setting a timer
- Direct I/O---Number of direct I/O operations that have occurred
since setting a timer
- Page faults---Number of page faults that have occurred since
setting a timer
Following are descriptions of each routine:
- LIB$INIT_TIMER---Allocates and initializes space for collecting the
statistics. You should specify the handle-adr argument
as a variable with a value of 0 to ensure the modularity of your
program. When you specify the argument, the system collects the
information in a specially allocated area in dynamic storage. This
prevents conflicts with other timers used by the application.
- LIB$SHOW_TIMER---Obtains one or all of five statistics (elapsed
time, CPU time, buffered I/O, direct I/O, and page faults); the
statistics are formatted for output. The handle-adr
argument must be the same value as specified for LIB$INIT_TIMER (do not
modify this variable). Specify the code argument to
obtain one particular statistic rather than all the statistics.
You can let the system write the statistics to SYS$OUTPUT (the
default), or you can process the statistics with your own routine. To
process the statistics yourself, specify the name of your routine in
the action-rtn argument. You can pass one argument to
your routine by naming it in the user-arg argument. If
you use your own routine, it must be written as an integer function and
return an error code (return a value of 1 for success). This error code
becomes the error code returned by LIB$SHOW_TIMER. Two arguments are
passed to your routine: the first is a passed-length character string
containing the formatted statistics, and the second is the value of the
fourth argument (if any) specified to LIB$SHOW_TIMER.
- LIB$STAT_TIMER---Obtains one of five unformatted statistics.
Specify the statistic you want in the code argument.
Specify a storage area for the statistic in value. The
handle-adr argument must be the same value as you
specified for LIB$INIT_TIMER.
- LIB$FREE_TIMER---Ensures the modularity of your program. Invoke
this procedure when you are done with the timer. The value in the
handle-adr argument must be the same as that specified
for LIB$INIT_TIMER.
You must invoke LIB$INIT_TIMER to allocate storage for the timer. You
should invoke LIB$FREE_TIMER before you exit from your program unit. In
between, you can invoke LIB$SHOW_TIMER or LIB$STAT_TIMER, or both, as
often as you want. Example 27-4 invokes LIB$SHOW_TIMER and uses a
user-written subprogram either to display the statistics or to write
them to a file.
Example 27-4 Displaying and Writing Timer
Statistics |
.
.
.
! Timer arguments
INTEGER*4 TIMER_ADDR,
2 TIMER_DATA,
2 TIMER_ROUTINE
EXTERNAL TIMER_ROUTINE
! Declare library procedures as functions
INTEGER*4 LIB$INIT_TIMER,
2 LIB$SHOW_TIMER
EXTERNAL LIB$INIT_TIMER,
2 LIB$SHOW_TIMER
! Work variables
CHARACTER*5 REQUEST
INTEGER*4 STATUS
! User request - either WRITE or FILE
INTEGER*4 WRITE,
2 FILE
PARAMETER (WRITE = 1,
2 FILE = 2)
! Get user request
WRITE (UNIT=*, FMT='($,A)') ' Request: '
ACCEPT *, REQUEST
IF (REQUEST .EQ. 'WRITE') TIMER_DATA = WRITE
IF (REQUEST .EQ. 'FILE') TIMER_DATA = FILE
! Set timer
STATUS = LIB$INIT_TIMER (TIMER_ADDR)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Get statistics
STATUS = LIB$SHOW_TIMER (TIMER_ADDR,,
2 TIMER_ROUTINE,
2 TIMER_DATA)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
! Free timer
STATUS = LIB$FREE_TIMER (TIMER_ADDR)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
.
.
.
INTEGER FUNCTION TIMER_ROUTINE (STATS,
2 TIMER_DATA)
! Dummy arguments
CHARACTER*(*) STATS
INTEGER TIMER_DATA
! Logical unit number for file
INTEGER STATS_FILE
! User request
INTEGER WRITE,
2 FILE
PARAMETER (WRITE = 1,
2 FILE = 2)
! Return code
INTEGER SUCCESS,
2 FAILURE
PARAMETER (SUCCESS = 1,
2 FAILURE = 0)
! Set return status to success
TIMER_ROUTINE = SUCCESS
! Write statistics or file them in STATS.DAT
IF (TIMER_DATA .EQ. WRITE) THEN
TYPE *, STATS
ELSE IF (TIMER_DATA .EQ. FILE) THEN
CALL LIB$GET_LUN (STATS_FILE)
OPEN (UNIT=STATS_FILE,
2 FILE='STATS.DAT')
WRITE (UNIT=STATS_FILE,
2 FMT='(A)') STATS
ELSE
TIMER_ROUTINE = FAILURE
END IF
END
|
You can use the SYS$GETSYI system service to obtain more detailed
system information about boot time, the cluster, processor type,
emulated instructions, nodes, paging files, swapping files, and
hardware and software versions. With SYS$GETQUI and LIB$GETQUI, you can
obtain queue information.
27.6 Date/Time Formatting Routines
This section provides information about using date/time formatting
routines that allow you to specify input and output formats other than
the standard operating system format for dates and times. These include
international formats with appropriate language spellings for days and
months.
If the desired language is English (the default language) and the
desired format is the standard operating system format, then
initialization of logical names is not required in order to use the
date/time input and output routines. However, if the desired language
and format are not the defaults, the system manager (or any user having
CMEXEC, SYSNAM, and SYSPRV privileges) must initialize the required
logical names.
27.6.1 Performing Date/Time Logical Initialization
Note
You must complete the initialization steps outlined in this section
before you can use any of the date/time input and output routines with
languages and formats other than the defaults.
|
As an alternative to the standard operating system format, the command
procedure SYS$MANAGER:LIB$DT_STARTUP.COM defines several output formats
for dates and times. This command procedure must be executed by the
system manager before using any of the run-time library date/time
routines for input or output formats other than the default. Ideally,
this command procedure should be executed from a site-specific startup
procedure.
In addition to defining the date/time formats, the LIB$DT_STARTUP.COM
command procedure also defines spellings for date and time elements in
languages other than English. If different language spellings are
required, the system manager must define the logical name SYS$LANGUAGES
before invoking LIB$DT_STARTUP.COM. The translation of SYS$LANGUAGES is
then used to select which languages are defined.
Table 27-5 shows the available languages and their logical names.
Table 27-5 Available Languages for Date/Time Formatting
Language |
Logical Name |
Austrian
|
AUSTRIAN
|
Danish
|
DANISH
|
Dutch
|
DUTCH
|
Finnish
|
FINNISH
|
French
|
FRENCH
|
French Canadian
|
CANADIAN
|
German
|
GERMAN
|
Hebrew
|
HEBREW
|
Italian
|
ITALIAN
|
Norwegian
|
NORWEGIAN
|
Portuguese
|
PORTUGUESE
|
Spanish
|
SPANISH
|
Swedish
|
SWEDISH
|
Swiss French
|
SWISS_FRENCH
|
Swiss German
|
SWISS_GERMAN
|
For example, if the system managers want the spellings for French,
German, and Italian languages to be defined, they must define
SYS$LANGUAGES as shown, prior to invoking LIB$DT_STARTUP.COM:
$ DEFINE SYS$LANGUAGES FRENCH, GERMAN, ITALIAN
|
If the user requires an additional language, for example FINNISH, then
the system manager must add FINNISH to the definition of SYS$LANGUAGES
and reexecute the command procedure.
Date/Time Manipulation Option
The Date/Time Manipulation option provides date/time spelling support
for four new
languages. Users or application programmers can select the desired
language by defining the logical name SYS$LANGUAGES. The new languages
and their equivalent names are as follows:
Language |
Equivalent Name |
Chinese (simplified character)
|
Hanzi
|
Chinese (traditional character)
|
Hanyu
|
Korean
|
Hangul
|
Thai
|
Thai
|
Defining Date/Time Spelling
To define the spelling for Hanzi and Hanyu, define SYS$LANGUAGES as
shown below, prior to invoking LIB$DT_STARTUP.COM:
$ DEFINE SYS$LANGUAGES HANZI, HANYU
$ @SYS$MANAGER:LIB$DT_STARTUP
|
Predefined Output Formats
Figure 27-1 lists the new predefined date format logical names in the
first column, their formats in the second column, and examples of the
output generated using these formats in the third column.
Figure 27-1 Predefined Output Date Formats
Note
LIB$DATE_FORMAT_042 and LIB$DATE_FORMAT_043 support the DEC Hanzi coded
character set.
LIB$DATE_FORMAT_044 and LIB$DATE_FORMAT_045 support the DEC Hanyu coded
character set.
LIB$DATE_FORMAT_046 and LIB$DATE_FORMAT_047 support the DEC Hangul
coded character set.
|
Figure 27-2 lists the new predefined time format logical names in the
first column, their formats in the second column, and examples of the
output generated using these formats in the third column.
Figure 27-2 Predefined Output Time Formats
Note
LIB$TIME_FORMAT_021 supports the DEC Hanzi coded character set.
LIB$TIME_FORMAT_022 supports the DEC Hanyu coded character set.
LIB$TIME_FORMAT_023 supports the DEC Hangul coded character set.
|
Thus, to select a particular format for a date or time, or both, you
can define the LIB$DT_FORMAT logical name using the following logicals:
- LIB$DATE_FORMAT_nnn, where nnn can range from 001
to 047
- LIB$TIME_FORMAT_nnn, where nnn can range from 001
to 023
|