4.1. Malloc subsystem

A process can dynamically allocate chunks of memory from the process heap by calling malloc subsystem subroutines. If the subroutine call succeeds, a process will be given the requested amount of virtual memory pages from the operating system, and those pages will be contiguously mapped in the process address space.

On AIX, the mapping addresses of newly allocated virtual pages are varied, depending on the user process model. For the detailed explanation about the available address range of the process heap, see 3.2, “The 32-bit user process model” on page 109 and 3.3, “The 64-bit user process model” on page 130.

The malloc subsystem performs the following fundamental memory operations:

AllocationAllocates the specified size of virtual memory.
DeallocationDeallocates (frees) the previous acquired memory space.
ReallocationReallocates (adjusts) the size of the previous acquired memory space.

The malloc subsystem provides the following subroutines grouped by the function categories:

  • Allocation

    - malloc()

    - calloc()

    - alloca()

    - valloc()

  • Deallocation

    - free()

  • Reallocation

    - realloc()

  • Other purposes

    - mallopt()

    - mallinfo()

    - mallinfo_heap()

    - disclaim()

Once virtual memory pages are allocated by calling either malloc(), calloc(), or valloc() sub-routines, those routines internally call the system call sbrk() and increase the break value, which defines the maximum address of the process data segment (see Figure 3-8 on page 126).

If the process calls the free() sub-routine with the address of previously allocated memory, the corresponding virtual memory pages are marked free and placed in the list,[1] with which the malloc subsystem manages free virtual pages. The reference to free virtual pages should return a segmentation violation (SIGSEGV) to the caller.

[1] Technically, it is an internal data structure, not a linked-list.

If the process again requests to allocate memory through the malloc subsystem after that, the subsystem will try to allocate the requested memory size from the list. If sufficient chunks of memory are available in the list, the subsystem returns it. Otherwise, sbrk() is again internally called by the subsystem to increase the break value.

4.1.1. malloc(), calloc(), valloc(), and alloca()

Use the malloc() or calloc() subroutines to request only as much space as you actually need. Never request and then initialize a maximum-sized array when the actual situation uses only a fraction of it.

When a process touches a new page to initialize the array elements, the process effectively forces the VMM to steal a page of real memory from someone. Later, this results in a page fault when the process that owned that page tries to access it again. The difference between the malloc() and calloc() subroutines is not just in the interface.

Because the calloc() subroutine zeroes the allocated storage, it touches every page that is allocated, whereas the malloc() subroutine touches only the first page. If you use the calloc() subroutine to allocate a large area and then use only a small portion at the beginning, you place an unnecessary load on the system. Not only do the pages have to be initialized, but if their real-memory frames are reclaimed, the initialized and never-to-be-used pages must be written out to paging space. This situation wastes both I/O and paging space.

The valloc() subroutine, found in many BSD systems, is supported as a compatibility interface in the Berkeley compatibility library (libbsd.a). The valloc() subroutine calls the malloc() subroutine and automatically page-aligns requests that are greater than one page. The only difference between the valloc() subroutine in the libbsd.a library and the one in the standard C library (described above) is in the value returned when the size parameter is zero. The valloc() subroutine has the same effect as malloc(), except that the allocated memory is aligned to a multiple of the value returned by sysconf(_ SC_PAGESIZE).

The alloca() subroutine allocates the number of bytes of space specified by the Size parameter in the stack frame of the caller. This space is automatically freed when the subroutine that called the alloca subroutine returns to its caller.

If alloca() is used in the code and compiled with the C++ compiler, #pragma alloca would also have to be added before the usage of alloca() in the code. Alternatively, the -ma option would have to be used while compiling the code.

4.1.2. mallopt(), mallinfo, and mallinfo_heap()

The mallopt() and mallinfo() subroutines are provided for source-level compatibility with the System V malloc subroutines. Nothing done with the mallopt() subroutine affects how memory is allocated by the system, unless the M_MXFAST option is used.

The mallinfo() subroutine can be used to obtain information about the heap managed by the malloc() subroutine. Refer to the malloc.h file for details of the mallinfo structure.

Note

When MALLOCTYPE is set to buckets and the memory request is within the range of block sizes defined for the buckets, the memory request is serviced but the heap statistics that are reported by mallinfo() are not updated. See 4.2.3, “The default memory allocator with the malloc buckets extension” on page 173 for a detailed explanation about malloc buckets.


The mallinfo_heap() subroutine provides information about a specific heap if malloc multiheap is enabled (see 4.2.6, “Malloc multiheap” on page 181). The mallinfo_heap() subroutine returns a structure that details the properties and statistics of the heap specified by the user. Refer to the malloc.h file for details about the mallinfo_heap structure.

Note

The mallinfo_heap() subroutine should not be used with the 3.1 memory allocator explained in 4.2.1, “The 3.1 memory allocator” on page 171.


4.1.3. disclaim()

If a large structure is used early and then left untouched for the remainder of the process life, it should be released. It is not sufficient to use the free() subroutine to free the space that was allocated with the malloc() or calloc() subroutines on AIX, unless the MALLOCDISCLAIM environment variable is defined. The free() subroutine releases only the address range that the structure occupied from the process address space. To release the real memory and paging space, use the disclaim() subroutine to disclaim the space as well. The call to disclaim() should be before the call to free().

When the disclaim() routine is called with the specific range of memory address, it instructs VMM to relinquish physical in-memory pages, and disk blocks in the paging space. The resultant address-range is logically 0 again, just like it was when it was created, before any accesses were made to it.

This is a very useful optimization technique that some applications can use to get performance gains. For example, assume that an application has just finished using a buffer that is a small portion of a virtual memory address range, and it needs to manipulate the other data in the same address range. In this case, the application can call disclaim() specifying that memory range, which will be replenished with 0-filled pages on subsequent accesses. The call to disclaim() avoids the unnecessary page-in of staled data from the paging space.

MALLOCDISCLAIM

If the MALLOCDISCLAIM environment variable is set as shown in the following example before a process start-up, all calls to the free() subroutine automatically instruct the malloc subsystem to call the disclaim() subroutine internally:

MALLOCDISCLAIM=true

This is useful in circumstances where a process has a high paging-space usage, but is not actually using the memory.

Note

It is not supported to insert MALLOCDISCLAIM=true in /etc/environment.


For a detailed description of the malloc subsystem subroutines, please refer to the “System Memory Allocation Using the malloc subsystem” section in AIX 5L Version 5.2 General Programming Concepts: Writing and Debugging Programs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset