HP OpenVMS Systems Documentation

Content starts here

OpenVMS Programming Concepts Manual


Previous Contents Index

11.7.4.4 Functions Restricted to 32-Bit Pointers

Some functions in the Compaq C RTL do not support 64-bit pointers. If you try to pass a 64-bit pointer to one of these functions, the compiler generates a %CC-W-MAYLOSEDATA warning. Applications compiled with /POINTER_SIZE=64 might need to be modified to avoid passing 64-bit pointers to these functions.

Table 11-5 shows the functions restricted to using 32-bit pointers. The Compaq C RTL offers no 64-bit support for these functions. You must ensure that only 32-bit pointers are used with these functions.

Table 11-5 Functions Restricted to 32-Bit Pointers
atexit getopt modf setstate
execve iconv recvmsg setvbuf
execvp initstate sendmsg  
frexp ioctl setbuf  

Table 11-6 shows functions that make callbacks to user-supplied functions as part of processing that function call. The callback procedures are not passed 64-bit pointers.

Table 11-6 Callbacks that Pass only 32-Bit Pointers
from_vms to_vms
ftw tputs

11.7.5 Reading Header Files

This section introduces the pointer-size manipulations used in the Compaq C RTL header files. Use the following examples to become more comfortable reading these header files and to help modify your own header files.


Examples

#1

:
#if INITIAL__POINTER_SIZE (1)
#   if (VMS__VER < 70000000) || !defined __ALPHA (2)
#      error " Pointer size usage not permitted before OpenVMS Alpha V7.0"
#   endif
#   pragma __pointer_size __save (3)
#   pragma __pointer_size 32 (4)
#endif
:
:
#if __INITIAL_POINTER__SIZE (5)
#   pragma __pointer_size 64
#endif
:
:
#if __INITIAL_POINTER_SIZE (6)
#   pragma __pointer_size __restore
#endif
:


      

All Compaq C compilers that support the /POINTER_SIZE qualifier predefine the macro __INITIAL_POINTER_SIZE . The Compaq C RTL header files take advantage of the ANSI rule that if a macro is not defined, it has an implicit value of 0.

The macro is defined as 32 or 64 when the /POINTER_SIZE qualifier is used. It is defined as 0 if the qualifier is not used. The statement shown as (1) can be read as "if the user has specified either /POINTER_SIZE=32 or /POINTER_SIZE=64 on the command line."

Compaq C Version 5.2 and higher is supported on many OpenVMS platforms. The lines shown as (2) generate an error message if the target of the compilation is one that does not support 64-bit pointers.

A header file cannot assume anything about the actual pointer-size context in effect at the time the header file is included. Furthermore, the Compaq C compiler offers only the __INITIAL_POINTER_SIZE macro and a mechanism to change the pointer size, but no way to determine the current pointer size.

All header files that have a dependency on pointer sizes are responsible for saving (3), initializing (4), altering (5), and restoring (6) the pointer-size context.

#2

:
#ifndef __CHAR_PTR32 (1)
#   define __CHAR_PTR32 1
    typedef char * __char_ptr32;
    typedef const char * __const_char_ptr32;
#endif
:
:
#if __INITIAL_POINTER__SIZE
#   pragma __pointer_size 64
#endif
:
:
#ifndef __CHAR_PTR64 (2)
#   define __CHAR_PTR64 1
    typedef char *__ char_ptr64;
    typedef const char * __const_char_ptr64;
#endif
:


      

Some function prototypes need to refer to a 32-bit pointer when in a 64-bit pointer-size context. Other function prototypes need to refer to a 64-bit pointer when in a 32-bit pointer-size context.

Compaq C binds the pointer size used in a typedef at the time the typedef is made. The typedef declaration of __char_ptr32 (1) is made in a 32-bit context. The typedef declaration of __char_ptr64 (2) is made in a 64-bit context.

#3

:
#if INITIAL__POINTER_SIZE
#   if (__VMS_VER < 70000000) || !defined __ALPHA
#      error " Pointer size usage not permitted before OpenVMS Alpha V7.0"
#   endif
#   pragma __pointer_size save
#   pragma __pointer_size 32
#endif
:
(1)
:
#if __INITIAL_POINTER_SIZE (2)
#   pragma __pointer_size 64
#endif
:
(3)
:
int abs (int __j); (4)
:
__char_ptr32 strerror (int __errnum); (5)
:


      

Before declaring function prototypes that support 64-bit pointers, the pointer context is changed (2) from 32-bit pointers to 64-bit pointers.

Functions restricted to 32-bit pointers are placed in the 32-bit pointer context section (1) of the header file. All other functions are placed in the 64-bit context section (3) of the header file.

Functions that have no pointer-size impact ((4) and (5)) are located in the 64-bit section. Functions that have no pointer-size impact, except for a 32-bit address return value (5), are also in the 64-bit section, and use the 32-bit specific typedef s previously discussed.

#4

:
#if __INITIAL_POINTER_SIZE
#   pragma __pointer_size 64
#endif
:
:
#if __INITIAL_POINTER_SIZE == 32 (1)
#   pragma __pointer_size 32
#endif
:
char *strcat (char *__s1, __const_char_ptr64 __s2); (2)
:
#if __INITIAL_POINTER_SIZE
#   pragma __pointer_size 32
    :
    char *_strcat32  (char *__s1, __const_char_ptr64 __s2); (3)
    :
#   pragma __pointer_size 64
    :
    char *_strcat64  (char *__s1, const char *__s2); (4)
    :
#endif
:


      

This example shows declarations of functions that have both a 32-bit and 64-bit implementation. These declarations are located in the 64-bit section of the header file.

The normal interface to the function (2) is declared using the pointer size specified on the /POINTER_SIZE qualifier. Because the header file is in 64-bit pointer context and because of the statements at (1), the declaration at (2) is made using the same pointer size context as the /POINTER_SIZE qualifier.

The 32-bit specific interface (3) and the 64-bit specific interface (4) are declared in 32-bit and 64-bit pointer-size context, respectively.


Chapter 12
Memory Management Services and Routines on OpenVMS Alpha

This chapter describes the use of memory management system services and run-time routines on Alpha systems. Although the operating system's memory management concepts are much the same on VAX systems and Alpha 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 system. This chapter highlights those differences by using the Alpha icon.

This chapter contains the following sections:

Section 12.1 describes the page sizes of Alpha systems.

Section 12.2 describes the layout of virtual address space.

Section 12.3 describes the three levels of the operating system's memory allocation routines.

Section 12.4 discusses how to use system services to add virtual address space, adjust working sets, control process swapping, and create and manage sections.

12.1 Virtual Page Sizes (Alpha Only)

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.

Wherever possible, the Alpha 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 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 OpenVMS System Services Reference Manual for details.

12.2 Virtual Address Space

The Alpha system defines the same virtual address space layout as the VAX system. The Alpha system virtual address space allows for growth of the P0 and P1 regions in the same directions as on VAX systems.

The initial size of a process's virtual address space depends on the size of the image being executed. The virtual address space of an executing program consists of the following three regions:

  • Process program region (P0)
    The process program region is also referred to as P0 space. P0 space contains the instructions and data for the current image.
    Your program can dynamically allocate storage in the process program region by calling run-time library (RTL) dynamic memory allocation routines or the operating system's system services.
  • Process control region (P1)
    The process control region is also referred to as P1 space. P1 space contains system control information and the user-mode process stack. The user mode stack expands as necessary toward the lower-addressed end of P1 space.
  • Common system region (S0)
    The common system region is also referred to as S0 space, or system space. S0 space contains the operating system. Your program cannot allocate or free memory within the common system region from the user access mode.

The operating system's memory management routines map and control the relationship between physical memory and the virtual address space of a process. These activities are, for the most part, transparent to you and your programs. In some cases, however, you can make a program more efficient by explicitly controlling its virtual memory usage.

The maximum size to which a process can increase its address space is controlled by the system parameter VIRTUALPAGECNT.

Using memory management system services, a process can add a specified number of pages to the end of either the program region or the control region. Adding pages to the program region provides the process with additional space for image execution, for example, for the dynamic creation of tables or data areas. Adding pages to the control region increases the size of the user stack. As new pages are referenced, the stack is automatically expanded (see Figure 12-1). (By using the STACK= option in a linker options file, you can also expand the user stack when you link the image.)

Figure 12-1 illustrates the layout of a process's virtual memory. The initial size of a process's virtual address space depends on the size of the image being executed.

Figure 12-1 Layout of Alpha Process Virtual Address Space


12.3 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:

  1. Memory management system services
    The memory management system services comprise the lowest level of memory allocation routines. These 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)
    SYS$DGBLSC (Delete Global Section)

    For most cases in which a system service is used for memory allocation, the Expand Region (SYS$EXPREG) system service is used to create pages of virtual memory.
    Because system 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) or control region (P1)
    • Add or delete virtual address space at a specific range of addresses
    • 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 process swapping)
    • Define disk files containing data or shareable images and map the files into the virtual address space of a process
  2. 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 and LIB$FREE_VM_PAGE 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).
  3. RTL heap management routines
    The RTL heap management routines LIB$GET_VM and LIB$FREE_VM provide a mechanism for allocating and freeing blocks of memory of arbitrary size.
    The following are heap management routines based on the concept of zones:
    LIB$CREATE_VM_ZONE
    LIB$CREATE_USER_VM_ZONE
    LIB$DELETE_VM_ZONE
    LIB$FIND_VM_ZONE
    LIB$RESET_VM_ZONE
    LIB$SHOW_VM_ZONE
    LIB$VERIFY_VM_ZONE

    If an unallocated block is not available to satisfy a call to LIB$GET_VM, LIB$GET_VM calls LIB$GET_VM_PAGE to allocate additional pages.

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 LIB$FREE_VM_PAGE.

Figure 12-2 shows the three levels of memory allocation routines.

Figure 12-2 Hierarchy of Alpha Memory Management Routines


For information about using memory management RTLs, see Chapter 14.

12.4 Using System Services for Memory Allocation

This section describes how to use system services to perform the following tasks:

  • Increase and decrease virtual address space
  • Input and return address arrays
  • Control page ownership and protection
  • Control working set paging
  • Control process swapping

12.4.1 Increasing and Decreasing Virtual Address Space

The system services allow you to add address space anywhere within the process's program region (P0) or control region (P1). To add address space at the end of P0 or P1, use the Expand Program/Control Region (SYS$EXPREG) system service. SYS$EXPREG optionally returns the range of virtual addresses for the new pages. To add address space in other portions of P0 or P1, use SYS$CRETVA.

The format for SYS$EXPREG is as follows:


SYS$EXPREG (pagcnt ,[retadr] ,[acmode] ,[region])

Specifying the Number of Pages

On Alpha systems, use the pagcnt argument to specify the number of pagelets to add to the end of the region. The Alpha system rounds the specified pagelet value to the next integral number of Alpha pages for the system where it is executing. To check the exact boundaries of the memory allocated by the system, specify the optional retadr argument. The retadr argument contains the start address and the end address of the memory allocated by the system service.

Specifying the Access Mode

Use the acmode argument to specify the access to be assigned to the newly created pages.

Specifying the Region

Use the region argument to specify whether to add the pages to the end of the P0 or P1 region.

To deallocate pages allocated with SYS$EXPREG and SYS$CRETVA, use SYS$DELTVA.

For Alpha systems, the following example illustrates the addition of 4 pagelets to the program region of a process by writing a call to the SYS$EXPREG system service.



#include <stdio.h>
#include <ssdef.h>


main() {
    unsigned int status, retadr[2],pagcnt=4, region=0;

/* Add 4 pages to P0 space */
    status = SYS$EXPREG( pagcnt, &retadr, 0, region);
    if (( status & 1) != 1)
        LIB$SIGNAL( status );
    else
        printf("Starting address: %d Ending address: %d\n",
               retadr[0],retadr[1];
}

The value 0 is passed in the region argument to specify that the pages are to be added to the program region. To add the same number of pages to the control region, you would specify REGION=1.

Note that the region argument to the SYS$EXPREG service is optional; if it is not specified, the pages are added to or deleted from the program region by default.

On Alpha systems, the SYS$EXPREG service can add pagelets only in the direction of the growth of a particular region. When you need to add pages to the middle of these regions, you can use the Create Virtual Address Space (SYS$CRETVA) system service. Likewise, when you need to delete pages created by either SYS$EXPREG or SYS$CRETVA, you can use the Delete Virtual Address Space (SYS$DELTVA) system service. For example, if you have used the SYS$EXPREG service twice to add pages to the program region and want to delete the first range of pages but not the second, you could use the SYS$DELTVA system service, as shown in the following example:


#include <stdio.h>
#include <ssdef.h>

struct {
    unsigned int lower, upper;
}retadr1, retadr2, retadr3;

main() {
    unsigned int status, pagcnt=4, region=0;

/* Add 4 pages to P0 space */
    status = SYS$EXPREG( pagcnt, &retadr1, 0, region);
    if (( status & 1) != 1)
        LIB$SIGNAL( status );
    else
        printf("Starting address: %d ending address: %d\n",
               retadr1.lower,retadr1.upper);

/* Add 3 more pages to P0 space */

    pagcnt = 3;
    status = SYS$EXPREG( pagcnt, &retadr2, 0, region);
    if (( status & 1) != 1)
        LIB$SIGNAL( status );
    else
        printf("Starting address: %d ending address: %d\n",
               retadr2.lower,retadr2.upper);

/* Delete original allocation */
    status = SYS$DELTVA( &retadr1, &retadr3, 0 );
    if (( status & 1) != 1)
        LIB$SIGNAL( status );
    else
        printf("Starting address: %d ending address: %d\n",
               retadr1.lower,retadr1.upper);

}

In this example, the first call to SYS$EXPREG rounds up the requested pagelet count to an integral number of CPU-specific pages and adds that number of pages to the program region; the virtual addresses of the created pages are returned in the 2-longword array at retadr1. The second request converts the pagelet count to pages, adds them to the program region, and returns the addresses at retadr2. The call to SYS$DELTVA deletes the area created by the first SYS$EXPREG call.

Caution

Be aware that using SYS$CRETVA presents some risk because it can delete pages that already exist if those pages are not owned by a more privileged access mode. Further, if those pages are deleted, notification is not sent. Therefore, unless you have complete control over an entire system, use SYS$EXPREG or the RTL routines to allocate address space.

Section 12.4.3 mentions some other possible risks in using SYS$CRETVA for allocating memory.


Previous Next Contents Index