HP OpenVMS Programming Concepts Manual
In the previous example, if the structures
will be used interchangeably within the same source module, you can
eliminate the symbol FOODEF64. The routine foo_print would then be
defined as follows:
int foo_print (void * foo_ptr);
Eliminating the FOODEF64 symbol allows 32-bit and 64-bit callers to use
the same function prototype; however less strict type checking is then
available during the C source compilation.
11.4.2 OpenVMS Alpha, OpenVMS VAX, and OpenVMS I64 Guidelines
The following sections provide guidelines about using arguments on
OpenVMS Alpha, OpenVMS VAX, and OpenVMS I64 systems.
Only address, size, and length arguments should be passed as quadwords by value.
Arguments passed by value are restricted to longwords on VAX. To be
compatible with VAX APIs, quadword arguments should be passed by
reference instead of by value. However, addresses, sizes and lengths
are examples of arguments which, because of the architecture, could
logically be longwords on OpenVMS VAX and quadwords on OpenVMS Alpha
and OpenVMS I64.
Even if the API will not be available on OpenVMS VAX, this guideline
should still be followed for consistency across all APIs.
Avoid page size dependent units.
Arguments such as lengths and offsets should be represented in units
that are page size independent, such as bytes.
A pagelet is an awkward unit. It was invented for compatibility with
VAX and is used on OpenVMS Alpha and OpenVMS I64 within OpenVMS VAX
compatible interfaces. A pagelet is equivalent in size to a VAX page
and should not be considered a page size independent unit because it is
often confused with a CPU-specific page on Alpha and OpenVMS I64.
Example: Length_64 argument in EXPREG_64 is passed as
a quadword byte count by value.
Naturally align all data passed by reference.
The called routine should specify to the compiler that arguments are
aligned, and the compiler can perform more efficient load and store
sequences. If the data is not naturally aligned, users will experience
If the called routine can execute incorrectly because the data passed
by reference is not naturally aligned, the called routine should do
explicit checking and return an error if not aligned. For example, if a
load/locked, store/conditional is being done internally in the routine
on the data, and the data is not aligned, the load/locked,
store/conditional will not work properly.
11.4.3 Promoting an API from a 32-Bit API to a 64-Bit API
For ease of use, it is best to separate promoting an API from improving
the 32-bit design or adding new functionality. Calling a routine within
the new 64-bit API should be an easy programming task.
64-bit routines should accept 32-bit forms of structures as well as 64-bit forms.
To make it easy to modify calls to an API, the 32-bit form of a
structure should be accepted by the interface as well as the 64-bit
Example: If the 32-bit API passed information by
descriptor, the new interface should pass the same information by
64-bit routines should provide the same functionality as the 32-bit routines.
An application currently calling the 32-bit API should be able to
completely upgrade to calling the 64-bit API without having to preserve
some of the old calls to the old 32-bit API just because the new 64-bit
API is not a functional superset of the old API.
Example: SYS$EXPREG_64 works for P0, P1 and P2 process
space. Callers can replace all calls to SYS$EXPREG since SYS$EXPREG_64
is a functional superset of $EXPREG.
Use the suffix "_64" when appropriate.
For system services, this suffix is used for routines that accept
64-bit addresses by reference. For promoted routines, this
distinguishes the 64-bit capable version from its 32-bit counterpart.
For new routines, it is a visible reminder that a 64-bit wide address
cell will be read/written. This is also used when a structure is passed
that contains an embedded 64-bit address, if the structure is not
self-identifying as a 64-bit structure. Hence, a routine name need not
include "_64" simply because it receives a 64-bit descriptor. Remember
that passing an arbitrary value by reference does not mean the suffix
is required, passing a 64-bit address by reference does.
This practice is recommended for other routines as well.
SYS$EXPREG_64 (region_id_64, length_64, acmode, return_va_64,
SYS$CMKRNL_64 (routine_64, quad_arglst_64)
11.4.4 Example of a 32-Bit Routine and a 64-Bit Routine
The following example illustrates a 32-bit routine interface that has
been promoted to support 64-bit addressing. It handles several of the
issues addressed in the guidelines.
The C function declaration for an old system service SYS$CRETVA looks
like the following:
#pragma required_pointer_size save
#pragma required_pointer_size 32
int sys$cretva (
struct _va_range * inadr,
struct _va_range * retadr,
unsigned int acmode);
#pragma required_pointer_size restore
The C function declaration for a new system service SYS$CRETVA_64 looks
like the following:
#pragma required_pointer_size save
#pragma required_pointer_size 64
int sys$cretva_64 (
struct _generic_64 * region_id_64,
void * start_va_64,
unsigned __int64 length_64,
unsigned int acmode,
void ** return_va_64,
unsigned __int64 * return_length_64);
#pragma required_pointer_size restore
The new routine interface for SYS$CRETVA_64 corrects the embedded
pointers within the
structure, passes the 64-bit
argument by reference and passes the 64-bit
argument by value.
11.5 OpenVMS Alpha and OpenVMS I64 Tools and Utilities That Support 64-Bit Addressing
This section briefly describes the following OpenVMS Alpha and OpenVMS
I64 tools that support 64-bit virtual addressing:
- OpenVMS Debugger
- System-code debugger
- LIB$ and CVT$ facilities of the OpenVMS Run-Time Library
- Watchpoint utility (The Watchpoint utility has not been ported to
11.5.1 OpenVMS Debugger
On OpenVMS Alpha and OpenVMS I64 systems, the Debugger can access the
extended memory made available by 64-bit addressing support. You can
examine and manipulate data in the complete 64-bit address space.
You can examine a variable as a quadword by using the option Quad,
which is on the Typecast menu of both the Monitor pull-down menu and
the Examine dialog box.
The default type for the debugger is longword, which
is appropriate for debugging 32-bit applications. You should change the
default type to quadword for debugging applications
that use the 64-bit address space. To do this, use the SET TYPE
Note that hexadecimal addresses are 16-digit numbers on Alpha and
OpenVMS I64. For example,
DBG> EVALUATE/ADDRESS/HEX %hex 000004A0
The debugger supports 32-bit and 64-bit pointers.
For more information about using the OpenVMS Debugger, see the
HP OpenVMS Debugger Manual.
11.5.2 OpenVMS Alpha System-Code Debugger
The OpenVMS Alpha system-code debugger accepts 64-bit addresses and
uses full 64-bit addresses to retrieve information.
XDELTA supports 64-bit addressing on OpenVMS Alpha and OpenVMS I64.
Quadword display mode displays full quadwords of information. 64-bit
address display mode accepts and displays all addresses as 64-bit
XDELTA has predefined command strings for displaying the contents of
the PFN database.
For more information about Delta/XDelta, see the HP OpenVMS Delta/XDelta Debugger Manual.
11.5.4 LIB$ and CVT$ Facilities of the OpenVMS Run-Time Library
For more information about 64-bit addressing support for the LIB$ and
CVT$ facilities of the OpenVMS RTL library, refer to the OpenVMS
RTL Library (LIB$) Manual.
11.5.5 Watchpoint Utility
The Watchpoint utility is a debugging tool that maintains a history of
modifications that are made to a particular location in shared system
space by setting watchpoints on 64-bit addresses. It watches any system
address, whether in S0, S1, or S2 space.
A $QIO interface to the Watchpoint utility supports 64-bit addresses.
The WATCHPOINT command interpreter (WP) issues $QIO requests to the
WATCHPOINT driver (WPDRIVER) from commands that follow the standard
rules of DCL grammar.
Enter commands at the WATCHPOINT> prompt to set, delete, and obtain
information from watchpoints. Before invoking the WATCHPOINT command
interpreter (WP) or loading the WATCHPOINT driver, you must set the
SYSGEN MAXBUF dynamic parameter to 64000, as follows:
$ RUN SYS$SYSTEM:SYSGEN
SYSGEN> SET MAXBUF 64000
SYSGEN> WRITE ACTIVE
Before invoking WP, you must install the WPDRIVER with SYSMAN, as
$ RUN SYS$SYSTEM:SYSMAN
SYSMAN> IO CONNECT WPA0/DRIVER=SYS$WPDRIVER/NOADAPTER
You can then invoke WP with the following command:
Now you can enter commands at the WATCHPOINT> prompt to set, delete,
and obtain information from watchpoints.
You can best view the WP help screens as well as the output to the
Watchpoint utility using a terminal set to 132 characters, as follows:
SDA allows a user to specify 64-bit addresses and 64-bit values in
expressions. It also displays full 64-bit values where appropriate.
The following commands have been enhanced or are new in OpenVMS Version
8.2 for I64 use.
- SET CPU
For more information about using SDA 64-bit addressing support, see the
HP OpenVMS System Analysis Tools Manual.
11.6 Language and Pointer Support for 64-Bit Addressing
Full support in HP C and the HP C Run-Time Library (RTL) for 64-bit
addressing make C the preferred language for programming 64-bit
applications, libraries, and system code for OpenVMS Alpha and OpenVMS
I64. The 64-bit pointers can be seamlessly integrated into existing C
code, and new 64-bit applications can be developed, with natural C
coding styles, that take advantage of the 64-bit address space provided
by OpenVMS Alpha and OpenVMS I64.
Support for all 32-bit pointer sizes (the default), all 64-bit pointer
sizes, and the mixed 32-bit and 64-bit pointer size environment provide
compatibility as well as flexibility for programming 64-bit OpenVMS
applications in HP C.
The ANSI-compliant, #pragma approach for supporting the mixed 32-bit
and 64-bit pointer environment is common to Tru64 UNIX. Features of
64-bit C support include memory allocation routine name mapping
(transparent support for _malloc64 and _malloc32) and C-type checking
for 32-bit versus 64-bit pointer types.
The OpenVMS Calling Standard describes the techniques used by all
OpenVMS languages for invoking routines and passing data between them.
The standard also defines the mechanisms that ensure consistency in
error and exception handling routines.
The OpenVMS Calling Standard provides the following support for 64-bit
- Called routines can start to use complete 64-bit addresses.
- Callers can pass either 32-bit or 64-bit pointers.
- Pointers passed by reference often require a new 64-bit variant of
the original routine.
- Self-identifying structures, such as those defined for descriptors
and item lists, enable an existing API to be enhanced compatibly.
OpenVMS Alpha and OpenVMS I64 64-bit addressing support for mixed
pointers also includes the following features:
- OpenVMS Alpha and OpenVMS I64 64-bit virtual address space layout
that applies to all processes. (There are no special 64-bit processes
or 32-bit processes.)
- 64-bit pointer support for addressing the entire 64-bit OpenVMS
Alpha and OpenVMS I64 address space layout including P0, P1, and P2
address spaces and S0/S1, S2, and page table address spaces.
- 32-bit pointer compatibility for addressing P0, P1, and S0/S1
- 64-bit system services that support P0, P1, and P2 space addresses.
- 32-bit sign-extension checking for all arguments passed to 32-bit,
pointer- only system services.
- C and MACRO-32 macros for handling 64-bit addresses.
11.7 HP C RTL Support for 64-Bit Addressing
OpenVMS Alpha and I64 64-bit virtual addressing support makes the
64-bit virtual address space defined by the Alpha and Itanium
architectures available to both the OpenVMS operating system and its
users. It also allows per-process virtual addressing for accessing
dynamically mapped data beyond traditional 32-bit limits.
The HP C Run-Time Library on OpenVMS Alpha and OpenVMS I64 systems
includes the following features in support of 64-bit pointers:
- Guaranteed binary and source compatibility of existing programs
- No impact on applications that are not modified to exploit 64-bit
- Enhanced memory allocation routines that allocate 64-bit memory
- Widened function parameters to accommodate 64-bit pointers
- Dual implementations of functions that need to know the pointer
size used by the caller
- Information available to the HP C compiler to seamlessly call the
- Ability to explicitly call either the 32-bit or 64-bit form of
functions for applications that mix pointer sizes
- A single shareable image for use by 32-bit and 64-bit applications
See the HP C Run-Time Library Reference Manual for OpenVMS Systems for a description of the 64-bit addressing
support provided by the HP C Run-Time Library.
Memory Management Services and Routines on OpenVMS Alpha and OpenVMS I64
This chapter describes the use of memory management system services and
run-time routines on Alpha and I64 systems. Although the operating
system's memory management concepts are much the same on VAX, Alpha,
and I64 systems, details of the memory management system are different.
These details may be critical to certain uses of the operating system's
memory management system services and routines on an Alpha and I64
This chapter contains the following sections:
Section 12.1 describes the page sizes of Alpha and I64 systems.
Section 12.2 describes the three levels of the operating system's
memory allocation routines.
Section 12.3 discusses how to use system services to add virtual
address space, adjust working sets, control process swapping, and
create and manage sections.
Section 12.4 describes large page-file sections.
12.1 Virtual Page Sizes
On Alpha systems, in order to facilitate memory protection and mapping,
the virtual address space is subdivided into segments of 8 KB, 16 KB,
32 KB, or 64 KB sizes called CPU-specific pages. On
VAX systems, the page sizes are 512 bytes. Intel Itanium processors
support a range of page sizes to assist operating systems to virtually
map system resources. All Intel Itanium processors support page sizes
of 4 KB, 8 KB, 16 KB, 64 KB, 256 KB, 1 MB, 4 MB, 16 MB, 64 MB, and 256
MB. For compatibility with OpenVMS Alpha systems, OpenVMS I64 uses the
8 KB page size by default. (Larger default page sizes may be used in
future versions of OpenVMS.)
Wherever possible, the Alpha and I64 system's versions of the system
services and run-time library routines that manipulate memory attempt
to preserve compatibility with the VAX system's services and routines.
The Alpha and I64 system's versions of the routines that accept page
count values as arguments still interpret these arguments in 512-byte
quantities, which are called pagelets to distinguish
them from CPU-specific page sizes. The routines convert pagelet values
into CPU-specific pages. The routines that return page count values
convert from CPU-specific pages to pagelets, so that return values
expected by applications are still measured in the same 512-byte units.
This difference in page size does not affect memory allocation using
higher-level routines, such as run-time library routines that
manipulate virtual memory zones or language-specific memory allocation
routines such as the malloc and free routines in C.
To determine system page size, you make a call to the SYS$GETSYI system
service, specifying the SYI$_PAGE_SIZE item code. See the description
of SYS$GETSYI and SYI$_PAGE_SIZE in the HP OpenVMS System Services Reference Manual for details.
12.2 Levels of Memory Allocation Routines
Sophisticated software systems must often create and manage complex
data structures. In these systems, the size and number of elements are
not always known in advance. You can tailor the memory allocation for
these elements by using dynamic memory allocation. By
managing the memory allocation, you can avoid allocating fixed tables
that may be too large or too small for your program. Managing memory
directly can improve program efficiency. By allowing you to allocate
specific amounts of memory, the operating system provides a hierarchy
of routines and services for memory management. Memory allocation and
deallocation routines allow you to allocate and free storage within the
virtual address space available to your process.
There are three levels of memory allocation routines:
- Memory management system services
The memory management system services comprise the lowest level of
memory allocation routines. 64-bit services include, but are not
limited to, the following:
- SYS$CREATE_BUFOBJ_64 (Creates a buffer object)
- SYS$CRMPSC_GDZRO_64 (Create and Map to Global Demand-Zero Section)
- SYS$CREATE_REGION_64 (Create Virtual Region)
- SYS$CRETVA_64 (Create Virtual Address Space)
- SYS$CRMPSC_FILE_64 (Create and Map Private Disk File Section)
- SYS$CRMPSC_GFILE_64 (Create and Map Global Disk File Section)
- SYS$CRMPSC_GPFILE_64 (Create and Map Global Page File Section)
- SYS$CRMPSC_GPFN_64 (Create and Map Global Page Frame Section)
- SYS$CRMPSC_PFN_64 (Create and Map Private Page Frame Section)
- SYS$DELETE_REGION_64 (Delete a Virtual Region)
- SYS$DELTVA_64 (Delete Virtual Address Space)
- SYS$DGBLSC (Delete Global Section)
- SYS$EXPREG_64 (Expand Virtual Address Space)
- SYS$LCKPAG_64 (Lock Pages in Memory)
- SYS$LKWSET_64 (Lock Pages in Working Set)
- SYS$MGBLSC_64 (Map to Global Section)
- SYS$MGBLSC_GPFN_64 (Map Global Page Frame Section)
- SYS$PURGE_WS (Purge Working Set)
- SYS$SETPRT_64 (Set Protection on Pages)
- SYS$ULKPAG_64 (Unlock Pages from Memory)
- SYS$ULWSET_64 (Unlock Pages from Working Set)
- SYS$UPDSEC_64(W) (Update Global Section File on Disk)
32-bit services include, but are not limited to, the following:
- SYS$EXPREG (Expand Region)
- SYS$CRETVA (Create Virtual Address Space)
- SYS$DELTVA (Delete Virtual Address Space)
- SYS$CRMPSC (Create and Map Section)
- SYS$MGBLSC (Map Global Section)
For most cases in which a system service is used for memory
allocation, the Expand Region (SYS$EXPREG or SYS$EXPREG_64) system
service is used to create pages of virtual memory.
services provide more control over allocation procedures than RTL
routines, you must manage the allocation precisely. System services
provide extensive control over address space allocation by allowing you
to do the following types of tasks:
- Add or delete virtual address space to the process's program region
(P0), control region (P1), 64-bit program region (P2), or user-created
- Add or delete virtual address space at a specific range of addresses
- Define memory resident demand-zero sections and map them in to the
virtual address space of a process.
- Increase or decrease the number of pages in a program's working set
- Lock or delete pages of a program's working set in memory
- Lock the entire program's working set in memory (by disabling
- Define disk files containing data or shareable images and map the
files into the virtual address space of a process
- RTL page management routines
The RTL routines exist for
creating, deleting, and accessing information about virtual address
space. You can either allocate a specified number of contiguous pages
or create a zone of virtual address space. A zone is a
logical unit of the memory pool or subheap that you can control as an
independent area. It can be any size required by your program. Refer to
Chapter 14 for more information about zones.
The RTL page
management routines LIB$GET_VM_PAGE, LIB$GET_VM_PAGE_64,
LIB$FREE_VM_PAGE, and LIB$FREE_VM_PAGE_64 provide a convenient
mechanism for allocating and freeing pages of memory.
These routines maintain a processwide pool of free pages. If
unallocated pages are not available when LIB$GET_VM_PAGE is called, it
calls SYS$EXPREG to create the required pages in the program region (P0
space). For LIB$GET_VM_PAGE_64, if there are not enough contiguous free
pagelets to satisfy an allocation request, additional pagelets are
created by calling the system service SYS$EXPREG_64.
- RTL heap management routines
The RTL heap management routines
LIB$GET_VM, LIB$GET_VM_64, LIB$FREE_VM, and LIB$FREE_VM_64 provide a
mechanism for allocating and freeing blocks of memory of arbitrary size.
The following are heap management routines based on the concept of
Modular application programs can call routines in any or all levels of
the hierarchy, depending on the kinds of services the application
program needs. You must observe the following basic rule when using
multiple levels of the hierarchy:
Memory that is allocated by an allocation routine at one level of the
hierarchy must be freed by calling a deallocation routine at the same
level of the hierarchy. For example, if you allocated a page of memory
by calling LIB$GET_VM_PAGE, you can free it only by calling
For information about using memory management RTLs, see Chapter 14.