 |
HP OpenVMS Programming Concepts Manual
27.2.1.3 Obtaining Delta Time with SYS$BINTIM
The SYS$BINTIM system service also converts ASCII strings to delta time
values to be used as input to timer services. The buffer for delta time
ASCII strings has the following format:
The first field, indicating the number of days, must be specified as 0
if you are specifying a delta time for the current day.
The following example shows how to use the SYS$BINTIM service to obtain
a delta time in system format:
#include <stdio.h>
#include <descrip.h>
/* Buffer to receive binary time */
struct {
unsigned int buff1, buff2;
}btenmin;
main() {
unsigned int status;
$DESCRIPTOR(atenmin,"0 00:10:00.00"); /* 10-min delta */
/* Convert time from ASCII to binary */
status = SYS$BINTIM(&atenmin, /* timbuf - time in ASCII */
&btenmin); /* timadr - binary time */
}
|
If you are programming in VAX MACRO, you can also specify approximate
delta time values when you assemble a program, using two MACRO .LONG
directives to represent a time value in 100-ns units. The arithmetic is
based on the following formula:
1 second = 10 million * 100 ns
|
For example, the following statement defines a delta time value of 5
seconds:
FIVESEC: .LONG -10*1000*1000*5,-1 ; Five seconds
|
The value 10 million is expressed as 10*1000*1000 for readability. Note
that the delta time value is negative.
If you use this notation, however, you are limited to the maximum
number of 100-ns units that can be expressed in a longword. In time
values this is slightly more than 7 minutes.
27.2.1.4 Obtaining Numeric and ASCII Time with SYS$NUMTIM
The Convert Binary Time to Numeric Time (SYS$NUMTIM) system service
converts a time in the system format into binary integer values. The
service returns each of the components of the time (year, month, day,
hour, and so on) into a separate word of a 7-word buffer. The
SYS$NUMTIM system service and the format of the information returned
are described in the HP OpenVMS System Services Reference Manual.
You use the SYS$ASCTIM system service to format the time in ASCII for
inclusion in an output string. The SYS$ASCTIM service accepts as an
argument the address of a quadword that contains the time in system
format and returns the date and time in ASCII format.
If you want to include the date and time in a character string that
contains additional data, you can format the output string with the
Formatted ASCII Output (SYS$FAO) system service. The SYS$FAO system
service converts binary values to ASCII representations, and
substitutes the results in character strings according to directives
supplied in an input control string. Among these directives are !%T and
!%D, which convert a quadword time value to an ASCII string and
substitute the result in an output string. For examples of how to do
this, see the discussion of $FAO in the HP OpenVMS System Services Reference Manual.
27.2.2 Date/Time Manipulation Routines
The run-time LIB$ facility provides several date/time manipulation
routines. These routines let you add, subtract, and multiply dates and
times. Use the LIB$ADDX and LIB$SUBX routines to add and subtract
times, since the times are defined in integer arrays. Use LIB$ADD_TIMES
and LIB$SUB_TIMES to add and subtract two quadword times. When
manipulating delta times, remember that they are stored as negative
numbers. For example, to add a delta time to an absolute time, you must
subtract the delta time from the absolute time. Use LIB$MULT_DELTA_TIME
and LIB$MULTF_DELTA_TIME to multiply delta times by scalar and floating
scalar.
Table 27-2 lists all the LIB$ routines that perform date/time
manipulation.
Table 27-2 Date/Time Manipulation Routines
Routine |
Function |
LIB$ADD_TIMES
|
Adds two quadword times
|
LIB$FORMAT_DATE_TIME
|
Formats a date and/or time for output
|
LIB$FREE_DATE_TIME_CONTEXT
|
Frees the date/time context
|
LIB$GET_MAXIMUM_DATE_LENGTH
|
Returns the maximum possible length of an output date/time string
|
LIB$GET_USERS_LANGUAGE
|
Returns the user's selected language
|
LIB$INIT_DATE_TIME_CONTEXT
|
Initializes the date/time context with a user-specified format
|
LIB$MULT_DELTA_TIME
|
Multiplies a delta time value by an integer scalar value
|
LIB$MULTF_DELTA_TIME
|
Multiplies a delta time value by an F-floating point scalar value
|
LIB$SUB_TIMES
|
Subtracts two quadword times
|
27.3 Timer Routines Used to Obtain and Set Current Time
This section presents information about obtaining the current date and
time, and setting current time. The run-time library (LIB$) facility
provides date/time utility routines for languages that do not have
built-in time and date functions. These routines return information
about the current date and time or a date/time specified by the user.
You can obtain the current time by using the LIB$DATE_TIME routine or
by implementing the SYS$GETTIM system service. To set the current time,
use the SYS$SETTIME system service.
Table 27-3 describes the date/time routines.
Table 27-3 Timer RTLs and System Services
Routine |
Function |
Timer Run-Time Library (LIB$) Routines |
LIB$DATE_TIME
|
Returns, using a string descriptor, the operating system date and time
in the semantics of a string that the user provides.
|
LIB$DAY
|
Returns the number of days since the system zero date of November 17,
1858. This routine takes one required argument and two optional
arguments:
- The address of a longword to contain the number of days since the
system zero date (required)
- A quadword passed by reference containing a time in system time
format to be used instead of the current system time (optional)
- A longword integer to contain the number of 10-millisecond units
since midnight (optional)
|
LIB$DAY_OF_WEEK
|
Returns the numeric day of the week for an input time value. If the
input time value is 0, the current day of the week is returned. The
days are numbered 1 through 7: Monday is day 1 and Sunday is day 7.
|
System Service Routine |
SYS$SETIME
|
Changes the value of or recalibrates the system time.
|
27.3.1 Obtaining Current Time and Date with LIB$DATE_TIME
The LIB$DATE_TIME routine returns a character string containing the
current date and time in absolute time format. The full string requires
a declaration of 23 characters. If you specify a shorter string, the
value is truncated. A declaration of 16 characters obtains only the
date. The following example displays the current date and time:
! Formatted date and time
CHARACTER*23 DATETIME
! Status and library procedures
INTEGER*4 STATUS,
2 LIB$DATE_TIME
EXTERNAL LIB$DATE_TIME
STATUS = LIB$DATE_TIME (DATETIME)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
TYPE *, DATETIME
|
27.3.2 Obtaining Current Time and Date with SYS$GETTIM
You can obtain the current date and time in internal format with the
SYS$GETTIM system service. You can convert from internal to character
format with the SYS$ASCTIM system service or a directive to the SYS$FAO
system service and convert back to internal format with the SYS$BINTIM
system service. The Get Time (SYS$GETTIM) system service places the
time into a quadword buffer. For example:
/* Buffer to receive the binary time */
struct {
unsigned int buff1, buff2;
}time;
.
.
.
main() {
unsigned status;
|
This call to SYS$GETTIM returns the current date and time in system
format in the quadword buffer TIME.
The Convert Binary Time to ASCII String (SYS$ASCTIM) system service
converts a time in system format to an ASCII string and returns the
string in a 23-byte buffer. You call the SYS$ASCTIM system service as
follows:
#include <stdio.h>
#include <descrip.h>
struct {
unsigned int buff1, buff2;
}time_value;
main() {
unsigned int status;
char timestr[23];
$DESCRIPTOR(atimenow, timestr);
/* Get binary time */
status = SYS$GETTIM(&time_value);
if ((status & 1) != 1)
LIB$SIGNAL( status );
/* Convert binary time to ASCII */
status = SYS$ASCTIM(0, /* timlen - Length of ASCII string */
&atimenow, /* timbuf - ASCII time buffer */
&time_value, /* timadr - Binary time */
0); /* cvtflags - Conversion indicator */
if ((status & 1) != 1)
LIB$SIGNAL( status );
}
|
Because the address of a 64-bit time value is not supplied, the default
value, 0, is used.
The string the service returns has the following format:
dd
|
Day of the month
|
MMM
|
Month (a 3-character alphabetic abbreviation)
|
yyyy
|
Year
|
hh:mm:ss.cc
|
Time in hours, minutes, seconds, and hundredths of a second
|
27.3.3 Setting the Current Time with SYS$SETIME
The Set System Time (SYS$SETIME) system service allows a user with the
operator (OPER) and logical I/O (LOG_IO) privileges to set the current
system time. You can specify a new system time (using the
timadr argument), or you can recalibrate the current
system time using the processor's hardware time-of-year clock (omitting
the timadr argument). If you specify a time, it must
be an absolute time value; a delta time (negative) value is invalid.
The system time is set whenever the system is bootstrapped. Normally
you do not need to change the system time between system bootstrap
operations; however, in certain circumstances you may want to change
the system time without rebooting. For example, you might specify a new
system time to synchronize two processors, or to adjust for changes
between standard time and Daylight Savings Time. Also, you may want to
recalibrate the time to ensure that the system time matches the
hardware clock time (the hardware clock is more accurate than the
system clock).
The DCL command SET TIME calls the SYS$SETIME system service.
If a process issues a delta time request and then the system time is
changed, the interval remaining for the request does not change; the
request executes after the specified time has elapsed. If a process
issues an absolute time request and the system time is changed, the
request executes at the specified time, relative to the new system time.
The following example shows the effect of changing the system time on
an existing timer request. In this example, two set timer requests are
scheduled: one is to execute after a delta time of 5 minutes and the
other specifies an absolute time of 9:00.
#include <stdio.h>
#include <descrip.h>
#include <ssdef.h>
#include <stdlib.h>
void gemini (int x);
unsigned int status;
/* Buffers to receive binary times */
struct {
unsigned int buff1, buff2;
}abs_binary, delta_binary;
main() {
$DESCRIPTOR(abs_time,"-- 19:37:00.00"); /* 9 am absolute time */
$DESCRIPTOR(delta_time,"0 :00:30"); /* 5-min delta time */
/* Convert ASCII absolute time to binary format */
status = SYS$BINTIM( &abs_time, /* ASCII absolute time */
&abs_binary); /* Converted to binary */
if (status == SS$_NORMAL)
{
status = SYS$SETIMR(0, /* efn - event flag */
&abs_binary, /* daytim - expiration time */
&gemini, /* astadr - AST routine */
1, /* reqidt - timer request id */
0); /* flags */
if (status == SS$_NORMAL)
printf("Setting system timer A\n");
}
else
LIB$SIGNAL( status );
/* Convert ASCII delta time to binary format */
status = SYS$BINTIM( &delta_time, /* ASCII delta time */
&delta_binary); /* Converted to binary */
if (status == SS$_NORMAL)
{
printf("Converting delta time to binary format\n");
status = SYS$SETIMR(0, /* efn - event flag */
&delta_binary, /* daytim - expiration time */
&gemini, /* astadr - AST routine */
2, /* reqidt - timer request id */
0); /* flags */
if (status == SS$_NORMAL)
printf("Setting system timer B\n");
else
LIB$SIGNAL( status );
}
else
LIB$SIGNAL( status );
status = SYS$HIBER();
}
void gemini (int reqidt) {
unsigned short outlen;
unsigned int cvtflg=1;
char timenow[12];
char fao_str[80];
$DESCRIPTOR(nowdesc, timenow);
$DESCRIPTOR(fao_in, "Request ID !UB answered at !AS");
$DESCRIPTOR(fao_out, fao_str);
/* Returns and converts the current time */
status = SYS$ASCTIM( 0, /* timlen - length of ASCII string */
&nowdesc, /* timbuf - receives ASCII string */
0, /* timadr - time value to convert */
cvtflg); /* cvtflg - conversion flags */
if ((status & 1) != 1)
LIB$SIGNAL( status );
/* Receives the formatted output string */
status = SYS$FAO(&fao_in, /* srcstr - control FAO string */
&outlen, /* outlen - length in bytes */
&fao_out, /* outbuf - output buffer */
reqidt, /* p1 - param needed for 1st FAO dir */
&nowdesc); /* p2 - param needed for 2nd FAO dir */
if ((status & 1) != 1)
LIB$SIGNAL( status );
status = LIB$PUT_OUTPUT( &fao_out );
return;
}
|
The following example shows the output received from the preceding
program. Assume the program starts execution at 8:45. Seconds later,
the system time is set to 9:15. The timer request that specified an
absolute time of 9:00 executes immediately, because 9:00 has passed.
The request that specified a delta time of 5 minutes times out at 9:20.
$ SHOW TIME
30-DEC-1993 8:45:04.56 +----------------------+
$ RUN SCORPIO | operator sets system |
<-----------------------------------------------| time to 9:15 |
Request ID number 1 executed at 09:15:00.00 +----------------------+
Request ID number 2 executed at 09:20:00.02
$
|
27.4 Routines Used for Timer Requests
This section presents information about setting and canceling timer
requests, and scheduling and canceling wakeups. Since many applications
require the scheduling of program activities based on clock time, the
operating system allows an image to schedule events for a specific time
of day or after a specified time interval. For example, you can use
timer system services to schedule, convert, or cancel events. For
example, you can use the timer system services to do the following:
- Schedule the setting of an event flag or the queuing of an
asynchronous system trap (AST) for the current process, or cancel a
pending request that has not yet been processed
- Schedule a wakeup request for a hibernating process, or cancel a
pending wakeup request that has not yet been processed
- Set or recalibrate the current system time, if the caller has the
proper user privileges
Table 27-4 describes system services that set, cancel, and schedule
timer requests.
Table 27-4 Timer System Services
Timer System Service Routine |
Function |
SYS$SETIMR
|
Sets the timer to expire at a specified time. This service sets a
per-thread timer.
|
SYS$CANTIM
|
Cancels all or a selected subset of the Set Timer requests previously
issued by the current image executing in a process. This service
cancels all timers associated with the process.
|
SYS$SCHDWK
|
Schedules the awakening (restarting) of a kernel thread that has placed
itself in a state of hibernation with the Hibernate (SYS$HIBER) service.
|
SYS$CANWAK
|
Removes all scheduled wakeup requests for a process from the timer
queue, including those made by the caller or by other processes. The
Schedule Wakeup ($SCHDWK) service makes scheduled wakeup requests.
|
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;
}
|
|