 |
OpenVMS Programming Concepts Manual
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.
Each numeric condition value has a unique symbolic name in the
following format:
where code is a mnemonic describing the return condition.
For example, the following symbol usually indicates a successful return:
An example of an error return condition value is as follows:
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:
- Write a short VAX MACRO program containing the desired macros.
- Assemble or compile the program and generate a listing. Using the
listing, find the desired symbols and their hexadecimal values.
- 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:
- 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
|
- 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
|
- 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
- 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.
- 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.
- ITEM_LIST_3_TYPE is a predeclared type in
package STARLET that defines the OpenVMS three-longword item list
structure.
- The dollar-sign character is not valid in Ada
identifiers; package STARLET defines the fac$ names by
removing the dollar sign.
- COND_VALUE_TYPE is a predeclared type in
package CONDITION_HANDLING that is used for return status values.
- 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.
- 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
- The SUB statement defines the routine and its
entry mask.
- The DECLARE WORD NAMLEN declaration reserves
a 16-bit word for the output value.
- The COMMON (BUF) STRING NAME_STRING = 255
declaration allocates 255 bytes for the output data in a static area.
The compiler builds the descriptor.
- 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).
- The input character string is specified
directly in the system service call; the compiler builds the descriptor.
- 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
- 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.)
- 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
|