[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS Programming Concepts Manual


Previous Contents Index

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");

}
  1. The call to SYS$SETIMR requests that event flag 4 be set in 30 seconds (expressed in the quadword B30SEC).
  2. 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;
}

  1. 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.
  2. 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.
  3. 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


Previous Next Contents Index