RENT mode support

The RENT option supports constructed reentrancy for C programs with writable static and external variables. This makes Metal C programs with writable static and external variables to be reentrant so a program can be concurrently used by multiple users. The writable static area (WSA) can be managed by user provided routines. Using the RENT support, you can use Metal C as an alternative to assembler, to write programs to run in CICS® environment. For information about how the CICS API and the CICS XPI can be used in Metal C and for programming examples, see CICS programming interface examples. The default of the RENT option is NORENT.
Note: The Metal C RENT support is independent of and different from the NOMETAL RENT support. They should not be mixed.

Example

xlc -qMETAL -qRENT -S a.c            1 
as -mgoff a.s                        2 
export _LD_SYSLIB="//'CBC.SCCNOBJ'"  3 
ld a.o
Notes:
  1. Request Metal C RENT support.
  2. The HLASM GOFF option is required to assemble the compiler generated code for RENT.
  3. It is necessary to add CBC.SCCNOBJ dataset to the binder SYSLIB for the resolution of CCNZINIT and CCNZTERM.

Linkage convention

General Purpose Register 0 (GPR0) is used to pass the WSA address. The prolog code you supplied needs to preserve the content of GPR0 on exit of the prolog code. Programs compiled with RENT and NORENT can be mixed as long as the NORENT programs do not call RENT programs.
Note: Global variables compiled with RENT and NORENT cannot have the same name.

Assembler code interface

The runtime RENT support is accomplished by additional calls generated for the function "main" between the prolog/epilog code and the function code. The RENT environment initialization and termination routines are called to establish and terminate the dynamically allocated WSA storage with the static initialization data applied. For the AMODE 31 "main" function, CCNZINIT and CCNZTERM are the names of these routines. While for the AMODE 64 "main" function, CCNZQINI and CCNZQTRM are the function names. For the simplicity of further references, only the names of the 31-bit version are used. The actual WSA storage management is done by user supplied plug-in routines called from CCNZINIT and CCNZTERM. Two user modifiable Global Set Symbols, &CCN_WSA_INIT and &CCN_WSA_TERM, can be used in the user supplied prolog code to set the user supplied WSA initialization and termination function names. The AMODE of the user supplied routines has to be the same as the AMODE of function "main".
Note: CCNZINIT, CCNZTERM, CCNZWSAI and CCNZWSAT require the stack space to be supplied by function "main" prolog code. Both CCNZINIT and CCNZTERM require NAB to be established by function "main". Also, CCNZINIT and CCNZTERM assume stack space to be available for the WSA initialization and termination functions. This arrangement is to ensure that the stack space used by CCNZINIT and CCNZTERM as well as the WSA initialization and termination routines is consistent with the stack space used by function "main". Allocating 1K of extra stack space (in addition to the DSA size suggested by &CCN_DSASZ for "main") by function "main" should be sufficient for AMODE 31. For AMODE 64, the extra stack space is roughly doubled.
The following new Global Set Symbols are introduced for the RENT option.
  • &CCN_MAIN
  • &CCN_RENT
  • &CCN_WSA_INIT
  • &CCN_WSA_TERM
For detailed information about these new Global Set Symbols, see Compiler-generated global SET symbols.
You can provide your own WSA initialization and termination routines by setting these Global Set Symbols with the module names of your own routines. For example:
   GBLC &CCN_WSA_INIT
   GBLC &CCN_WSA_TERM
   &CCN_WSA_INIT SETC 'MYWSAI'
   &CCN_WSA_TERM SETC 'MYWSAT'
Your own WSA initialization and termination routines can be object modules, load modules, or program modules, and they need to be supplied to the binder's input.
The compiler generated code for "main" has the following kind of assembly statements in it:
  • For AMODE 31:
       DC V(&CCN_WSA_INIT) 
       DC V(&CCN_WSA_TERM)
  • For AMODE 64:
       DC VD(&CCN_WSA_INIT) 
       DC VD(&CCN_WSA_TERM)

WSA initialization routine

Given the size of the WSA for the whole application and the image of the WSA with initialization data applied, the WSA initialization routine you provided dynamically allocate the WSA storage for the application and copy the WSA image into it. The address of the allocated storage is returned which CCNZINIT saves it on the function main's stack to be propagated to the rest of the application. You are responsible for ensuring that the allocated storage is addressable to all parts of the application. This particularly means if there are AMODE 31 parts in the application, the WSA storage should not be allocated above the 2G bar if the AMODE 31 parts need to access it. Also, the WSA storage has to be allocated in the primary address space. WSA storage in data spaces is not supported.

The routine you provide is given an address of an area to store whatever extra information you want to keep and pass to the WSA termination routine you provided. The storage area size is the size of a pointer, that is, 4 bytes for AMODE 31, and 8 bytes for AMODE 64.

Function prototype:
    typedef void * (init_func_t) (void * wsa_image_addr, 
    unsigned long wsa_size, void * *user_info_addr, unsigned int alignment);
Input parameters:
  • wsa_image_addr - the address of the WSA image in the loaded program object
  • wsa_size - the total size of the application's WSA
  • user_info_addr - the address of the CCNZINIT provided save area for saving user information
  • alignment - the minimum required alignment of the allocated WSA storage. For example, "alignment=8" means double-word alignment.
Return value:
The address of the allocated and initialized WSA storage. The default is the IBM® supplied routine CCNZWSAI or CCNZQWSI, which allocates storage for both AMODE 31 and AMODE 64 with the following macro:
   STORAGE OBTAIN,LENGTH=(n),BNDRY=PAGE

WSA termination routine

This routine is called from CCNZTERM for the WSA termination and cleanup process. It is passed in the address of the WSA storage allocated by the WSA initialization routine. It is also given the same WSA size that was originally passed to the WSA initialization routine.

Function prototype:
    typedef void (term_func_t) (void * allocated_wsa_addr, 
    unsigned long wsa_size, void * user_info_addr);
Input parameters:
  • allocated_wsa_addr - the address of the allocated WSA storage
  • wsa_size - the total size of the application's WSA
  • user_info_addr - the saved user information
Return value:
The default is the IBM supplied routine CCNZWSAT or CCNZQWST, which frees the storage with the following macro:
   STORAGE RELEASE,LENGTH=(n),ADDR=(m)