HP OpenVMS systems
A procedure's JSB entry point name indicates the highest numbered register that the procedure modifies. Thus, a procedure with a suffix Rn modifies registers R0 through Rn. (You should always assume that R0 and R1 are modified.) The calling program loads the arguments in the registers before the JSB instruction is executed.
A calling program must use a JSB instruction to invoke a run-time library routine by means of its JSB entry point. You pass arguments to a JSB entry point by placing them in registers in the following manner:
NUM: .FLOAT 0.7853981 ; Constant P1/4 MOVF NUM, R0 ; Set up input argument JSB G^MTH$SIN_R4 ; Call F_floating sine procedure ; Return with value in R0
In this example, R4 in the entry point name indicates that MTH$SIN_R4 changes the contents of registers R0 through R4. The routine does not reference or change the contents of registers R5 through R11.
The entry mask of a calling procedure should specify all the registers to be saved if the procedure invokes a JSB routine. This step is necessary because a JSB procedure does not have an entry mask and thus has no way to specify registers to be saved or restored.
For example, consider program A calling procedure B by means of a CALL entry point.
A similar problem occurs if the stack is unwound, because unwinding the stack restores the contents of registers for each stack frame as it removes the previous frame. Because a JSB entry point does not create a stack frame, the contents of the registers before the JSB instruction will not be restored unless they were saved in the entry mask of the calling program. You do this by naming the registers to be saved in the calling program's entry mask, so a stack unwind correctly restores all registers from the stack. In the following example, the function Y=PROC(A,B) returns the value Y, where Y = SIN(A)*SIN(B):
.ENTRY PROC, ^M <R2, R3, R4, R5> ; Save R2:R5 MOVF @4(AP), R0 ; R0 = A JSB G^MTH$SIN_R4 ; R0 = SIN(A) MOVF R0 , R5 ; Copy result to register ; not modified by MTH$SIN MOVF @8(AP) , R0 ; R0 = B JSB G^MTH$SIN_R4 ; R0 = SIN(B) MULF R5 , R0 ; R0 = SIN(A)SIN(B) RET ; Return
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:
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 .PSECT $DATA 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 ; string 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 .PSECT $CODE .ENTRY START , ^M<> PUSHAQ PROMPT_D ; Push address of prompt ; descriptor PUSHAQ STRING_D ; Push address of string ; descriptor 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 PUSHL R0 CALLS #1 , G^LIB$SIGNAL 10$: MOVL #SS$_NORMAL , R0 ; Success, or name too ; long RET .END START
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:
|F_floating||R0 and R1|
|D_floating||R0 through R3|
|G_floating||R0 through R3|
|H_floating||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:
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 function.
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)= BEGIN LIBRARY 'SYS$LIBRARY:STARLET'; ! Defines system services, etc. MACRO DESC=%CHARCOUNT(%REMAINING), ! VAX string descriptor UPLIT BYTE(%REMAINING) %; ! definition BIND FMTDESC=UPLIT( DESC('At the tone, the time will be ', %CHAR(7), '!%T' )); EXTERNAL ROUTINE LIB$PUT_OUTPUT: ADDRESSING_MODE(GENERAL); ROUTINE TIMEOUT = BEGIN LOCAL 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. !- MSGDESC[DSC$B_CLASS]=DSC$K_CLASS_S; MSGDESC[DSC$B_DTYPE]=DSC$K_DTYPE_T; MSGDESC[DSC$W_LENGTH]=80; MSGDESC[DSC$A_POINTER]=MSGBUF $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 END; END ELUDOM
BLISS accesses a function return value or condition value returned in R0 (R8, R9 for I64) as follows:
STATUS = LIB$PUT_OUTPUT(MSG_DESC); IF NOT .STATUS THEN LIB$STOP(.STATUS);
I64 register usage differs from that of Alpha and VAX. If you use OpenVMS high-level languages, the register and register mapping differences in the calling standards are handled by the compilers and are not exposed to your code. However, if your code uses BLISS linkages to interface with Macro-32 source code, your code might have to take into account the differences in register mapping.
BLISS added a new qualifier and source level switch to enable register mapping for register numbers in linkage and register declarations. It is off by default. BLISS also has additional support for linkages that reference arguments.
See your compiler documentation for additional information.
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)) = BEGIN LINKAGE LINK_MATH_R4 = JSB (REGISTER = 0; ! input reg REGISTER = 0): ! output reg NOPRESERVE (0,1,2,3,4) NOTUSED (5,6,7,8,9,10,11); EXTERNAL ROUTINE MTH$SIND_R4 : LINK_MATH_R4; FORWARD ROUTINE MATH_JSB; LIBRARY 'SYS$LIBRARY:STARLET.L32'; ROUTINE MATH_JSB = ! Routine BEGIN LOCAL INPUT_VALUE : INITIAL (%E'30.0'), SIN_VALUE; !+ ! 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); RETURN SS$_NORMAL; END; ! End of routine END ! End of module JSB_LINK ELUDOM
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.
This chapter describes the basic methods and conventions for coding calls to system services from OpenVMS high-level languages or from an assembly language.
System services are called by using the conventions of the HP OpenVMS Calling Standard. The programming languages that generate VAX, Alpha, or I64 native mode instructions provide mechanisms for specifying the procedure calls.
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 HP 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 and OpenVMS I64 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 BLISS and are located in SYS$LIBRARY:STARLET.REQ.
20.2 Preserving System Integrity
As described in this document and the HP 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 HP 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 resource quotas.
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 HP 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 kernel mode.
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.
The symbolic names are defined by the symbolic definition macro SYS$PSLDEF.
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 maximized.
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 HP 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 Chapter 17.
The OpenVMS Alpha and OpenVMS I64 SYS$LIBRARY:SYS$LIB_C.TLB file contains C function prototypes for system services. These prototypes are documented in HP OpenVMS System Services Reference Manual: A--GETUAI and and HP 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 HP 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, VAX, and I64 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).
On I64 systems, the first eight parameters are passed in R32 through R39, with the parameter count in R25 and subsequent parameters in quadwords on the stack.
Some services also require service-specific data structures that either indicate functions to be performed or hold information to be returned. The HP 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.