[Digital logo]
[HR]

Migrating an Application from OpenVMS VAX to OpenVMS Alpha


Previous | Contents

Your application may not need to be modified. However, Digital suggests that you obtain the exact boundaries of the memory allocated by the system, because the amount of memory returned by the $EXPREG system service may vary among implementations of the Alpha architecture. To do this, specify the optional retadr argument to the $EXPREG system service, if your application does not already include it. The retadr argument contains the start-address and the end-address of the memory allocated by the system service.

For example, the program in Example 5-1 calls the $EXPREG system service to request 10 additional pages of memory. If you run this program on a VAX system, the $EXPREG system service allocates 5120 bytes of additional memory. If you run this program on an Alpha system, the $EXPREG system service allocates at least 8192 bytes and possibly more, depending on the page size of the particular implementation of the Alpha architecture.

Example 5-1 Allocating Memory by Expanding Your Virtual Address Space


#include  <ssdef.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
 
#define  PAGE_COUNT 10  (1)
#define  P0_SPACE   0 
#define  P1_SPACE   1 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
     int    status = 0; 
     long   bytes_allocated, addr_returned[2]; 
 
(2)   status = SYS$EXPREG( PAGE_COUNT, &addr_returned, 0, P0_SPACE); 
 
     bytes_allocated = addr_returned[1] - addr_returned[0]; 
 
     if( status == SS$_NORMAL) 
        printf("bytes allocated = %d\n", bytes_allocated ); 
     else 
        return (status); 
         
} 

The items in the following list correspond to the numbered items in Example 5-1:

  1. The example defines a symbol, PAGE_COUNT, to stand for the number of pages requested.
  2. The example requests 10 additional pages to be added at the end of the P0 region of its virtual address space.

5.2.2 Allocating Memory in Existing Virtual Address Space

If your application reallocates memory that is already in its virtual address space by using the $CRETVA system service, you may need to modify the values of the following arguments to $CRETVA:

Recommendations

To determine whether your application needs to be modified, Digital suggests doing the following:

Example 5-2 shows how memory allocated to a buffer can be reallocated by using the $CRETVA system service.

Example 5-2 Allocating Memory in Existing Address Space


#include  <ssdef.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
 
char _align(page) buffer[1024]; 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
 
     int      status = 0; 
     long     inadr[2]; 
     long     retadr[2]; 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[1023]; 
 
     printf("inadr[0]=%u,inadr[1]=%u\n",inadr[0],inadr[1]); 
 
     status = SYS$CRETVA(inadr, &retadr, 0); 
 
     if( status & STS$M_SUCCESS ) 
     { 
        printf("success\n"); 
        printf("retadr[0]=%u,retadr[1]=%u\n",retadr[0],retadr[1]); 
     } 
     else 
     { 
        printf("failure\n"); 
        exit(status); 
     } 
} 

5.2.3 Deleting Virtual Memory

Calls to the $DELTVA system service to free memory allocated by the $EXPREG and $CRETVA system services should require no modification if your application uses the address range returned in the retadr argument (returned by the routine used to allocate the memory) as the inadr argument to the $DELTVA system service. Because the actual amount of the allocation will vary with the implementation, your application should not make any assumptions regarding the extent of the allocation.

5.3 Examining Memory Mapping Routines

To determine if the memory mapping performed by your application requires modification, check to see where in virtual memory your application performs the mapping. The memory mapping system services ($CRMPSC and $MGBLSC) allow you to map memory in the following ways:

How your application maps a section is determined primarily by the following arguments to the $CRMPSC and $MGBLSC system services:

The $CRMPSC and $MGBLSC system services map a miminum of one CPU-specific page. If the section file does not fill a single page, the remainder of the page is filled with zeros. 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.

5.3.1 Mapping into Expanded Virtual Address Space

If your application maps a section file into an expanded area of your application's virtual address space, you may not need to modify the source code. Because the mapping occurs in expanded virtual address space, there is no danger of overmapping existing data, even if the amount of memory allocated is larger on an Alpha system than on a VAX system. Thus, the values you specify as arguments to the $CRMPSC system service on a VAX system should still work on an Alpha system.

Recommendation

While applications that map sections into expanded areas of virtual memory may work correctly without modification, Digital suggests that you specify the retadr argument, if not already specified by your application, to determine the exact boundaries of the memory that was mapped by the call.


Note

If your application specifies the relpag argument, you must specify the retadr argument; it is not an optional argument. For more information about using the relpag argument, see Section 5.3.4.

Example 5-3 shows a call to the $CRMPSC system service that maps a section file into expanded address space. The example maps a section file named MAPTEST.DAT that was created using the DCL CREATE command, as follows:

$  CREATE maptest.dat 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
[Ctrl/Z]

Example 5-3 Mapping a Section into Expanded Virtual Address Space


#include  <ssdef.h> 
#include  <string.h> 
#include  <stdlib.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
#include  <rms.h> 
#include  <secdef.h> 
 
struct FAB fab; 
 
char _align(page) buffer[1024]; 
char *filename = "maptest.dat"; 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
 
     int    status = 0; 
     long   flags = SEC$M_EXPREG; 
     long   inadr[2]; 
     long   retadr[2]; 
     int    fileChannel; 
 
/********  create disk file to be mapped *************/ 
 
     fab = cc$rms_fab; 
     fab.fab$l_fna = filename; 
     fab.fab$b_fns = strlen( filename ); 
     fab.fab$l_fop = FAB$M_CIF | FAB$M_UFO;  /* must be UFO */ 
 
     status = sys$create( &fab ); 
 
     if( status & STS$M_SUCCESS ) 
        printf("%s opened\n",filename); 
     else 
     { 
        exit( status ); 
     } 
 
     fileChannel = fab.fab$l_stv; 
 
/**********  create and map the section  ****************/ 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[0]; 
 
     status = SYS$CRMPSC( inadr, /* inadr=address target for map */ 
                        &retadr, /* retadr= what was actually mapped */ 
                              0, /* acmode  */ 
                          flags, /* flags, with SEC$M_EXPREG bit set */ 
                              0, /* gsdnam, only for global sections */ 
                              0, /* ident, only for global sections */ 
                              0, /* relpag, only for global sections */ 
                    fileChannel, /* returned by SYS$CREATE */ 
                              0, /* pagcnt = size of sect. file used */ 
                              0, /* vbn = first block of file used */ 
                              0, /* prot = default okay */ 
                              0); /* page fault cluster size */ 
 
     if( status & STS$M_SUCCESS ) 
     { 
          printf("section mapped\n"); 
          printf("retadr[0]=%u,retadr[1]=%u\n",retadr[0],retadr[1]); 
     } 
     else 
     { 
          printf("map failed\n"); 
          exit( status ); 
     } 
 
} 

5.3.2 Mapping a Single Page to a Specific Location

If your application maps a section file into a single page of memory, you will need to modify your source code because this mode of operation is not supported on Alpha systems. Because the page size on Alpha systems differs from that on VAX systems and varies with different implementations of the Alpha architecture, you must specify the exact boundaries of the memory into which you intend to map a section file. The $CRMPSC system service returns an invalid arguments error (SS$_INVARG) for this usage.

To see if your application uses this mode, check the start- and end-addresses specified in the inadr argument. If both addresses are the same and the SEC$M_EXPREG bit in the flags argument is not set, your application is using this mode.

Recommendations

Digital suggests the following guidelines when modifying calls to the $CRMPSC system service in this mode:

5.3.3 Mapping into a Defined Address Range

If your application maps a section into a defined area of its virtual address space, you may need to modify your source code because, on Alpha systems, the $CRMPSC and $MGBLSC system services interpret some of the arguments differently than on VAX systems. The differences are as follows:

Recommendations

Digital suggests that you change your application so that it maps data into expanded virtual address space, if possible. If you cannot change the way your application maps data, Digital recommends the following guidelines:

For example, the VAX program in Example 5-4 maps the section file created in Section 5.3.1 into its existing virtual address space. The application defines a buffer, named buffer, that is 512 bytes in size, reflecting the VAX page size. The program defines the exact bounds of the section by passing the address of the first byte of the buffer as the start-address and the address of the last byte of the buffer as the end-address in the inadr argument.

Example 5-4 Mapping a Section into a Defined Area of Virtual Address Space


#include <ssdef.h> 
#include <stdio.h> 
#include <stsdef.h> 
#include <descrip.h> 
#include <dvidef.h> 
#include <rms.h> 
#include <secdef.h> 
 
struct FAB fab; 
 
char *filename = "maptest.dat"; 
 
char _align(page) buffer[512]; 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
 
     int    status = 0; 
     long   flags = 0; 
     long   inadr[2]; 
     long   retadr[2]; 
     int    fileChannel; 
 
/********  create disk file to be mapped *************/ 
 
     fab = cc$rms_fab; 
     fab.fab$l_fna = filename; 
     fab.fab$b_fns = strlen( filename ); 
     fab.fab$l_fop = FAB$M_CIF | FAB$M_UFO;  /* must be UFO */ 
 
     status = sys$create( &fab ); 
 
     if( status & STS$M_SUCCESS ) 
        printf("Opened mapfile %s\n",filename); 
     else 
     { 
        printf("Cannot open mapfile %s\n",filename); 
        exit( status ); 
     } 
 
     fileChannel = fab.fab$l_stv; 
 
/**********  create and map the section  ****************/ 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[511]; 
 
     printf("inadr[0]=%u,inadr[1]=%u\n",inadr[0],inadr[1]); 
 
     status = SYS$CRMPSC(inadr, /* inadr=address target for map */ 
                         &retadr, /* retadr= what was actually mapped */ 
                               0, /* acmode  */ 
                               0, /* flags */ 
                               0, /* gsdnam, only for global sections */ 
                               0, /* ident, only for global sections */ 
                               0, /* relpag, only for global sections */ 
                     fileChannel, /* returned by SYS$CREATE */ 
                               0, /* pagcnt = size of sect. file used */ 
                               0, /* vbn = first block of file used */ 
                               0, /* prot = default okay */ 
                               0 ); /* page fault cluster size */ 
 
     if( status & STS$M_SUCCESS ) 
     { 
           printf("Map succeeded\n"); 
           printf("retadr[0]=%u,retadr[1]=%u\n",retadr[0],retadr[1]); 
     } 
     else 
     { 
           printf("Map failed\n"); 
           exit( status ); 
     } 
 
} 

To get the program in Example 5-4 to run correctly on an Alpha system, you must make the following modifications:

One way to accomplish these goals is to isolate the program section that contains the section data in its own image section by using the SOLITARY program section attribute.

In the example, the section, named buffer, appears in the program section named buffer. (Program section creation is different in various programming languages on each platform. Check compiler documentation to ensure that the section is placed in its own program section.), The following link operation illustrates how to set the solitary attribute of this program section:

$  LINK MAPTEST, SYS$INPUT/OPT 
PSECT_ATTR=BUFFER,SOLITARY 
[Ctrl/Z]

To specify an end-address for the section buffer that is aligned with the end of a CPU-specific page boundary, obtain the CPU-specific page size at run time, subtract 1 from the returned value, and use it to take the address of the last element of the array. Pass this value as the second longword in the inadr argument. (To find out how to obtain the page size at run time, see Section 5.4.) Note that you do not need to change the allocation of the buffer into which the section is mapped.

To ensure that your application will run on an Alpha system with any page size, specify the /BPAGE=16 qualifier to force the linker to align image sections on 64KB boundaries. Note that the total amount of memory mapped may be much larger than the total amount of usable memory. The amount of usable memory is determined by the value of the page count argument (pagcnt) or the size of the section file, whichever is smaller. To avoid using memory that is not within the bounds of the section, use the values returned in the retadr argument.

Example 5-5 shows the source changes required for Example 5-4 to get it to run on an Alpha system. Example 5-5 Source Code Changes Required to Run Example 5-4 on an Alpha System


#include  <ssdef.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <string.h> 
#include  <stdlib.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
#include  <rms.h> 
#include  <secdef.h> 
#include  <syidef.h> (1)
 
char buffer[512];  (2)
char *filename = "maptest.dat"; 
struct FAB fab; 
 
long  cpu_pagesize; (3)
 
struct itm {                      /* item list */ 
    short int     buflen;  /* length of buffer in bytes */ 
    short int  item_code;  /* symbolic item code */ 
    long          bufadr;  /* address of return value buffer */ 
    long       retlenadr;  /* address of return value buffer length */ 
  } itmlst[2]; (4)
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
     int    i; 
     int    status = 0; 
     long   flags = SEC$M_EXPREG; 
     long   inadr[2]; 
     long   retadr[2]; 
     int    fileChannel; 
     char  *mapped_section; 
 
/********  create disk file to be mapped *************/ 
 
     fab = cc$rms_fab; 
     fab.fab$l_fna = filename; 
     fab.fab$b_fns = strlen( filename ); 
     fab.fab$l_fop = FAB$M_CIF | FAB$M_UFO;  /* must be UFO */ 
 
     status = sys$create( &fab ); 
 
     if( status & STS$M_SUCCESS ) 
        printf("%s opened\n",filename); 
     else 
     { 
        exit( status ); 
     } 
 
     fileChannel = fab.fab$l_stv; 
 
/**********  obtain the page size at run time  ****************/ 
 
 
     itmlst[0].buflen =  4; 
     itmlst[0].item_code = SYI$_PAGE_SIZE;    
     itmlst[0].bufadr =  &cpu_pagesize;       
     itmlst[0].retlenadr = &cpu_pagesize_len; 
     itmlst[1].buflen = 0; 
     itmlst[1].item_code = 0;  
 
(5)   status = sys$getsyiw( 0, 0, 0, &itmlst, 0, 0, 0 ); 
 
     if( status & STS$M_SUCCESS ) 
     { 
          printf("getsyi succeeds, page size = %d\n",cpu_pagesize); 
     } 
     else 
     { 
          printf("getsyi fails\n"); 
          exit( status ); 
     } 
 
/**********  create and map the section  ****************/ 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[cpu_pagesize - 1]; (6) 
 
     printf("address of buffer = %u\n", inadr[0] ); 
 
     status = SYS$CRMPSC(&inadr, /* inadr=address target for map */ 
                        &retadr, /* retadr= what was actually mapped */ 
                              0, /* acmode  */ 
                              0, /* no flags to set  */ 
                              0, /* gsdnam, only for global sections */ 
                              0, /* ident, only for global sections */ 
                              0, /* relpag, only for global sections */ 
                    fileChannel, /* returned by SYS$CREATE */ 
                              0, /* pagcnt = size of sect. file used */ 
                              0, /* vbn = first block of file used */ 
                              0, /* prot = default okay */ 
                              0); /* page fault cluster size */ 
 
     if( status & STS$M_SUCCESS ) 
     { 
          printf("section mapped\n"); 
          printf("start address returned =%u\n",retadr[0]); 
     } 
     else 
     { 
          printf("map failed\n"); 
          exit( status ); 
     } 
} 

The items in the following list correspond to the numbered items in Example 5-5:

  1. The header file SYIDEF.H contains definitions of OpenVMS item codes for the $GETSYI system service.
  2. The buffer is defined without using the _align(page) storage descriptor. Because the page size cannot be determined until run time on OpenVMS Alpha systems, the DEC C for OpenVMS Alpha compiler aligns the data on the largest Alpha page size (64 KB) when _align(page) is specified.
  3. This structure defines the item list used to obtain the page size at run time.
  4. This variable will hold the page-size value returned.
  5. This call to the $GETSYI system service obtains the page size at run time.
  6. The end-address of the buffer is specified by subtracting 1 from the page-size value returned.

5.3.4 Mapping from an Offset into a Section File

Your application may 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 the $CRMPSC system service. The value of the relpag argument specifies the page number relative to the beginning of the file at which the mapping should begin.


Previous | Next | Contents | [Home] | [Comments] | [Ordering info] | [Help]

[HR]

  6459P006.HTM
  OSSG Documentation
  22-NOV-1996 13:07:13.28

Copyright © Digital Equipment Corporation 1996. All Rights Reserved.

Legal