hp.com home products and services support and drivers solutions how to buy
cd-rom home
End of Jump to page title
HP OpenVMS systems
documentation

Jump to content


HP OpenVMS Programming Concepts Manual

HP OpenVMS Programming Concepts Manual


Previous Contents Index

20.4 System Service Completion

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:

20.4.1 Asynchronous and Synchronous System Services

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 

20.4.2 System Service Resource Wait Mode

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:

Table 20-2 Severity Codes of Condition Value Returned
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; 

20.4.5 Special Condition Values Using Symbolic Codes

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:

  1. Write a short VAX MACRO program containing the desired macros.
  2. Assemble or compile the program and generate a listing. Using the listing, find the desired symbols and their hexadecimal values.
  3. Define each symbol with its value within your source program.

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:

  1. Create the following three-line VAX MACRO program (named JPIDEF.MAR here; you can choose any name you want):


    .TITLE  JPIDEF  "Obtain values for $JPIDEF" 
    $JPIDEF GLOBAL          ; These MUST be UPPERCASE 
    .END 
    

  2. On VAX, assemble and link the program to create the file JPIDEF.MAP as follows:


    $ MACRO JPIDEF
    $ LINK/NOEXE/MAP/FULL  JPIDEF
    %LINK-W-USRTFR, image NL:[].EXE; has no user transfer address
    

    The file JPIDEF.MAP contains the symbols defined by $JPIDEF listed both alphabetically and numerically.
    On Alpha and I64, to compile the program to create the JPIDEF.MAP, enter the following:


    $ MACRO/MIGRATION JPIDEF
    $ LINK/NOEXE/MAP/FULL  JPIDEF
    %LINK-W-USRTFR, image NL:[].EXE; has no user transfer address
    

  3. Find the value of JPI$_CPUTIM and define the symbol in your program.

20.4.6 Testing the Return Condition Value for VAX MACRO

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; 

Ada Notes

  1. The with clause names the predefined packages of declarations used in this program. SYSTEM and TEXT_IO are standard Ada packages; STARLET defines the OpenVMS system service routines, data types, and constants; and CONDITION_HANDLING defines error-handling facilities.
  2. Enough space is allocated to EQUIV_NAME to hold the longest possible logical name. NAME_LENGTH will receive the actual length of the translated logical name. The VOLATILE pragma is required for variables that will be modified by means other than an assignment statement or being an output parameter to a routine call.
  3. ITEM_LIST_3_TYPE is a predeclared type in package STARLET that defines the OpenVMS three-longword item list structure.
  4. The dollar-sign character is not valid in Ada identifiers; package STARLET defines the fac$ names by removing the dollar sign.
  5. COND_VALUE_TYPE is a predeclared type in package CONDITION_HANDLING that is used for return status values.
  6. System services are defined in package STARLET using names that omit the prefix SYS$. The passing mechanisms are specified in the routine declaration in STARLET, so they need not be specified here.
  7. In this example, any failure status from the SYS$TRNLNM service is signaled as an error. Other means of error recovery are possible; see your Ada language documentation for more details.

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 
 
 

BASIC Notes


Previous Next Contents Index