__cinit() - Initialize a Metal C environment

Format

#include <metal.h>
__csysenv_t __cinit(struct __csysenv_s * csysenv);

General description

The __cinit() function establishes a Metal C environment based on the characteristics in the input csysenv structure. This environment is used when calling Metal C functions that require an environment, such as those related to storage management (malloc(), free(), and so on). Storage for the environment structures is obtained by using the attributes specified in the input csysenv structure.

Use of this function requires the long long data type. See z/OS XL C/C++ Language Reference for information about how to make long long data type available

The environment token created by __cinit() can be used from both AMODE 31 and AMODE 64 programs. Calls to __malloc31() always affect the below-the-bar heap. Calls made while in AMODE 31 to all other functions that obtain storage affect the below-the-bar heap; calls made while in AMODE 64 affect the above-the-bar heap.
Table 1. csysenv argument in __cinit()
Argument Description
csysenv A structure describing the characteristics of the environment to be created.
The details on the csysenv (__csysenv_s) structure is shown as follows:
struct __csysenv_s {                                                  
 int       __cseversion;      /* Control block version number       */
                              /* Must be set to __CSE_VERSION_1     */
                                                                      
 int       __csesubpool;      /* for 31 bit storage                 */
 __ptr31(void, __csetcbowner) /* owning TCB for resources           */
                              /* default: TCB mode - caller tcb,    */
                              /*   SRB. XMEM - CMRO TCB             */
 int       __csereserved;     /* Reserved field                     */
 char      __csettknowner[16]; /* TCB token of owning TCB for       */
                              /* above the bar storage              */
                              /* default: caller tcbtoken           */
                              /*   SRB mode: tcbtoken must be       */
                              /*             specified              */
                                                                      
 unsigned int                                                         
           __cseheap31initsize; /* Minimum size, in bytes, to obtain  
                               for the initial AMODE 31 heap storage. 
                               If 0, defaults to 32768 bytes        */
 unsigned int                                                         
           __cseheap31incrsize; /* Minimum size, in bytes, to obtain  
                               when expanding the AMODE 31 heap.      
                               If 0, defaults to 32768 bytes        */
                                                                      
#ifdef __LL                                                           
 unsigned long long                                                   
           __cseheap64initsize; /* Minimum size, in MB, to obtain     
                               for the initial AMODE 64 heap storage. 
                               If 0, defaults to 1 MB               */
 unsigned long long                                                   
           __cseheap64incrsize; /* Minimum size, in MB, to obtain     
                               When expanding the AMODE 64 heap.      
                               If 0, defaults to 1MB                */
 unsigned long long                                                   
           __cseheap64usertoken; /* usertoken for use with ?iarv64    
                               to obtain above the bar storage      */
#else                                                                 
 unsigned int                                                         
           __cseheap64initsize_hh;                                    
 unsigned int                                                         
           __cseheap64initsize; /* Minimum size, in MB, to obtain     
                               for the initial AMODE 64 heap storage. 
                               If 0, defaults to 1 MB               */
 unsigned int                                                         
           __cseheap64incrsize_hh;                                    
 unsigned int                                                         
           __cseheap64incrsize; /* Minimum size, in MB, to obtain     
                               When expanding the AMODE 64 heap.      
                               If 0, defaults to 1MB                */
 unsigned int                                                         
           __cseheap64usertoken_hh;                                   
 unsigned int                                                         
           __cseheap64usertoken;/* usertoken for use with ?iarv64     
                               to obtain above the bar storage      */
#endif                                                                
                                                                      
 unsigned int                 /* AMODE 64 Storage Attributes        */
            __cseheap64fprot:1, /* On, AMODE 64 heap storage is to be 
                                 fetch protected                      
                                 Off, storage is not fetch            
                                 protected                          */
            __cseheap64cntlauth:1; /* On, AMODE 64 heap storage has   
                                 CONTROL=AUTH attribute               
                                 Off, storage is CONTROL=UNAUTH     */
 int        __csereserved1[7]; /* Reserved for future use           */
};                                                                    
Note: The entire __csysenv_s structure must be cleared to binary zeros before initializing specific fields within it.

Returned value

If successful, __cinit() returns an environment token that is used on subsequent calls to Metal C functions that require an environment. If unable to create an environment, __cinit() returns 0.

Example

#include <metal.h>                                     
#include <stdlib.h>                                    
#include <string.h>                                    
                                                       
#ifdef _LP64                                           
 register void * myenvtkn __asm("r12");                
                                                       
#else                                                  
 register void * myetkr12 __asm("r12");                
 __csysenv_t     myenvtkn;                             
#endif                                                 
                                                       
void mymtlfcn(void)  {                                 
  struct __csysenv_s mysysenv;                         
                                                       
  void * mystg;                                        
  void * my31stg;                                      
                                                       
  /***************************************************/
  /* Initialize the csysenv structure.               */
  /***************************************************/
  memset(&mysysenv, 0x00, sizeof(mysysenv));           
                                                       
  mysysenv.__cseversion = __CSE_VERSION_1;             
                                                       
  mysysenv.__csesubpool = 129;                         
                                                       
  /***************************************************/
  /* Set heap initial and increment sizes.           */
  /***************************************************/
  mysysenv.__cseheap31initsize = 131072;               
  mysysenv.__cseheap31incrsize = 8192;                 
  mysysenv.__cseheap64initsize = 20;                   
  mysysenv.__cseheap64incrsize = 1;                    
 #ifdef _LP64                                          
  /***************************************************/
  /* Create a Metal C environment.                   */
  /***************************************************/
  myenvtkn = (void * ) __cinit(&mysysenv);             
                                                       
 #else                                                 
  /***************************************************/
  /* Create a Metal C environment.                   */
  /***************************************************/
  myenvtkn = __cinit(&mysysenv);                       
                                                       
  /***************************************************/
  /* Save the high half of R12 and then set R12 to   */
  /* the 8 byte environment token.                   */
  /***************************************************/
  __asm(" LG     12,%0\n"                              
        :                                              
        : "m"(myenvtkn)                                
        : "r12"             );                         
 #endif                                                
                                                       
  /***************************************************/
  /* Call functions that require an environment.     */
  /***************************************************/
  mystg   = malloc(1048576);                           
  my31stg = __malloc31(100);                           
                                                       
  /***************************************************/
  /* Clean up the environment.                       */
  /***************************************************/
  __cterm((__csysenv_t) myenvtkn);                     
}                                                      
In order to share the environment token to other source files there are 2 options:
  • Compile all Metal C files that make up the program by using the RESERVED_REG("r12") compiler option. This reserves register 12 so that the environment token will remain untouched by the compiled code.
  • Pass myenvtkn by using other methods, and for any source that needs to use the environment token declare the global register variable as in this example and assign the environment token to it.
Output: None.