 |
OpenVMS Programming Concepts Manual
12.4.7.4 Defining the Section Characteristics
The flags argument to the SYS$CRMPSC system service
defines the following section characteristics:
- Whether it is a private section or a global section. The default is
to create a private section.
- How the pages of the section are to be treated when they are copied
into physical memory or when a process refers to them. The pages in a
section can be either or both of the following:
- Read/write or read-only
- Created as demand-zero pages or as copy-on-reference pages,
depending on how the processes are going to use the section and whether
the file contains any data (see Section 12.4.7.12)
- Whether the section is to be mapped to a disk file or to specific
physical page frames (see Section 12.4.7.18).
Table 12-3 shows the flag bits that must be set for specific
characteristics on Alpha systems.
Table 12-3 Flag Bits to Set for Specific Section Characteristics on Alpha Systems
|
Section to Be Created |
Correct Flag Combinations |
Private |
Global |
PFN Private |
PFN Global |
SEC$M_GBL
|
0
|
1
|
0
|
1
|
SEC$M_CRF
|
Optional
|
Optional
|
0
|
0
|
SEC$M_DZRO
|
Optional
|
Optional
|
0
|
0
|
SEC$M_WRT
|
Optional
|
Optional
|
Optional
|
Optional
|
SEC$M_PERM
|
Not used
|
Optional
|
Not used
|
1
|
SEC$M_SYSGBL
|
Not used
|
Optional
|
Not used
|
Optional
|
SEC$M_PFNMAP
|
0
|
0
|
1
|
1
|
SEC$M_EXPREG
|
Optional
|
Optional
|
Optional
|
Optional
|
SEC$M_PAGFIL
|
0
|
Optional
|
0
|
0
|
When you specify section characteristics, the following restrictions
apply:
- Global sections cannot be both demand-zero and copy-on-reference.
- Demand-zero sections must be writable.
12.4.7.5 Defining Global Section Characteristics
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 12.4.7.6.
The flags argument specifies the following types of
global section:
- Group temporary (the default)
- Group permanent
- System temporary
- System permanent
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.
12.4.7.6 Global Section Name
The gsdnam argument specifies a descriptor that points
to a character string.
Translation of the gsdnam argument proceeds in the
following manner:
- The current name string is prefixed with GBL$ and the result is
subject to logical name translation.
- If the result is a logical name, step 1 is repeated until
translation does not succeed or until the number of translations
performed exceeds the number specified by the system parameter
LNM$C_MAXDEPTH.
- The GBL$ prefix is stripped from the current name string that could
not be translated. This current string is the global section name.
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:
- GBL$ is prefixed to GSDATA.
- GBL$GSDATA is translated to GSDATA_001. (Further translation is not
successful. When logical name translation fails, the string is passed
to the service.)
There are three exceptions to the logical name translation method
discussed in this section:
- If the name string starts with an underscore (_), the operating
system strips the underscore and considers the resultant string to be
the actual name (that is, further translation is not performed).
- If the name string is the result of a logical name translation,
then the name string is checked to see if it has the
terminal attribute. If the name string is marked with
the terminal attribute, the operating system considers
the resultant string to be the actual name (that is, further
translation is not performed).
- If the global section has a name in the format name_nnn,
the operating system first strips the underscore and the digits
(nnn), then translates the resultant name according to the
sequence discussed in this section, and finally reappends the
underscore and digits. The system uses this method in conjunction with
known images and shared files installed by the system manager.
12.4.7.7 Mapping Sections
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 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:
- If both addresses specified in the inadr argument
are the same and the SEC$M_EXPREG bit is set in the
flags argument, SYS$CRMPSC allocates the memory in
whichever program region the addresses fall but does not use the
specified location.
- If both addresses are different, SYS$CRMPSC maps the section into
memory using the boundaries specified.
On Alpha 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[1]; /* Assume page size = 8 KB */
maprange[0] = 0x14000; /* Address (hex) of page 10 */
maprange[1] = 0x27FFF; /* Address (hex) of page 19 */
|
On Alpha 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
or
inadr[0] = first byte in range
inadr[1] = 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 systems, the relpag argument specifies the
location in the section file at which you want mapping to begin.
On Alpha 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[1], retadr[1], flags;
/*
This range used merely to indicate P0 space since SEC$M_EXPREG
is specified
*/
inadr[0]= 0x200; /* Any program (P0) region address */
inadr[1]= 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 systems, the starting retadr address should
match inadr, plus relpag if
specified. The ending (higher) address will be limited by the lower of:
- The value of the pagcnt argument
- The actual remaining block count in the file starting with
specified starting vbn, or relpag
- The bound dictated by the inadr argument
After a section is mapped successfully, the image can refer to the
pages using one of the following:
- A base register or pointer and predefined symbolic offset names
- Labels defining offsets of an absolute program section or structure
The following example shows part of a program used to create and map a
process section on Alpha 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
|
Notes on Example
- The OPEN macro opens the section file defined in the file access
block SECFAB. (The FOP parameter to the $FAB macro must specify the UFO
option.)
- The SYS$CRMPSC system service uses the addresses specified at
MAPRANGE to specify an input range of addresses into which the section
will be mapped. The pagcnt argument requests that only
4 pagelets of the file be mapped.
- The flags argument requests that the pages in the
section have read/write access. The symbolic flag definitions for this
argument are defined in the $SECDEF macro. Note that the file access
field (FAC parameter) in the FAB also indicates that the file is to be
opened for writing.
- When SYS$CRMPSC completes, the addresses of the 4 pagelets that
were mapped are returned in the output address array at RETRANGE. The
address of the beginning of the section is placed in register 6, which
serves as a pointer to the section.
12.4.7.8 Mapping Global Sections
A process that creates a global section can map that global section.
Then other processes can map it by calling the Map Global Section
(SYS$MGBLSC) system service.
When a process maps a global section, it must specify the global
section name assigned to the section when it was created, whether it is
a group or system global section, and whether it desires read-only or
read/write access. The process may also specify the following:
- A version identification (ident argument),
indicating the version number of the global section (when multiple
versions exist) and whether more recent versions are acceptable to the
process.
- A relative pagelet number (relpag argument),
specifying the pagelet number, relative to the beginning of the
section, to begin mapping the section. In this way, processes can use
only portions of a section. Additionally, a process can map a piece of
a section into a particular address range and subsequently map a
different piece of the section into the same virtual address range.
On Alpha systems, you should specify the retadr
argument to determine the exact boundaries of the memory that was
mapped by the call. If your application specifies the
relpag argument, you must specify the
retadr argument. In this case, it is not an optional
argument.
Cooperating processes can both issue a SYS$CRMPSC system service to
create and map the same global section. The first process to call the
service actually creates the global section; subsequent attempts to
create and map the section result only in mapping the section for the
caller. The successful return status code SS$_CREATED indicates that
the section did not already exist when the SYS$CRMPSC system service
was called. If the section did exist, the status code SS$_NORMAL is
returned.
The example in Section 12.4.7.12 shows one process (ORION) creating a
global section and a second process (CYGNUS) mapping the section.
12.4.7.9 Global Page-File Sections
Global page-file sections are used to store temporary data in a global
section. A global page-file section is a section of virtual memory that
is not mapped to a file. The section can be deleted when processes have
finished with it. (Contrast this with demand-zero section file pages
where no initialization is necessary, but the pages are saved in a
file.) The system parameter GBLPAGFIL controls the total number of
global page-file pages in the system.
To create a global page-file section, you must set the flag bits
SEC$M_GBL and SEC$M_PAGFIL in the flags argument to
the Create and Map Section (SYS$CRMPSC) system service. The channel
(chan argument) must be 0.
You cannot specify the flag bit SEC$M_CRF with the flag bit
SEC$M_PAGFIL.
12.4.7.10 Mapping into a Defined Address Range (Alpha Only)
On Alpha systems, SYS$CRMPSC and SYS$MGBLSC interpret some of the
arguments differently than on VAX systems if you are mapping a section
into a defined area of virtual address space. The differences are as
follows:
- The addresses specified as values in the inadr
argument must be aligned on CPU-specific page boundaries. On VAX
systems, SYS$CRMPSC and the SYS$MGBLSC round these addresses to page
boundaries for you. On Alpha systems, SYS$CRMPSC does not round the
addresses you specify to page boundaries, because rounding to
CPU-specific page boundaries on Alpha system affects a much larger
portion of memory than it does on VAX systems, where page sizes are
much smaller. Therefore, on Alpha systems, you must explicitly state
where you want the virtual memory space mapped. If the addresses you
specify are not aligned on CPU-specific page boundaries, SYS$CRMPSC
returns an invalid arguments error (SS$_INVARG).
In particular, the
lower inadr address must be on a CPU-specific page
boundary, and the higher inadr address must be one
less than a CPU-specific page; that is, it indicates the
highest-addressed byte of the inadr range.
- The addresses returned in the retadr argument
reflect only the usable portion of the actual memory mapped by the
call, not the entire amount mapped. The usable amount is either the
value specified in the pagcnt argument (measured in
pagelets) or the size of the section file, whichever is smaller. The
actual amount mapped depends on how many CPU-specific pages are
required to map the section file. If the section file does not fill a
CPU-specific page, the remainder of the page is filled with zeros. The
excess space on this page should not be used by your application. The
end address specified in the retadr argument specifies
the upper limit available to your application. Also note that, when the
relpag argument is specified, the
retadr argument must be included. It is not
optional on Alpha systems.
12.4.7.11 Mapping from an Offset into a Section File (Alpha Only)
On Alpha systems, you can map a portion of a section file by specifying
the address at which to start the mapping as an offset from the
beginning of the section file. You specify this offset by supplying a
value to the relpag argument of SYS$CRMPSC. The value
of the relpag argument specifies the pagelet number
relative to the beginning of the file at which the mapping should begin.
To preserve compatibility, SYS$CRMPSC interprets the value of the
relpag argument in 512-byte units on both VAX systems
and Alpha systems. However, because the CPU-specific page size on the
Alpha system is larger than 512 bytes, the address specified by the
offset in the relpag argument probably does not fall
on a CPU-specific page boundary on an Alpha system. SYS$CRMPSC can map
virtual memory in CPU-specific page increments only. Therefore, on
Alpha systems, the mapping of the section file will start at the
beginning of the CPU-specific page that contains the offset address,
not at the address specified by the offset.
Note
Even though the routine starts mapping at the beginning of the
CPU-specific page that contains the address specified by the offset,
the start address returned in the retadr argument is
the address specified by the offset, not the address at which mapping
actually starts.
|
If you map from an offset into a section file, you must still provide
an inadr argument that abides by the requirements
presented in Section 12.4.7.10 when mapping into a defined address range.
12.4.7.12 Section Paging
The first time an image executing in a process refers to a page that
was created during the mapping of a disk file section, the page is
copied into physical memory. The address of the page in the virtual
address space of a process is mapped to the physical page. During the
execution of the image, normal paging can occur; however, pages in
sections are not written into the page file when they are paged out, as
is the normal case. Rather, if they have been modified, they are
written back into the section file on disk. The next time a page fault
occurs for the page, the page is brought back from the section file.
If the pages in a section were defined as demand-zero pages or
copy-on-reference pages when the section was created, the pages are
treated differently, as follows:
- If the call to SYS$CRMPSC requested that pages in the section be
treated as demand-zero pages, these pages are initialized to zeros when
they are created in physical memory. If the file is either a new file
being created as a section or a file being completely rewritten,
demand-zero pages provide a convenient way of initializing the pages.
The pages are paged back into the section file.
- When the section is deleted, all unreferenced pages are written
back to the file as zeros. This causes the file to be initialized, no
matter how few pages were modified.
See Section 12.4.7.14 for details
about deleting sections.
- If the call to SYS$CRMPSC requested that pages in the section be
copy-on-reference pages, each process that maps to the section receives
its own copy of the section, on a page-by-page basis from the file, as
it refers to them. These pages are never written back into the section
file but are paged to the paging file as needed.
In the case of global sections, more than one process can be mapped to
the same physical pages. If these pages need to be paged out or written
back to the disk file defined as the section, these operations are done
only when the pages are not in the working set of any process.
In the following example for Alpha systems, process ORION creates a
global section and process CYGNUS maps to that section:
/* Process ORION */
#include <rms.h>
#include <rmsdef.h>
#include <literal>(<string.h>)
#include <secdef.h>
#include <descrip.h>
struct FAB gblfab;
main() {
unsigned short chan;
unsigned int status, flags, efn=65;
char *fn = "SECTION.TST";
$DESCRIPTOR(name, "FLAG_CLUSTER"); /* Common event flag cluster name */
$DESCRIPTOR(gsdnam, "GLOBAL_SECTION"); /* Global section name */
(1)status = SYS$ASCEFC(efn, &name, 0);
if ((status & 1) != 1)
LIB$SIGNAL( status );
/* Initialize FAB fields */
gblfab = cc$rms_fab;
gblfab.fab$l_alq = 4;
gblfab.fab$b_fac = FAB$M_PUT;
gblfab.fab$l_fnm = fn;
gblfab.fab$l_fop = FAB$M_CIF || FAB$M_CBT;
.
.
.
/* Create a file if none exists */
(2)status = SYS$CREATE( &gblfab, 0, 0 );
if ((status & 1) != 1)
LIB$SIGNAL( status );
flags = SEC$M_GBL | SEC$M_WRT;
status = SYS$CRMPSC(0, 0, 0, flags, &gsdnam, ...);
if ((status & 1) != 1)
LIB$SIGNAL( status );
status = SYS$SETEF(efn);
if ((status & 1) != 1)
LIB$SIGNAL( status );
.
.
.
}
/* Process CYGNUS */
unsigned int status, efn=65;
$DESCRIPTOR(cluster,"FLAG_CLUSTER");
$DESCRIPTOR(section,"GLOBAL_SECTION");
.
.
.
(3)status = SYS$ASCEFC(efn, &cluster, 0);
if ((status & 1) != 1)
LIB$SIGNAL( status );
status = SYS$WAITFR(efn);
if ((status & 1) != 1)
LIB$SIGNAL( status );
status = SYS$MGBLSC(&inadr, &retadr, 0, flags, §ion, 0, 0);
if ((status & 1) != 1)
LIB$SIGNAL( status );
}
|
|