OpenVMS Programming Concepts Manual
19.3.5 Return Status
Your VAX MACRO program can test for errors by examining segments of the
32-bit status code returned by a run-time library routine.
To test for errors, check for a zero in bit 0 using a Branch on Low Bit
Set (BLBS) or Branch on Low Bit Clear (BLBC) instruction.
To test for a particular condition value, compare the 32 bits of the
return status with the appropriate return status symbol using a Compare
Long (CMPL) instruction or the run-time library routine LIB$MATCH_COND.
There are three ways to define a symbol for the condition value
returned by a run-time library routine so that you can compare the
value in R0 with a particular error code:
- Using the .EXTRN symbol directive. This causes the assembler to
generate an external symbol declaration.
- Using the $facDEF macro call. Calling the $LIBDEF macro,
for example, causes the assembler to define all LIB$ condition values.
- By default. The assembler automatically declares the condition
value as an external symbol that is defined as a global symbol in the
The following example asks for the user's name. It then calls the
run-time library routine LIB$GET_INPUT to read the user's response from
the terminal. If the string returned is longer than 30 characters (the
space allocated to receive the name), LIB$GET_INPUT returns in R0 the
condition value equivalent to the error LIB$_INPSTRTRU, 'input string
truncated.' This value is defined as a global symbol by default. The
example then checks for the specific error by comparing LIB$_INPSTRTRU
with the contents of R0. If LIB$_INPSTRTRU is the error returned, the
program considers that the routine executed successfully. If any other
error occurs, the program handles it as a true error.
$SSDEF ; Define SS$ symbols
$DSCDEF ; Define DSC$ symbols
PROMPT_D: ; Descriptor for prompt
.WORD PROMPT_LEN ; Length field
.BYTE DSC$K_DTYPE_T ; Type field is text
.BYTE DSC$K_CLASS_S ; Class field is string
.ADDRESS PROMPT ; Address
PROMPT: .ASCII /NAME: / ; String descriptor
PROMPT_LEN = . - PROMPT ; Calculate length of
STR_LEN = 30 ; Use 30-byte string
STRING_D: ; Input string descriptor
.WORD STR_LEN ; Length field
.BYTE DSC$K_DTYPE_T ; Type field in text
.BYTE DSC$K_CLASS_S ; Class field is string
.ADDRESS STR_AREA ; Address
STR_AREA: .BLKB STR_LEN ; Area to receive string
.ENTRY START , ^M<>
PUSHAQ PROMPT_D ; Push address of prompt
PUSHAQ STRING_D ; Push address of string
CALLS #2 , G^LIB$GET_INPUT ; Get input string
BLBS R0 , 10$ ; Check for success
CMPL R0 , #LIB$_INPSTRTRU ; Error: Was it
; truncated string?
BEQL 10$ ; No, more serious error
CALLS #1 , G^LIB$SIGNAL
10$: MOVL #SS$_NORMAL , R0 ; Success, or name too
19.3.6 Function Return Values in VAX MACRO
Function values are generally returned in R0 (32-bit values) or R0 and
R1 (64-bit values). A MACRO program can access a function value by
referencing R0 or R0 and R1 directly. For functions that return a
string, the address of the string or the address of its descriptor is
returned in R0. If a function needs to return a value larger than 64
bits, it must return the value by using an output argument.
Note the following exceptions to these rules:
- JSB entry points in the MTH$ facility return H_floating values in
R0 through R3.
- One routine, MTH$SINCOS, returns two function values: the sine and
the cosine of an angle. Depending on the data type of the function
values, the function values are returned in the following registers:
R0 and R1
R0 through R3
R0 through R3
R0 through R7
As in the case of output arguments, a variable declared to receive the
function values must be the same length as the value.
19.4 Calling a Library Routine in BLISS
This section describes how to code BLISS calls to library routines. A
called routine can return only one of the following:
- No value.
- A function value (typically, an integer or floating point number).
For example, MTH$SIN returns its result as an F_floating value in R0 on
VAX systems or F0 on Alpha systems.
On Alpha processors, BLISS
cannot access floating point registers.
- A return status (typically, a 32-bit condition value) indicating
that the routine has either executed successfully or failed. For
example, LIB$GET_INPUT returns a return status in R0. If the routine
executes successfully, it returns SS$_NORMAL; if not, it returns one of
several possible error condition values. BLISS treats the return status
like any other value.
19.4.1 BLISS Calling Sequence
Scalar arguments are usually passed to run-time library routines by
reference. Thus, when a BLISS program passes a variable, the variable
appears with no preceding period in the procedure-call actual argument
list. A constant value can be easily passed by using the %REF built-in
The following example shows how a BLISS program calls LIB$PUT_OUTPUT.
This routine writes a record at the user's terminal.
MODULE SHOWTIME(IDENT='1-1' %TITLE'Print time', MAIN=TIMEOUT)=
LIBRARY 'SYS$LIBRARY:STARLET'; ! Defines system services, etc.
DESC=%CHARCOUNT(%REMAINING), ! VAX string descriptor
UPLIT BYTE(%REMAINING) %; ! definition
FMTDESC=UPLIT( DESC('At the tone, the time will be ',
%CHAR(7), '!%T' ));
TIMEBUF: VECTOR, ! 64-bit system time
MSGBUF: VECTOR[80,BYTE], ! Output message buffer
MSGDESC: BLOCK[8,BYTE], ! Descriptor for message buffer
RSLT: WORD; ! Length of result string
! Initialize the fields of the string descriptor.
$GETTIM(TIMADR=TIMEBUF); ! Get time as 64-bit integer
$FAOL(CTRSTR=FMTDESC, ! Format descriptor
OUTLEN=RSLT, ! Output length (only a word!)
OUTBUF=MSGDESC, ! Output buffer desc.
PRMLST= %REF(TIMEBUF)); ! Address of 64-bit
! time block
MSGDESC [DSC$W_LENGTH] = .RSLT; ! Modify output desc.
RETURN (LIB$PUT_OUTPUT(MSGDESC); ! Return status
19.4.2 Accessing a Return Status in BLISS
BLISS accesses a function return value or condition value returned in
R0 as follows:
STATUS = LIB$PUT_OUTPUT(MSG_DESC);
IF NOT .STATUS THEN LIB$STOP(.STATUS);
19.4.3 Calling JSB Entry Points from BLISS
Many of the library mathematics routines have JSB entry points. You can
invoke these routines efficiently from a BLISS procedure using LINKAGE
and EXTERNAL ROUTINE declarations, as in the following example:
MODULE JSB_LINK (MAIN = MATH_JSB, ! Example of using JSB linkage
IDENT = '1-001',
ADDRESSING_MODE(EXTERNAL = GENERAL)) =
LINK_MATH_R4 = JSB (REGISTER = 0; ! input reg
REGISTER = 0): ! output reg
MTH$SIND_R4 : LINK_MATH_R4;
ROUTINE MATH_JSB = ! Routine
INPUT_VALUE : INITIAL (%E'30.0'),
! Get the sine of single floating 30 degrees. The input, 30 degrees,
! is passed in R0, and the answer, is returned in R0. Registers
! 0 to 4 are modified by MTH$SIND_R4.
MTH$SIND_R4 (.INPUT_VALUE ; SIN_VALUE);
END; ! End of routine
END ! End of module JSB_LINK
Calling System Services
The OpenVMS operating system kernel has many services that are made
available to application and system programs for use at run time. These
system services are procedures that the OpenVMS operating system uses
to control resources available to processes; to provide for
communication among processes; and to perform basic operating system
functions, such as the coordination of input/output operations. The
OpenVMS Programming Concepts Manual defines these functions further.
This chapter describes the basic methods and conventions for coding
calls to system services from OpenVMS high-level languages or from an
For more information about using the system services that support
64-bit addressing and to see example programs that demonstrate the use
of these services, refer to Chapter 11.
System services are called by using the conventions of the
OpenVMS Calling Standard. The programming languages that generate VAX or Alpha
native mode instructions provide mechanisms for specifying the
When you call a system service from your program, you must furnish
whatever arguments the routine requires. When the system service
procedure completes execution, in most cases it returns control to your
program. If the service returns a status code, your program should
check the value of the code to determine whether or not the service
completed successfully. If the return status indicates an error, you
may want to change the flow of execution of your program to handle the
error before returning control to your program.
When you write a program that calls a system service in the OpenVMS
operating system, the operating system views your program as a user
procedure. User procedures also can call other user procedures that are
either supplied by Compaq or written by you. Because an OpenVMS
native-mode language compiler program exists outside the operating
system, compiler generated programs calling any system service are also
defined as a set of user procedures.
If you program in a high-level language, refer to Chapter 21 for
information about the SYS$LIBRARY:SYS$LIB_C.TLB file, which is an
OpenVMS Alpha library of C header files.
For VAX MACRO, system service macros generate argument lists and CALL
instructions to call system services. These macros are located in the
system library (see SYS$LIBRARY:STARLET.MLB). When you assemble a
source program, this library is searched automatically for unresolved
references. (See Appendix D for further details.) Similar macros are
available for VAX BLISS and are located in SYS$LIBRARY:STARLET.REQ.
20.2 Preserving System Integrity
As described in the OpenVMS Programming Concepts Manual and the OpenVMS System Services Reference Manual, many system
services are available and suitable for application programs, but the
use of some of these powerful services must be restricted to protect
the performance of the system and the integrity of user processes.
For example, because the creation of permanent mailboxes uses system
dynamic memory, the unrestricted use of permanent mailboxes could
decrease the amount of memory available to other users. Therefore, the
ability to create permanent mailboxes is controlled: a user must be
specifically assigned the privilege to use the Create Mailbox
(SYS$CREMBX) system service to create a permanent mailbox.
The various controls and restrictions applied to system service usage
are described in this chapter. The Description section of each system
service in the OpenVMS System Services Reference Manual lists any privileges and quotas necessary
to use the service.
20.2.1 User Privileges
The system manager, who maintains the user authorization file for the
system, grants privileges for access to the protected system services.
The user authorization file contains, in addition to profile
information about each user, a list of specific user privileges and
When you log in to the system, the privileges and quotas assigned to
you are associated with the process created on your behalf. These
privileges and quotas are applied to every image the process executes.
When an image issues a call to a system service that is protected by
privilege, the privilege list is checked. If you have the specific
privilege required, the image is allowed to execute the system service;
otherwise, a condition value indicating an error is returned.
For a list of privileges, see the description of the Create Process
($CREPRC) system service in the OpenVMS System Services Reference Manual.
20.2.2 Resource Quotas
Many system services require certain system resources for execution.
These resources include system dynamic memory and process quotas for
I/O operations. When a system service that uses a resource controlled
by a quota is called, the process's quota for that resource is checked.
If the process has exceeded its quota, or if it has no quota allotment,
an error condition value may be returned.
20.2.3 Access Modes
A process can execute at any one of four access modes: user,
supervisor, executive, or kernel. The access modes determine a
process's ability to access pages of virtual memory. Each page has a
protection code associated with it, specifying the type of
access---read, write, or no access---allowed for each mode.
For the most part, user-written programs execute in user mode; system
programs executing at the user's request (system services, for example)
may execute at one of the other three, more privileged access modes.
In some system service calls, the access mode of the caller is checked.
For example, when a process tries to cancel timer requests, it can
cancel only those requests that were issued from the same or less
privileged access modes. For example, a process executing in user mode
cannot cancel a timer request made from supervisor, executive, or
Note that many system services use access modes to protect system
resources, and thus employ a special convention for interpreting access
mode arguments. You can specify an access mode using a numeric value or
a symbolic name. Table 20-1 shows the access modes and their numeric
values, symbolic names, and privilege ranks.
Table 20-1 OpenVMS System Access Modes
The symbolic names are defined by the symbolic definition macro
System services that permit an access mode argument allow callers to
specify only an access mode of equal or lesser privilege than the
access mode from which the service was called. If the specified access
mode is more privileged than the access mode from which the service was
called, the less privileged access mode is always used.
To determine the mode to use, the operating system compares the
specified access mode with the access mode from which the service was
called. Because this operation results in an access mode with a higher
numeric value (when the access mode of the caller is different from the
specified access mode), the access mode is said to be
Because much of the code you write executes in user mode, you can omit
the access mode argument. The argument value defaults to 0 (kernel
mode), and when this value is compared with the value of the current
execution mode (3, user mode), the higher value (3) is used.
20.3 System Service Call Entry
The Format section of each system service description in the
OpenVMS System Services Reference Manual indicates the positional dependencies and keyword names
of each argument, as shown in the following format:
$SERVICE arga ,argb ,argc ,argd
This format indicates that the macro name of the service is $SERVICE
and that it requires four arguments, ordered as shown and with keyword
names arga, argb,
argc, and argd.
Arguments passed to a service must be listed in your call entry in the
order shown in the Format section of the service description. Each
argument has four characteristics: OpenVMS usage, data type, access
type, and passing mechanism. These characteristics are described in
The OpenVMS Alpha SYS$LIBRARY:SYS$LIB_C.TLB file contains C function
prototypes for system services. These prototypes are documented in
OpenVMS System Services Reference Manual: A--GETUAI and and OpenVMS System Services Reference Manual: GETUTC--Z. For each prototype, the manuals
provide the correct syntax (which shows the arguments the function
accepts in the order in which it expects them), a description of each
argument, and the type of data returned by the function.
Some arguments are optional. Optional arguments are indicated by
brackets in the service descriptions. When your program invokes a
system service by using a CALL entry point, you can omit optional
arguments at the end of the argument list. If the optional argument is
not the last argument in the list, you must either pass a zero by value
or use a comma to indicate the place of the omitted argument. Some
languages, such as C, require that you pass a zero by value for all
trailing optional arguments. See your language processor documentation
for further information.
In the call statement of a high-level language program, you must prefix
the macro function service name with SYS (the system service facility
prefix). For example, the call statement in a C program procedure that
calls the SYS$GETDVI system service with four arguments is as follows:
return_status = sys$getdvi( event_flagnum, channel, &devnam, &item_list,0,0,0);
Note that in C, you must not omit the optional trailing arguments and
should pass a zero by value for these unused parameters. See your
language processor documentation for further information.
The OpenVMS System Services Reference Manual provides a description of each service that indicates
how each argument is to be passed. Phrases such as "an
address" and "address of a character string descriptor"
identify reference and descriptor arguments, respectively. Terms like
"Boolean value," "number," "value," or
"mask" indicate an argument that is passed by value.
In the Alpha and VAX environments, the called routine interprets each
argument using one of three standard passing mechanisms: by value, by
reference, or by descriptor.
On VAX systems, the calling program passes an argument list of
longwords to a called service; each longword in the argument list
specifies a single argument.
On Alpha systems, the calling program passes arguments in an argument
item sequence; each quadword in the sequence specifies a single
argument item. Note that the argument item sequence is formed using
R16--R21 or F16--F21 (a register for each argument).
For more detailed information on arguments lists and passing
mechanisms, see Sections 18.4 and 18.5.
Some services also require service-specific data structures that either
indicate functions to be performed or hold information to be returned.
The OpenVMS System Services Reference Manual includes descriptions of these service-specific data
structures. You can use this information and information from your
programming language manuals to define such service-specific item lists.
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:
- When synchronous system services return control to your program
- When asynchronous system services return control to your program
- How you can synchronize the completion of asynchronous system
- How control is returned to your program when special process
execution modes are enabled
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
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
! I/O status block
INTEGER*4 ZERO /0/
COMMON /IO_BLOCK/ JPISTATUS,
! 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),
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
STATUS = SYS$SYNCH (%VAL(FLAG),
IF (.NOT. JPISTATUS) THEN
CALL LIB$SIGNAL (%VAL(JPISTATUS))