Document revision date: 30 March 2001

## OpenVMS Programming Concepts Manual

Previous | Contents | Index

### 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. 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:

- The low-order bit indicates successful (1) or unsuccessful (0) completion of the service.
- The low-order 3 bits, taken together, represent the severity of the error. Table 20-2 lists the possible severity code values returned.
  For VAX MACRO, the symbolic definition macro SYS$STSDEF defines the symbolic names. For the C programming language, the SSDEF.H file defines the symbolic names.
- The remaining bits (bits 3 through 31) classify the particular return condition and the operating system component that issued the condition value. For system service return status values, the high-order word (bits 16 through 31) contains zeros.

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 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.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 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. 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.
   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 Assembly Languages

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.

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

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

1. The SUB statement defines the routine and its entry mask.
2. The DECLARE WORD NAMLEN declaration reserves a 16-bit word for the output value.
3. The COMMON (BUF) STRING NAME_STRING = 255 declaration allocates 255 bytes for the output data in a static area. The compiler builds the descriptor.
4. The SYS$ form invokes the system service as a function.
   Enclose the arguments in parentheses and specify them in positional order only. Specify a comma for each optional argument that you omit (including trailing arguments).
5. The input character string is specified directly in the system service call; the compiler builds the descriptor.
6. The IF statement performs a test on the low-order bit of the return status. This form is recommended for all status returns.

Example 20-4 System Service Call in BLISS

    MODULE ORION=

    BEGIN
    EXTERNAL ROUTINE
        ERROR_PROC: NOVALUE;                 ! Error processing routine

    LIBRARY 'SYS$LIBRARY:STARLET.L32';       ! Library containing OpenVMS
                                             ! macros (including $TRNLNM).
                                             ! This declaration
                                             ! is required.

    GLOBAL ROUTINE ORION: NOVALUE=

        BEGIN
        OWN
            NAMBUF : VECTOR[255, BYTE],       ! Output buffer
            NAMLEN : WORD,                    ! Translated string length
            ITEMS : BLOCK[16,BYTE]
                    INITIAL(WORD(255,         ! Output buffer length
                            LNM$_STRING),     ! Item code
                            NAMBUF,           ! Output buffer
                            NAMLEN,           ! Address of word for
                                              ! translated
                                              ! string length
                            0);               ! List terminator

        LOCAL                                 ! Return status from
            STATUS;                           ! system service

        STATUS = $TRNLNM(TABNAM = %ASCID'LNM$FILE_DEV',
                         LOGNAME = %ASCID'CYGNUS',
                         ITMLST = ITEMS); (1)

        IF NOT .STATUS THEN ERROR_PROC(.STATUS);  (2)

        END;

BLISS Notes

1. The macro is invoked by its service name, without a suffix.
   Enclose the arguments in parentheses and specify them by keyword. (Keyword names correspond to the names of the arguments shown in lowercase in the system service format descriptions in the OpenVMS System Services Reference Manual.)
2. The return status, which is assigned to the variable STATUS, is tested for TRUE or FALSE. FALSE (low bit = 0) indicates failure or warning.

Example 20-5 System Service Call in C

     #include <starlet.h> (1)
     #include <lib$routines.h>
     #include <ssdef.h>
     #include <lnmdef.h>
     #include <descrip.h>
     #include <stdio.h>

     typedef struct {                 (2)
         unsigned short  buffer_length;
         unsigned short  item_code;
         char     *buffer_addr;
         short     *return_len_addr;
         unsigned     terminator;
     } item_list_t;

     main ()
     {                                          (3)
         $DESCRIPTOR(table_name, "LNM$FILE_DEV");
         $DESCRIPTOR(log_name, "CYGNUS");
         char    translated_name[255];
         int     status;
         short   return_length;
         item_list_t item_list;

         item_list.buffer_length = sizeof(translated_name); (4)
         item_list.item_code = LNM$_STRING;
         item_list.buffer_addr = translated_name;
         item_list.return_len_addr = &return_length;
         item_list.terminator = 0;

         status = sys$trnlnm(0, &table_name, &log_name, 0, &item_list);  (5)

         if (!(status & 1))       (6)
             lib$signal(status);
         else
             printf("The logical name %s is equivalent to %*s\n",
                 log_name.dsc$a_pointer,
                 return_length,
                 translated_name);
     }

C Notes

Previous | Next | Contents | Index

| privacy and legal statement |
5841PRO_055.HTML