HP OpenVMS systems
Locking a range of pages in the working set is problematic on I64 because the linker generates additional code that must also be locked and determining the address of that linker code is nontrivial.
The solution, applicable for both Alpha and I64, is to use the LIB$LOCK_IMAGE and LIB$UNLOCK_IMAGE LIBRTL routines to lock the entire image in to the working set. You can specify an address of a byte within the image to be locked in the working set, or zero for the current image.
If your privileged program runs on Alpha and I64 and not on VAX, you can remove all the code that finds the code, data and linkage data and locks these areas in the working set. You can replace this code with calls to LIB$LOCK_IMAGE and LIB$UNLOCK_IMAGE. These routines are simpler to program correctly and make your code easier to understand and maintain.
LIB$LOCK_IMAGE and LIB$UNLOCK_IMAGE are preferable to SYS$LKWSET and
SYS$ULKWSET for locking code and related data in the working set. For
more information about locking images in the working set, refer to the
HP OpenVMS RTL Library (LIB$) Manual and to the descriptions of LIB$LOCK_IMAGE and
LIB$UNLOCK_IMAGE in this manual.
18.104.22.168 Specifying a Range of Addresses In OpenVMS Version 8.1
Programs that enter kernel mode and increase IPL to higher than 2 must lock program code and data in the working set. Locking code and data is necessary to avoid crashing the system with a PGFIPLHI bugcheck.
On VAX systems, typically only the code and data explicitly referenced by the program need to be locked. On Alpha, the code, data and linkage data referenced by the program need to be locked. On I64 systems, code, data, short data, and linker generated code need to be locked. To make porting easier and because the addresses of short data and linker generated data cannot be easily found within an image, changes were made to the SYS$LKWSET and SYS$LKWSET_64 system servics.
As of OpenVMS Alpha Version 8.1 and OpenVMS I64 Version 8.1, the SYS$LKWSET and SYS$LKWSET_64 system services test the first address passed in. If this address is within an image, these services attempt to lock the entire image in the working set. If a successful status code is returned, the program can increase IPL to higher than 2 without crashing the system with a PGFIPLHI bugcheck.
A counter is maintained within the internal OpenVMS image structures that counts the number of times the image has been successfully locked in the working set. The counter is incremented when locked and decremented when unlocked. When the counter becomes zero, the entire image is unlocked from the working set.
If the program's image is too large to be locked in the working set,
the status SS$_LKWSETFUL is returned. If you encounter this status, you
can increase the user's working set quota.
22.214.171.124 Specifying a Range of Addresses In OpenVMS Versions Prior to V8.1
For OpenVMS versions prior to OpenVMS Alpha Version 8.1, you can use the inadr argument to specify the range of addresses to be locked. SYS$LKWSET rounds the addresses to CPU-specific page boundaries, if necessary. The range of addresses of the pages actually locked are returned in the retadr argument.
However, because the Alpha system's instructions cannot contain full virtual addresses, the Alpha system's images must reference procedures and data indirectly through a pointer to a procedure descriptor. The procedure descriptor contains information about the procedure, including the actual code address. These pointers to procedure descriptors and data are collected into a program section called a linkage section. Therefore, it is not sufficient simply to lock a section of code into memory to improve performance. You must also lock the associated linkage section into the working set.
To lock the linkage section into memory, you must determine the start and end addresses that encompass the linkage section and pass these addresses as values in the inadr argument to a call to SYS$LKWSET. For more information about linking, see Migrating to an OpenVMS AXP System: Recompiling and Relinking Applications. Note that this manual has been archived but is available on the OpenVMS Documentation Web site at:
If you use the SYS$LKWSET or SYS$LKWSET_64 system service, use the
acmode argument to specify the access mode to be
associated with the pages you want locked.
12.3.8 Process Swapping
The operating system balances the needs of all the processes currently executing, providing each with the system resources it requires on an as-needed basis. The memory management routines balance the memory requirements of the process. Thus, the sum of the working sets for all processes currently in physical memory is called the balance set.
When a process whose working set is in memory becomes inactive---for example, to wait for an I/O request or to hibernate---the entire working set or part of it may be removed from memory to provide space for another process's working set to be brought in for execution. This removal from memory is called swapping.
The working set may be removed in two ways:
A privileged process may lock itself in the balance set. While pages can still be paged in and out of the working set, the process remains in memory even when it is inactive. To lock itself in the balance set, the process issues the Set Process Swap Mode (SYS$SETSWM) system service, as follows:
This call to SYS$SETSWM disables process swap mode. You can also disable swap mode by setting the appropriate bit in the STSFLG argument to the Create Process (SYS$CREPRC) system service; however, you need the PSWAPM privilege to alter process swap mode.
A process can also lock particular pages in memory with the Lock Pages in Memory (SYS$LCKPAG or SYS$LCKPAG_64) system service. These pages are forced into the process's working set if they are not already there. When pages are locked in memory with these services, the pages remain in memory even when the remainder of the process's working set is swapped out of the balance set. These remaining pages stay in memory until they are unlocked with SYS$ULKPAG or SYS$ULKPAG_64. The SYS$LCKPAG and SYS$LCKPAG_64 system services can be useful in special circumstances, for example, for routines that perform I/O operations to devices without using the operating system's I/O system.
On Alpha and I64 systems, if you are attempting to lock executable code with $LCKPAG, you should examine if locking these pages in the working set is more correct. See the descriptions of $LKWSET and LIB$LOCK_IMAGE.
You need the PSWAPM privilege to issue the SYS$LCKPAG, SYS$LCKPAG_64,
SYS$ULKPAG, or SYS$ULKPAG_64 system service.
A section is a disk file or a portion of a disk file containing data or instructions that can be brought into memory and made available to a process for manipulation and execution. A section can also be one or more consecutive page frames in physical memory or I/O space; such sections, which require you to specify page frame number (PFN) mapping, are discussed in Chapter 13, Section 126.96.36.199.
When modified pages in writable disk file sections are paged out of memory during image execution, they are written back into the section file rather than into the paging file, as is the normal case with files. (However, copy-on-reference sections are not written back into the section file.)
The use of disk file sections involves these two distinct operations:
The Create and Map Section (SYS$CRMPSC) system service creates and maps a private section or a global section. Because a private section is used only by a single process, creation and mapping are simultaneous operations. In the case of a global section, one process can create a permanent global section and not map to it; other processes can map to it. A process can also create and map a global section in one operation.
The following sections describe the creation, mapping, and use of disk
file sections. In each case, operations and requirements that are
common to both private sections and global sections are described
first, followed by additional notes and requirements for the use of
global sections. Section 188.8.131.52 discusses global page-file sections.
184.108.40.206 Creating Sections with 64-Bit System Services
The $CRMPSC system service allows a process to create a private or global section and to map a section of its address space to the private or global section. However, although this system service is powerful and flexible, it is complex. If you are using an Alpha or I64 system, the following routines provide an easier method of creating and mapping sections:
Mapped I/O space on an OpenVMS I64 system may require non-cached access. You must set the SEC$M_UNCACHED flag when a PFN-mapped section is created if this section must be treated as uncached memory. The following system services accept this flag:
In addition, the SYS$MGBLSC_GPFN_64 service accepts, but ignores the flag. The cached/uncached characteristic is stored as a section attribute, and the system uses this attribute when the section is mapped. On OpenVMS Alpha systems, all four services accept but ignore the SEC$M_UNCACHED flag. Note that the older services, SYS$CRMPSC and SYS$MGBLSC were not updated and do not accept the new flag.
See the Intel® Itanium® Architecture Software Developer's
Manual for additional information regarding virtual-addressing
220.127.116.11 Creating Sections with 32-Bit System Services
Before you can use a file as a section, you must open it using OpenVMS RMS. The following example shows the OpenVMS RMS file access block ($FAB) and $OPEN macros used to open the file and the channel specification to the SYS$CRMPSC system service necessary for reading an existing file:
SECFAB: $FAB FNM=<SECTION.TST>, ; File access block FOP=UFO RTV= -1 . . . $OPEN FAB=SECFAB $CRMPSC_S - CHAN=SECFAB+FAB$L_STV,...
The file options parameter (FOP) indicates that the file is to be opened for user I/O; this option is required so that OpenVMS RMS assigns the channel using the access mode of the caller. OpenVMS RMS returns the channel number on which the file is accessed; this channel number is specified as input to the SYS$CRMPSC system service (chan argument). The same channel number can be used for multiple create and map section operations.
The option RTV= -1 tells the file system to keep all of the pointers to be mapped in memory at all times. If this option is omitted, the SYS$CRMPSC service requests the file system to expand the pointer areas if necessary. Storage for these pointers is charged to the BYTLM quota, which means that opening a badly fragmented file can fail with an EXBYTLM failure status. Too many fragmented sections may cause the byte limit to be exceeded.
The file may be a new file that is to be created while it is in use as a section. In this case, use the $CREATE macro to open the file. If you are creating a new file, the file access block (FAB) for the file must specify an allocation quantity (ALQ parameter).
You can also use SYS$CREATE to open an existing file; if the file does not exist, it is created. The following example shows the required fields in the FAB for the conditional creation of a file:
GBLFAB: $FAB FNM=<GLOBAL.TST>, - ALQ=4, - FAC=PUT,- FOP=<UFO,CIF,CBT>, - SHR=<PUT,UPI> . . . $CREATE FAB=GBLFAB
When the $CREATE macro is invoked, it creates the file GLOBAL.TST if
the file does not currently exist. The CBT (contiguous best try) option
requests that, if possible, the file be contiguous. Although section
files are not required to be contiguous, better performance can result
if they are.
18.104.22.168.2 Defining the Section Extents
After the file is opened successfully, the SYS$CRMPSC system service can create a section from the entire file or from only certain portions of it. The following arguments to SYS$CRMPSC define the extents of the file that comprise the section:
When you specify section characteristics, the following restrictions apply:
If the section is a global section, you must assign a character string name (gsdnam argument) to it so that other processes can identify it when they map it. The format of this character string name is explained in Section 22.214.171.124.5.
Group global sections can be shared only by processes executing with the same group number. The name of a group global section is implicitly qualified by the group number of the process that created it. When other processes map it, their group numbers must match.
A temporary global section is automatically deleted when no processes are mapped to it, but a permanent global section remains in existence even when no processes are mapped to it. A permanent global section must be explicitly marked for deletion with the Delete Global Section (SYS$DGBLSC) system service.
You need the user privileges PRMGBL and SYSGBL to create permanent group global sections or system global sections (temporary or permanent), respectively.
A system global section is available to all processes in the system.
Optionally, a process creating a global section can specify a
protection mask (prot argument) to restrict all access
or a type of access (read, write, execute, delete) to other processes.
126.96.36.199.5 Global Section Name
Translation of the gsdnam argument proceeds in the following manner:
For example, assume that you have made the following logical name assignment:
$ DEFINE GBL$GSDATA GSDATA_001
Your program contains the following statements:
#include <descrip.h> . . . $DESCRIPTOR(gsdnam,"GSDATA"); . . . status = sys$crmpsc(&gsdnam, ...);
The following logical name translation takes place:
There are three exceptions to the logical name translation method discussed in this section:
When you call the SYS$CRMPSC system service to create or map a section, or both, you must provide the service with a range of virtual addresses (inadr argument) into which the section is to be mapped.
On Alpha and I64 systems, the inadr argument specifies the size and location of the section by its start and end addresses. SYS$CRMPSC interprets the inadr argument in the following ways:
On Alpha and I64 systems, if you know specifically which pages the section should be mapped into, you provide these addresses in a 2-longword array. For example, to map a private section of 10 pages into virtual pages 10 through 19 of the program region, specify the input address array as follows:
unsigned int maprange; /* Assume page size = 8 KB */ maprange = 0x14000; /* Address (hex) of page 10 */ maprange = 0x27FFF; /* Address (hex) of page 19 */
On Alpha and I64 systems, the inadr argument range must have a lower address on an even page boundary and a higher address exactly one less than a page boundary. You do this to avoid programming errors that might arise because of incorrect programming assumptions about page sizes. For example, the range can be expressed as the following on an 8 KB page system:
0 ----> 1FFF
2000 ----> 7FFF
inadr = first byte in range
inadr = last byte in range
If the range is not expressed in terms of page-inclusive boundaries, then an SS$_INVARG condition value is returned.
You do not need to know the explicit addresses to provide an input address range. If you want the section mapped into the first available virtual address range in the program region (P0) or control region (P1), you can specify the SEC$M_EXPREG flag bit in the flags argument. In this case, the addresses specified by the inadr argument control whether the service finds the first available space in the P0 or P1. The value specified or defaulted for the pagcnt argument determines the amount of space mapped.
On Alpha and I64 systems, the relpag argument specifies the location in the section file at which you want mapping to begin.
On Alpha and I64 systems, the SYS$CRMPSC and SYS$MGBLSC system services map a minimum of one CPU-specific page. If the section file does not fill a single page, the remainder of the page is filled with zeros after faulting the page into memory. The extra space on the page should not be used by your application because only the data that fits into the section file will be written back to the disk.
The following example shows part of a program used to map a section at the current end of the program region:
unsigned int status, inadr, retadr, flags; /* This range used merely to indicate P0 space since SEC$M_EXPREG is specified */ inadr= 0x200; /* Any program (P0) region address */ inadr= 0x200; /* Any P0 address (can be same) */ . . . /* Address range returned in retadr */ flags = SEC$M_EXPREG; status = sys$crmpsc(&inadr, &retadr, flags, ...);
The addresses specified do not have to be currently in the virtual address space of the process. The SYS$CRMPSC system service creates the required virtual address space during the mapping of the section. If you specify the retadr argument, the service returns the range of addresses actually mapped.
On Alpha and I64 systems, the starting retadr address should match inadr, plus relpag if specified. The ending (higher) address will be limited by the lower of:
After a section is mapped successfully, the image can refer to the pages using one of the following:
The following example shows part of a program used to create and map a process section on Alpha and I64 systems:
SECFAB: $FAB FNM=<SECTION.TST>, - FOP=UFO, - FAC=PUT, - SHR=<GET,PUT,UPI> ; MAPRANGE: .LONG ^X14000 ; First 8 KB page .LONG ^X27FFF ; Last page RETRANGE: .BLKL 1 ; First page mapped ENDRANGE: .BLKL 1 ; Last page mapped . . . $OPEN FAB=SECFAB ; Open section file BLBS R0,10$ BSBW ERROR 10$: $CRMPSC_S - INADR=MAPRANGE,- ; Input address array RETADR=RETRANGE,- ; Output array PAGCNT=#4,- ; Map four pagelets FLAGS=#SEC$M_WRT,- ; Read/write section CHAN=SECFAB+FAB$L_STV ; Channel number BLBS R0,20$ BSBW ERROR 20$: MOVL RETRANGE,R6 ; Point to start of section