The Metal C Runtime Library provides the ability to completely
replace the underlying heap services at run time. You can use this
function if you want the heap services to use a different storage
management mechanism, for instance, one that is already in use elsewhere
within an application.
A Metal C application replaces the underlying heap services by
providing sets of function entry points in the
__csysenv_s structure
that is passed to the __cinit() function. To have the function entry
point fields available and recognized by the __cinit() function, take
the following steps:
- Define __METAL_CSYSENV_VERSION 2 so that the __csysenv_s structure
contains the heap service function entry point fields.
- In the __csysenv_s structure, set field __cseversion to __CSE_VERSION_2.
- In the __csysenv_s structure, provide addresses
for heap functions that are to be replaced.
- Call the __cinit() function, providing the __csysenv_s structure
that was initialized.
The Metal C application can provide at environment initialization
time 8 bytes of data that can be accessed by the replacement heap
services. To reserve the 8 bytes of data, take the following steps:
- Before calling the __cinit() function, set the user data of the
application in field __cseheapuserdata in the __csysenv_s structure.
- Use the R12 environment token value as a pointer to the __csysenvtoken_s structure.
In this structure, field __csetheapuserdata contains
8 bytes of data of the application.
During the __cinit() call, field __csetheapuserdata can
only be set from __cseheapuserdata if heap services
have been replaced; otherwise, field __csetheapuserdata will
be set to binary zeroes.
Two sets of heap service function entry points are provided, one
set for replacing heap services in the AMODE 31 version of the library,
and the other set for replacing heap services in the AMODE 64 version
of the library.
AMODE 31 heap services
To replace heap services
in the AMODE 31 version of the library, consider the following
__csysenv_s fields:
- void * (*__cseamode31malloc) (size_t)
- When specified, MCRTL AMODE 31 malloc() calls this routine to
obtain a piece of below-the-bar heap storage and returns its result
to the caller of malloc(). __cseamode31malloc is
treated as having the same function prototype as malloc():
void * malloc (size_t);
- void (* __cseamode31free) (void *)
- When specified, MCRTL AMODE 31 free() calls this routine to free
a piece of heap storage. __cseamode31free is treated
as having the same function prototype as free(): void free(void
*);
- void * (*__cseamode31realloc) (void *, size_t)
- When specified, MCRTL AMODE 31 realloc() calls this routine to
perform a realloc for a piece of heap storage and returns its result
to the caller of realloc(). __cseamode31realloc is
treated as having the same function prototype as realloc():
void * realloc (void *, size_t);
Providing this routine
is optional. If realloc() is called when a __cseamode31malloc routine
has been provided but __cseamode31realloc has not,
realloc() will return a zero.
Note: __cseamode31malloc and __cseamode31free must
be provided together. __cseamode31realloc is optional,
but when it is provided, the application must also include the other
AMODE 31 heap services in this set.
AMODE 64 heap services
To replace heap services
in the AMODE 64 version of the library, consider the following
__csysenv_s fields:
- void * (* __cseamode64malloc) (size_t)
- When specified, MCRTL AMODE 64 malloc() calls this routine to
obtain a piece of above-the-bar heap storage and returns to the caller
of malloc(). __cseamode64malloc is treated as having
the same function prototype as malloc(): void * malloc (size_t);
- void * (*__cseamode64malloc31) (size_t)
- When specified, MCRTL AMODE 64 __malloc31() calls this routine
to obtain a piece of below-the-bar heap storage and returns its result
to the caller of __malloc31(). __cseamode64malloc31 is
treated as having the same function prototype as __malloc31():
void * __malloc31(size_t);
- void (* __cseamode64free) (void *)
- When specified, MCRTL AMODE 64 free() calls this routine to free
a piece of heap storage. __cseamode64free is treated
as having the same function prototype as free(): void free(void
*);
Note that MCRTL AMODE 64 free() accepts as input and
processes heap storage that is allocated above or below the bar. The
user-specified __cseamode64free routine must provide
the same capability.
- void * (*__cseamode64realloc) (void *, size_t)
- When specified, MCRTL AMODE 64 realloc() calls this routine to
perform a realloc for a piece of heap storage and returns its result
to the caller of realloc(). __cseamode64realloc is
treated as having the same function prototype as realloc():
void * realloc (void *, size_t);
Providing this routine
is optional. If realloc() is called when a __cseamode64malloc routine
has been provided but __cseamode64realloc has not,
realloc() will return a zero.
Note that MCRTL AMODE 64 realloc()
accepts as input and processes heap storage that is allocated above
or below the bar. The user-specified __cseamode64realloc routine
must provide the same capability.
Note: __cseamode64malloc, __cseamode64malloc31,
and __cseamode64free must all be provided together. __cseamode64realloc is
optional, but when it is provided, the application must also include
the other AMODE 64 heap services in this set.
Usage notes
- Each heap service gets control in the AMODE of the calling service.
The heap service must return to the calling service in that same AMODE.
- Each heap service is called using standard Metal C linkage conventions,
including:
- GPR 1 containing the address of the function parameter list (using
C style parameter passing)
- GPR 13 containing the address of a stack frame allocated on a
contiguous Metal C stack
GPR 12 contains the environment token representing the Metal
C environment that is currently in use.
- It is not necessary to provide a replacement for the calloc()
function. The calloc() function calls malloc() as part of its processing,
so replacing malloc() indirectly alters the behavior of calloc() as
well.
- When user-provided heap services are in use, the Metal C Runtime
Library makes no attempt to keep track of any heap storage that has
been allocated by the application. The application is entirely
responsible for tracking its heap storage, and for freeing it after
it calls __cterm() to terminate the Metal C environment.
- The heap allocation functions should return NULL when they are
unable to obtain storage. The application is responsible for capturing
its own diagnostic data when necessary.
- The Metal C Runtime Library expects the following alignment for
the storage that is returned by the replacement heap services:
- Storage returned from the below-the-bar heap (AMODE 64 __malloc31(),
and AMODE 31 malloc()) is doubleword aligned.
- Storage returned from the above-the-bar heap (AMODE 64 malloc())
is quadword aligned.