|
HP OpenVMS systems documentation |
Previous | Contents | Index |
When a system service completes, control is returned to your program. You can specify how and when control is returned to your program by choosing synchronous or asynchronous forms of system services and by enabling process execution modes.
The following sections describe:
You can execute a number of system services either asynchronously or synchronously (such as, SYS$GETJPI and SYS$GETJPIW or SYS$ENQ and SYS$ENQW). The W at the end of the system service name indicates the synchronous version of the system service.
The asynchronous version of a system service queues a request and returns control to your program. You can perform operations while the system service executes; however, you should not attempt to access information returned by the service until you check for the system service completion.
Typically, you pass to an asynchronous system service an event flag and an I/O status block or a lock status block. When the system service completes, it sets the event flag and places the final status of the request in the status block. You use the SYS$SYNCH system service to ensure that the system service has completed. You pass SYS$SYNCH the event flag and the status block that you passed to the asynchronous system service; SYS$SYNCH waits for the event flag to be set, then ensures that the system service (rather than some other program) sets the event flag by checking the status block. If the status block is still zero, SYS$SYNCH waits until the status block is filled.
The synchronous version of a system service acts exactly as if you had used the asynchronous version followed immediately by a call to SYS$SYNCH. If you omit the efn argument, the service uses event flag number 0 whether you use the synchronous or asynchronous version of a system service.
Example 20-1 illustrates the use of the SYS$SYNCH system service to check the completion status of the asynchronous service SYS$GETJPI.
Example 20-1 Example of SYS$SYNCH System Service in FORTRAN |
---|
! Data structure for SYS$GETJPI . . . INTEGER*4 STATUS, 2 FLAG, 2 PID_VALUE ! I/O status block INTEGER*2 JPISTATUS, 2 LEN INTEGER*4 ZERO /0/ COMMON /IO_BLOCK/ JPISTATUS, 2 LEN, 2 ZERO . . . ! Call SYS$GETJPI and wait for information STATUS = LIB$GET_EF (FLAG) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = SYS$GETJPI (%VAL(FLAG), 2 PID_VALUE, 2 , 2 NAME_BUF_LEN, 2 JPISTATUS, 2 ,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) . . . STATUS = SYS$SYNCH (%VAL(FLAG), 2 JPISTATUS) IF (.NOT. JPISTATUS) THEN CALL LIB$SIGNAL (%VAL(JPISTATUS)) END IF END |
Normally, when a system service is called and a required resource is not available, the process is placed in a wait state until the resource becomes available. Then the service completes execution. This mode is called resource wait mode.
In a real-time environment, however, it may not be practical or desirable for a program to wait. In these cases, you can choose to disable resource wait mode so that when a required resource is unavailable, control returns immediately to the calling program with an error condition value. You can disable (and reenable) resource wait mode with the Set Resource Wait Mode (SYS$SETRWM) system service.
If resource wait mode is disabled, it remains disabled until it is explicitly reenabled or until your process is deleted. For example, if your program has disabled resource wait mode and has exited to the DCL prompt, subsequent programs or utilities invoked by this process continue to run with resource wait mode disabled and might not perform properly because they are not prepared to handle a failure to obtain a resource. In this case, you should reenable the wait mode before your program exits to the DCL prompt.
How a program responds to the unavailability of a resource depends
primarily on the application and the particular service being called.
In some instances, the program may be able to continue execution and
retry the service call later. In other instances, it may be necessary
for the program to wait for the resource and the system service to
complete.
20.4.3 Condition Values Returned from System Services
When a service returns control to your program, it places a return status value in the general register R0 (R8, R9 for I64). The value in the low-order word indicates either that the service completed successfully or that some specific error prevented the service from performing some or all of its functions. After each call to a system service, you must check whether it completed successfully. You can also test for specific errors in the condition value.
Depending on your specific needs, you can test just the low-order bit, the low-order 3 bits, or the entire condition value, as follows:
Value | Meaning | Symbolic Name |
---|---|---|
0 | Warning | STS$K_WARNING |
1 | Success | STS$K_SUCCESS |
2 | Error | STS$K_ERROR |
3 | Informational | STS$K_INFO |
4 | Severe or fatal error | STS$K_SEVERR |
5--7 | Reserved |
Each numeric condition value has a unique symbolic name in the following format:
SS$_code |
where code is a mnemonic describing the return condition.
For example, the following symbol usually indicates a successful return:
SS$_NORMAL |
An example of an error return condition value is as follows:
SS$_ACCVIO |
This condition value indicates that an access violation occurred because a service could not read an input field or write an output field.
The symbolic definitions for condition values are included in the default system library SYS$LIBRARY:STARLET.OLB. You can obtain a listing of these symbolic codes at assembly time by invoking the system macro SYS$SSDEF. To check return conditions, use the symbolic names for system condition values.
The OpenVMS operating system does not automatically handle system
service failure or warning conditions; you must test for them and
handle them yourself. This contrasts with the operating system's
handling of exception conditions detected by the hardware or software;
the system handles these exceptions by default, although you can
intervene in or override the default handling by declaring a condition
handler.
20.4.4 Testing the Condition Value
Each language provides some mechanism for testing the return status. Often you need only check the low-order bit, such as by a test for TRUE (success or informational return) or FALSE (error or warning return). Condition values that are returned by system services can provide information and whether the service completed successfully. The condition value that usually indicates success is SS$_NORMAL, but others are defined. For example, the condition value SS$_BUFFEROVF, which is returned when a character string returned by a service is longer than the buffer provided to receive it, is a success code. This condition value, however, gives the program additional information.
Warning returns and some error returns indicate that the service performed some, but not all, of the requested function.
The possible condition values that each service can return are described with the individual service descriptions in the HP OpenVMS System Services Reference Manual. When you write calls to system services, read the descriptions of the return condition values to determine whether you want the program to check for particular return conditions.
To check the entire value for a specific return condition, each language provides a way for your program to determine the values associated with specific symbolically defined codes. You should always use these symbolic names when you write tests for specific conditions.
For information about how to test for these codes, see the user's guide
for your programming language.
20.4.4.1 Testing the Condition Value With $VMS_STATUS_SUCCESS Macro
You can use the $VMS_STATUS_SUCCESS macro, defined in stsdef.h, to test an OpenVMS condition value. $VMS_STATUS_SUCCESS depends on the documented format of an OpenVMS condition value, and particularly on the setting of the lowest bit in a condition value. If the lowest bit is set, the condition indicates a successful status, while the bit is clear for an unsuccessful status.
$VMS_STATUS_SUCCESS is used only with condition values that follow the OpenVMS condition status value format, and not with C standard library routines and return values that follow C native status value norms. For deails on the OpenVMS condition status value structure, please see Chapter 9. For information on the return values from the various C standard library routines, see the HP C Run-Time Library Reference Manual for OpenVMS Systems.
For example, the following code demonstrates a test that causes a return on error.
RetStat = sys$dassgn( IOChan ); if (!$VMS_STATUS_SUCCESS( RetStat )) return RetStat; |
Individual services have symbolic codes for special return conditions, argument list offsets, identifiers, and flags associated with these services. For example, the Create Process (SYS$CREPRC) system service (which is used to create a subprocess or a detached process) has symbolic codes associated with the various privileges and quotas you can grant to the created process.
The SYS$LIBRARY:SYS$LIB_C.TLB file contains the C header files for OpenVMS Alpha and OpenVMS I64 C data structures and definitions. For more information about SYS$LIBRARY:SYS$LIB_C.TLB, refer to Chapter 21.
The default system macro library, STARLET.MLB, contains the macro definitions for most system symbols. When you assemble a source program that calls any of these macros, the assembler automatically searches STARLET.MLB for the macro definitions. Each symbol name has a numeric value.
If your language has a method of obtaining values for these symbols, this method is explained in the user's guide.
If your language does not have such a method, you can do the following:
For example, to use the Get Job/Process Information ($GETJPI) system service to find out the accumulated CPU time (in 10-millisecond ticks) for a specified process, you must obtain the value associated with the item identifier JPI$_CPUTIM. You can do this in the following way:
.TITLE JPIDEF "Obtain values for $JPIDEF" $JPIDEF GLOBAL ; These MUST be UPPERCASE .END |
$ MACRO JPIDEF $ LINK/NOEXE/MAP/FULL JPIDEF %LINK-W-USRTFR, image NL:[].EXE; has no user transfer address |
$ MACRO/MIGRATION JPIDEF $ LINK/NOEXE/MAP/FULL JPIDEF %LINK-W-USRTFR, image NL:[].EXE; has no user transfer address |
To check for successful completion after a system service call, the program can test the low-order bit of R0 and branch to an error-checking routine if this bit is not set, as follows:
BLBC R0,errlabel ; Error if low bit clear |
Programs should not test for success by comparing the return status to SS$_NORMAL. A future release of OpenVMS may add new, alternate success codes to an existing service, causing programs that test for SS$_NORMAL to fail.
The error-checking routine may check for specific values or for specific severity levels. For example, the following VAX MACRO instruction checks for an illegal event flag number error condition:
CMPL #SS$_ILLEFC,R0 ; Is event flag number illegal? |
Note that return condition values are always longword values; however,
all system services always return the same value in the high-order word
of all condition values returned in R0.
20.4.7 System Messages Generated by Condition Values
When you execute a program with the DCL command RUN, the command interpreter uses the contents of R0 to issue a descriptive message if the program completes with an unsuccessful status. On I64, the calling standard specifies that the return status is returned in R8. As an aid to portable code, the MACRO compiler automatically maps uses of R0 to R8. See the HP OpenVMS MACRO Compiler Porting and User's Guide for additional information.
The following VAX MACRO code fragment shows a simple error-checking procedure in a main program:
$READEF_S - EFN=#64, - STATE=TEST BSBW ERROR . . . ERROR: BLBC R0,10$ ; Check register 0 RSB ; Success, return 10$: RET ; Exit with R0 status |
After a system service call, the BSBW instruction branches to the subroutine ERROR. The subroutine checks the low-order bit in register 0 and, if the bit is clear, branches to a RET instruction that causes the program to exit with the status of R0 preserved. Otherwise, the subroutine issues an RSB instruction to return to the main program.
If the event flag cluster requested in this call to $READEF is not currently available to the process, the program exits and the command interpreter displays the following message:
%SYSTEM-F-UNASEFC, unassociated event flag cluster |
The keyword UNASEFC in the message corresponds to the condition value SS$_UNASEFC.
The following three severe errors generated by the calls, not the services, can be returned from calls to system services:
Error | Meaning |
---|---|
SS$_ACCVIO |
The argument list cannot be read by the caller (using the $
name_G macro), and the service is not called.
This meaning of SS$_ACCVIO is different from its meaning for individual services. When SS$_ACCVIO is returned from individual services, the service is called, but one or more arguments to the service cannot be read or written by the caller. |
SS$_INSFARG | Not enough arguments were supplied to the service. |
SS$_ILLSER | An illegal system service was called. |
20.5 Program Examples with System Service Calls
This section provides code examples that illustrate the use of a system
service call in the following programming languages:
Ada --- Example 20-2
BASIC --- Example 20-3
BLISS --- Example 20-4
C --- Example 20-5
COBOL --- Example 20-6
FORTRAN --- Example 20-7
Pascal --- Example 20-8
VAX MACRO --- Example 20-9
PL/I, Fortran 77, and ADA 83 are not supported on OpenVMS I64. If your application has code written in PL/I, HP recommends rewriting it in another language such as C or C++. Update code written in Ada 83 to Ada 95, and code written in Fortran 77 to Fortran 90.
Example 20-2 System Service Call in Ada |
---|
with SYSTEM, TEXT_IO, STARLET, CONDITION_HANDLING; (1) procedure ORION is -- Declare variables to hold equivalence name and length -- EQUIV_NAME: STRING (1..255); (2) pragma VOLATILE (EQUIV_NAME); NAME_LENGTH: SYSTEM.UNSIGNED_WORD; pragma VOLATILE (NAME_LENGTH); -- Declare itemlist and fill in entries. -- ITEM_LIST: STARLET.ITEM_LIST_3_TYPE (1..2) := (3) (1 => (ITEM_CODE => STARLET.LNM_STRING, (4) BUF_LEN => EQUIV_NAME'LENGTH, BUF_ADDRESS => EQUIV_NAME'ADDRESS, RET_ADDRESS => NAME_LENGTH'ADDRESS), 2 => (ITEM_CODE => 0, BUF_LEN => 0, BUF_ADDRESS => SYSTEM.ADDRESS_ZERO, RET_ADDRESS => SYSTEM.ADDRESS_ZERO)); STATUS: CONDITION_HANDLING.COND_VALUE_TYPE; (5) begin -- Translate the logical name -- STARLET.TRNLNM ( (6) STATUS => STATUS, TABNAM => "LNM$FILE_DEV", LOGNAM => "CYGNUS", ITMLST => ITEM_LIST); -- Display name if success, else signal error -- if not CONDITION_HANDLING.SUCCESS (STATUS) then (7) CONDITION_HANDLING.SIGNAL (STATUS); else TEXT_IO.PUT ("CYGNUS translates to """); TEXT_IO.PUT (EQUIV_NAME (1..INTEGER(NAME_LENGTH))); TEXT_IO.PUT_LINE (""""); end if; end ORION; |
Example 20-3 System Service Call in BASIC |
---|
10 SUB ORION (1) ! Subprogram ORION OPTION TYPE=EXPLICIT ! Require declaration of all ! symbols EXTERNAL LONG FUNCTION SYS$TRNLNM ! Declare the system service EXTERNAL WORD CONSTANT LNM$_STRING ! The request code that ! we will use DECLARE WORD NAMLEN, (2) ! Word to receive length LONG SYS_STATUS ! Longword to receive status COMMON (BUF) STRING NAME_STRING = 255 (3) RECORD ITEM_LIST ! Define item ! descriptor structure WORD BUFFER_LENGTH ! The buffer length WORD ITEM ! The request code LONG BUFFER_ADDRESS ! The buffer address LONG RETURN_LENGTH_ADDRESS ! The address of the return len ! word LONG TERMINATOR ! The terminator END RECORD ITEM_LIST ! End of structure definition DECLARE ITEM_LIST ITEMS ! Declare an item list ITEMS::BUFFER_LENGTH = 255% ! Initialize the item list ITEMS::ITEM = LNM$_STRING ITEMS::BUFFER_ADDRESS = LOC( NAME_STRING ) ITEMS::RETURN_LENGTH_ADDRESS = LOC( NAMLEN ) ITEMS::TERMINATOR = 0 (4) SYS_STATUS = SYS$TRNLNM( , 'LNM$FILE_DEV', 'CYGNUS',, ITEMS) (5) IF (SYS_STATUS AND 1%) = 0% (6) THEN ! Error path ELSE ! Success path END IF END SUB |
Previous | Next | Contents | Index |