GBDK libraries documentation
PrevChapter 5. LibrariesNext

malloc, free and related functions - stdlib.h

Functions

malloc

void *malloc( size_t numbytes )
Allocate numbytes of memory from the free memory pool and return a pointer to the base of the newly allocated region.

Description

Note that the memory is not cleared upon allocation.

Parameters

numbytes: The number of bytes to allocate

Returns

On success, returns a pointer to the newly allocated region. On failure returns NULL.

calloc

void *calloc( size_t nmem, size_t size )
Attempt to allocate space for nmem objects of size size and return a pointer to the allocated region.

Description

calloc is very similar to malloc but it also clears (fills with zero) the memory region before returning.

Parameters

size: size of one object

nmem: Number of objects to allocate space for

Returns

On success, returns a pointer to the newly allocated and cleared region. On failure, returns NULL.

realloc

void *realloc( void *current, size_t size )
Attempt to re-size a currently allocated region.

Description

realloc is used to resize a currently allocated block without loosing the data contained within. If the current block is larger than the requested block the the trailing data is lost. Note that the end of the block is not cleared if the current block is smaller than the requested one. If current is NULL, then this is equivalent to malloc. If size is zero, then this is equivalent to free.

Parameters

current: Pointer to the currently allocated block.

size: Size of the new block

Returns

On success returns a pointer to the newly allocated block. Note that the new block may be at a different location to the old. On failure or if size is zero, then NULL is returned.

free

int free( void *region )
Free a previously allocated region.

Description

Attempts to free a region previously allocated by malloc, realloc or calloc. Note that only valid regions can be freed. Note also that this prototype differs from the standard C free as it returns an error code.

Parameters

region: Pointer to a previously allocated region.

Returns

On success, returns zero (0). If the region is already free, returns -1. If the region was never allocated, returns -2.

Data types

NULL

NULL is returned by malloc and others upon failure. Currently defined to be equal to zero.

size_t: UWORD

size_t is used to specify the size of an object in bytes. As the GB has an 8 bit processor with a 16 bit address space, size_t is currently defined as a UWORD. Note that due to the banked nature of most GB programs, it might be changed to UDWORD at a later date.

Implementation

This malloc library is implemented using a simple signally linked list of hunks where a hunk is a a header and section of memory that can be either free or used. There is nothing particularly clever about the allocation algorithms. I'm an engineer as opposed to a computer scientist, so if the code gets the job done then it's close enough. Note that I do not know how well this system will hold up against heavy fragmentation caused by allocating many small blocks and keeping some of them. However, I also cant think of a program that you'd want to run on a GB that would do this.

Functions

malloc_init

int malloc_init( void )
If the malloc system is currently uninitialised, initialise it.

Description

Checks to see if the header malloc_first is valid by checking its magic number. If it is not, initialise it by marking it as free, setting it to occupy all of the free ram in the area C000h to D000h, setting the region header pointer to NULL and finally setting the magic number.

Parameters

None

Returns

On success, returns zero (0). If the malloc system is already setup, return -1.

malloc_gc

void malloc_gc( void )
Perform garbage collection on the malloc hunk list by joining consecutive free blocks.

Description

malloc_gc is called by malloc when an attempt to allocate a region fails. malloc_gc attempts to improve the situation by scanning through the malloc hunk list and joining adjacent free blocks into one larger block. In each scan, if two adjacent free blocks are found then they are combined and the scan continued from the first block. At the end of a scan, if any combinations were made then the list is rescanned. I'm not really sure why the rescan is there as in theory all combinations should be made on the first pass.

Parameters

None

Returns

Nothing

Data types

mmalloc_hunk

struct smalloc_hunk {
	UBYTE magic;
	pmmalloc_hunk	next;
	UWORD size;
	int status;
};
mmalloc_hunk is an internal structure used by the malloc library to keep track of allocated and free regions of memory.

Members

magic: A magic number that identifies this as a valid mmalloc_hunk next: Pointer to the next hunk, NULL if this is the last. size: Size in bytes of the hunk. status: Current status of the block that this hunk refers to. One of MALLOC_UNUSED (0), MALLOC_FREE (1) and MALLOC_USED (2). I have no idea why I defined both a MALLOC_UNUSED and a MALLOC_FREE :)

MALLOC_MAGIC: UBYTE

The magic number associated with a valid malloc hunk header. Currently set at a really boring 123. Suggestions for something better will be greatly appreciated.

Notes

The header for a hunk occurs just before the region. Any errant programs that write past their region could overwrite this header and break the linked list. But you get that. Most routines check the magic number while walking the list and abort if a broken header is found.

The amount of memory free after static variables are allocated is determined by using a new linker area called _HEAP, defined in crt0.s. _HEAP occurs after _BSS, so it should occur at the start of free memory. The only data initially in _HEAP is a reference to malloc_heap_start which is used by malloc_init. Note that it is possibly on a real GB for the magic number to occur in a bad place. This should be fixed in crt0.s at the initialisation time. malloc also shares the ram with the stack. Currently the problem of the stack growing down into allocated memory is lessened by allocating from low memory first and by providing a 512 byte buffer (set in malloc_init).

On cartridges with internal memory an extra 8k from A000h to BFFFh is available. Unfortunately free assumes that hunks are consecutive which causes problems. Two solutions are shifting _BSS to start at A000h or defining an extra flag in the header that is set if the next hunk is consecutive to the current one. The second option would also allow paged ram to be used, although it would have to be managed carefully.


PrevHomeNext
Types - types.hUpSupport for multiple fonts - font.h