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

3.7.2 Placing Entries in the System Timer Queue

When you use the system timer queue, you use the timer expiration to signal when a routine is to be executed. It allows the caller to request a timer that will activate sometime in the future. The timer is requested for the calling kernel thread. When the timer activates, the event is reported to that thread. It does not affect any other thread in the process.

For the actual signal, you can use an event flag or AST. With this method, you do not need a separate process to control program execution. However, you do use up your process's quotas for ASTs and timer queue requests.

Use the system service SYS$SETIMR to place a request in the system timer queue. The format of this service is as follows:

SYS$SETIMR ([efn] ,daytim ,[astadr] ,[reqidt] ,[flags]) 

Specifying the Starting Time

Specify the absolute or delta time at which you want the program to begin execution using the daytim argument. Use the SYS$BINTIM system service to convert an ASCII time to the binary system format required for this argument.

Signaling Timer Expiration

Once the system has reached this time, the timer expires. To signal timer expiration, set an event flag in the efn argument or specify an AST routine to be executed in the astadr argument. Refer to Section 16.6 and Chapter 5 for more information about using event flags and ASTs.

How Timer Requests Are Identified

The reqidt argument identifies each system time request uniquely. Then, if you need to cancel a request, you can refer to each request separately.

To cancel a timer request, use the SYS$CANTIM system service.

3.8 Controlling Kernel Threads and Process Execution

You can control kernel threads and process execution in the following ways:

3.8.1 Process Hibernation and Suspension

There are two ways to halt the execution of a kernel thread or process temporarily:

The kernel thread can continue execution normally only after a corresponding Wake from Hibernation (SYS$WAKE) system service (if it is hibernating), or after a Resume Process (SYS$RESUME) system service, if it is suspended.

Suspending or hibernating a kernel thread puts it into a dormant state; the thread is not deleted.

A process in hibernation can control itself; a process in suspension requires another process to control it. Table 3-8 compares hibernating and suspended processes.

Table 3-8 Process Hibernation and Suspension
Hibernation Suspension
Can cause onlt self to hibernate. Can suspend self or another process, depending on privilege; suspends all threads associated with the specified process.
Reversed by SYS$WAKE/SYS$SCHDWK system service. Reversed by SYS$RESUME system service.
Interruptible; can receive ASTs. Noninterruptible; cannot receive ASTs 1.
Can wake self. Cannot cause self to resume.
Can schedule wakeup at an absolute time or at a fixed time interval. Cannot schedule resumption.


1If a process is suspended in kernel mode (a hard suspension), it cannot receive any ASTs. If a process is suspended at supervisor mode (a soft suspension), it can receive executive or kernel mode ASTs. See the description of SYS$SUSPND in the OpenVMS System Services Reference Manual: GETQUI--Z.

Table 3-9 summarizes the system services and routines that can place a process in or remove a process from hibernation or suspension.

Table 3-9 System Services and Routines Used for Hibernation and Suspension
Routine Function
Hibernating Processes
SYS$HIBER Places the requesting kernel thread in the hibernation state. An AST can be delivered to the thread while it is hibernating. The service puts only the calling thread into HIB; no other thread is affected.
SYS$WAKE Resumes execution of a kernel thread in hibernation. This service wakes all hibernating kernel threads in a process regardless of the caller. Any thread that is not hibernating when the service is called is marked wake pending. Because of the wake pending, the next call to SYS$HIBER completes immediately and the thread does not hibernate. Premature wakeups must be handled in the code.
SYS$SCHDWK Resumes execution of a kernel thread in hibernation at a specified time. This service schedules a wakeup request for a thread that is about to call SYS$HIBER. The wakeup affects only the requesting thread; any other hibernating kernel threads are not affected.
LIB$WAIT Uses the services SYS$SCHDWK and SYS$HIBER.
SYS$CANWAK Cancels a scheduled wakeup issued by SYS$SCHDWK. Unless called with a specific timer request ID, this service cancels all timers for all threads in the process regardless of the calling thread.
Suspended Kernel Threads and Processes
SYS$SUSPEND Puts in a suspended state all threads associated with the specified process.
SYS$RESUME Puts in an execution state all threads of the specified process.

3.8.1.1 Using Process Hibernation

The hibernate/wake mechanism provides an efficient way to prepare an image for execution and then to place it in a wait state until it is needed.

If you create a subprocess that must execute the same function repeatedly and must execute immediately when it is needed, you could use the SYS$HIBER and SYS$WAKE system services, as shown in the following example:


/* Process TAURUS */ 
 
#include <stdio.h> 
#include <descrip.h> 
 
main() { 
 
        unsigned int status; 
        $DESCRIPTOR(prcnam,"ORION");                
        $DESCRIPTOR(image,"COMPUTE.EXE"); 
 
/* Create ORION */                      
        status = SYS$CREPRC(0,                (1)        /* Process id */ 
                            &image,                       /* Image */ 
                            0, 0, 0, 0, 0, 
                            &prcnam,                      /* Process name */ 
                            0, 0, 0, 0); 
        if ((status & 1) != 1) 
                LIB$SIGNAL(status); 
   .
   .
   .
/* Wake ORION */ 
        status = SYS$WAKE(0, &prcnam);          (2)
        if ((status & 1) != 1) 
                LIB$SIGNAL(status); 
   .
   .
   .
/* Wake ORION again */ 
        status = SYS$WAKE(0, &prcnam); 
        if ((status & 1) != 1) 
                LIB$SIGNAL(status); 
   .
   .
   .
} 
 
/* Process ORION and image COMPUTE */ 
 
#include <stdio.h> 
#include <ssdef.h> 
   .
   .
   .
sleep: 
        status = SYS$HIBER();                  (3)
        if ((status & 1) != 1) 
                LIB$SIGNAL(status); 
   .
   .
   .
        goto sleep; 
} 

  1. Process TAURUS creates the process ORION, specifying the descriptor for the image named COMPUTE.
  2. At an appropriate time, TAURUS issues a SYS$WAKE request for ORION. ORION continues execution following the SYS$HIBER service call. When it finishes its job, ORION loops back to repeat the SYS$HIBER call and to wait for another wakeup.
  3. The image COMPUTE is initialized, and ORION issues the SYS$HIBER system service.

The Schedule Wakeup (SYS$SCHDWK) system service, a variation of the SYS$WAKE system service, schedules a wakeup for a hibernating process at a fixed time or at an elapsed (delta) time interval. Using the SYS$SCHDWK service, a process can schedule a wakeup for itself before issuing a SYS$HIBER call. For an example of how to use the SYS$SCHDWK system service, see Chapter 6.

Hibernating processes can be interrupted by asynchronous system traps (ASTs), as long as AST delivery is enabled. The process can call SYS$WAKE on its own behalf in the AST service routine, and continue execution following the execution of the AST service routine. For a description of ASTs and how to use them, see Chapter 5.

3.8.1.2 Using Alternative Methods of Hibernation

You can use two additional methods to cause a process to hibernate:

When you use the SYS$CREPRC system service, the creating process can control when to wake the created process. When you use the RUN command, its qualifiers control when to wake the process.

If you use the /INTERVAL qualifier and the image to be executed does not call the SYS$HIBER system service, the image is placed in a state of hibernation whenever it issues a return instruction (RET). Each time the image is awakened, it begins executing at its entry point. If the image does call SYS$HIBER, each time it is awakened it begins executing at either the point following the call to SYS$HIBER or at its entry point (if it last issued a RET instruction).

If wakeup requests are scheduled at time intervals, the image can be terminated with the Delete Process (SYS$DELPRC) or Force Exit (SYS$FORCEX) system service, or from the command level with the STOP command. The SYS$DELPRC and SYS$FORCEX system services are described in Section 3.8.3.4 and in Section 3.8.4. The RUN and STOP commands are described in the OpenVMS DCL Dictionary.

These methods allow you to write programs that can be executed once, on request, or cyclically. If an image is executed more than once in this manner, normal image activation and termination services are not performed on the second and subsequent calls to the image. Note that the program must ensure both the integrity of data areas that are modified during its execution and the status of opened files.

3.8.1.3 Using SYS$SUSPND

Using the Suspend Process (SYS$SUSPND) system service, a process can place itself or another process into a wait state similar to hibernation. Suspension, however, is a more pronounced state of hibernation. The operating system provides no system service to force a process to be swapped out, but the SYS$SUSPND system service can accomplish the task in the following way. Suspended processes are the first processes to be selected for swapping. A suspended process cannot be interrupted by ASTs, and it can resume execution only after another process calls a Resume Process (SYS$RESUME) system service on its behalf. If ASTs are queued for the process while it is suspended, they are delivered when the process resumes execution. This is an effective tool for blocking delivery of all ASTs.

At the DCL level, you can suspend a process by issuing the SET PROCESS command with the /SUSPEND qualifier. This command temporarily stops the process's activities. The process remains suspended until another process resumes or deletes it. To allow a suspended process to resume operation, use either the /NOSUSPEND or /RESUME qualifier.

3.8.2 Passing Control to Another Image

The RTL routines LIB$DO_COMMAND and LIB$RUN_PROGRAM allow you to invoke the next image from the current image. That is, they allow you to perform image rundown for the current image and pass control to the next image without returning to DCL command level. Which routine you use depends on whether the next image is a command image or a noncommand image.

3.8.2.1 Invoking a Command Image

The following DCL command executes the command image associated with the DCL command COPY:


$ COPY DATA.TMP APRIL.DAT

To pass control from the current image to a command image, use the run-time library (RTL) routine LIB$DO_COMMAND. If LIB$DO_COMMAND executes successfully, control is not returned to the invoking image, and statements following the LIB$DO_COMMAND statement are not executed. The following statement causes the current image to exit and executes the DCL command in the preceding example:


   .
   .
   .
STATUS = LIB$DO_COMMAND ('COPY DATA.TMP APRIL.DAT') 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
 
END 

To execute a number of DCL commands, specify a DCL command procedure. The following statement causes the current image to exit and executes the DCL command procedure [STATS.TEMP]CLEANUP.COM:


   .
   .
   .
STATUS = LIB$DO_COMMAND ('@[STATS.TEMP]CLEANUP') 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
 
END 

3.8.2.2 Invoking a Noncommand Image

You invoke a noncommand image at DCL command level with the DCL command RUN. The following command executes the noncommand image [STATISTICS.TEMP]TEST.EXE:


$ RUN [STATISTICS.TEMP]TEST

To pass control from the current image to a noncommand image, use the run-time library routine LIB$RUN_PROGRAM. If LIB$RUN_PROGRAM executes successfully, control is not returned to the invoking image, and statements following the LIB$RUN_PROGRAM statement are not executed. The following program segment causes the current image to exit and passes control to the noncommand image [STATISTICS.TEMP]TEST.EXE on the default disk:


   .
   .
   .
STATUS = LIB$RUN_PROGRAM ('[STATISTICS.TEMP]TEST.EXE') 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
 
END 

3.8.3 Performing Image Exit

When image execution completes normally, the operating system performs a variety of image rundown functions. If the image is executed by the command interpreter, image rundown prepares the process for the execution of another image. If the image is not executed by the command interpreter---for example, if it is executed by a subprocess---the process is deleted.

Main programs and main routines terminate by executing a return instruction (RET). This instruction returns control to the caller, which could have been LIB$INITIALIZE, the debugger, or the command interpreter. The completion code, SS$_NORMAL, which has the value 1, should be used to indicate normal successful completion.

Any other condition value can be used to indicate success or failure. The command language interpreter uses the condition value as the parameter to the Exit (SYS$EXIT) system service. If the severity field (STS$V_SEVERITY) is SEVERE or ERROR, the continuation of a batch job or command procedure is affected.

These exit activities are also initiated when an image completes abnormally as a result of any of the following conditions:

3.8.3.1 Performing Image Rundown

The operating system performs image rundown functions that release system resources obtained by a process while it is executing in user mode. These activities occur in the following order:

  1. Any outstanding I/O requests on the I/O channels are canceled, and I/O channels are deassigned.
  2. Memory pages occupied or allocated by the image are deleted, and the working set size limit of the process is readjusted to its default value.
  3. All devices allocated to the process at user mode are deallocated (devices allocated from the command stream in supervisor mode are not deallocated).
  4. Timer-scheduled requests, including wakeup requests, are canceled.
  5. Common event flag clusters are disassociated.
  6. Locks are dequeued as a part of rundown.
  7. User mode ASTs that are queued but have not been delivered are deleted, and ASTs are enabled for user mode.
  8. Exception vectors declared in user mode, compatibility mode handlers, and change mode to user handlers are reset.
  9. System service failure exception mode is disabled.
  10. All process private logical names and logical name tables created for user mode are deleted. Deletion of a logical name table causes all names in that table to be deleted. Note that names entered in shareable logical name tables, such as the job or group table, are not deleted at image rundown, regardless of the access mode for which they were created.

3.8.3.2 Initiating Rundown

To initiate the rundown activities described in Section 3.8.3.1, the system calls the Exit (SYS$EXIT) system service on behalf of the process. In some cases, a process can call SYS$EXIT to terminate the image itself (for example, if an unrecoverable error occurs).

You should not call the SYS$EXIT system service directly from a main program. By not calling SYS$EXIT directly from a main program, you allow the main program to be more like ordinary modular routines and therefore usable by other programmers as callable routines.

The SYS$EXIT system service accepts a status code as an argument. If you use SYS$EXIT to terminate image execution, you can use this status code argument to pass information about the completion of the image. If an image returns without calling SYS$EXIT, the current value in R0 is passed as the status code when the system calls SYS$EXIT.

This status code is used as follows:

3.8.3.3 Performing Cleanup and Rundown Operations

Use exit handlers to perform image-specific cleanup or rundown operations. For example, if an image uses memory to buffer data, an exit handler can ensure that the data is not lost when the image exits as the result of an error condition.

To establish an exit-handling routine, you must set up an exit control block and specify the address of the control block in the call to the Declare Exit Handler (SYS$DCLEXH) system service. You can call an exit handler by using standard calling conventions; you can provide arguments to the exit handler in the exit control block. The first argument in the control block argument list must specify the address of a longword for the system to write the status code from SYS$EXIT.

If an image declares more than one exit handler, the control blocks are linked together on a last-in, first-out (LIFO) basis. After an exit handler is called and returns control, the control block is removed from the list. You can remove exit control blocks prior to image exit by using the Cancel Exit Handler (SYS$CANEXH) system service.

Exit handlers can be declared from system routines executing in supervisor or executive mode. These exit handlers are also linked together in other lists, and they receive control after exit handlers that are declared from user mode are executed.

Exit handlers are called as a part of the SYS$EXIT system service. While a call to the SYS$EXIT system service often precedes image rundown activities, the call is not a part of image rundown. There is no way to ensure that exit handlers will be called if an image terminates in a nonstandard way.


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_011.HTML