/* * Test * mode = 0 Normal mode (default) * 1 Debug mode * -1 Usage status dump * -2 Detailed usage status dump */ EXPORT void _mem_malloctest( int mode, MACB *_macb ) { MACB *macb = AlignMACB(_macb); if ( mode >= 0 ) { /* Change test mode */ macb->testmode = mode; _mem_chkalloc = chkalloc; } else { /* Dump usage status */ chkalloc(NULL, mode, macb); } }
/* * Free memory */ static void _mem_free( void *ptr, MACB *macb ) { LIST *aq; if ( ptr == 0 ) { return; } if ( macb->testmode > 0 ) { if ( !chkalloc(ptr, 0, macb) ) { return; } } aq = (LIST *)ptr - 1; clrAreaFlag(aq, AREA_USE); if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) { /* Merge with just next free area */ removeFreeQue(aq->next + 1); removeAreaQue(aq->next); } if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->previous, AREA_USE) ) { /* Merge with just previous free area */ aq = aq->previous; removeFreeQue(aq + 1); removeAreaQue(aq->next); } /* If whole page is empty, then release the page itself */ if ( chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) { /* Page release */ removeAreaQue(aq->next); removeAreaQue(aq); (*macb->relblk)(aq); } else { /* Register free area in free queue */ appendFreeArea(aq, macb); } }
/* * Memory allocate */ static void *_mem_malloc(RAW_U32 size, MACB *macb) { LIST *q; if ( macb->testmode) { chkalloc(0, 0, macb); } /* If smaller than the minimum fragment size, allocate the minimum fragment size */ if ( size > 0 && size < MIN_FRAGMENT ) { size = MIN_FRAGMENT; } size = ROUND(size); if ( size <= 0 ) { return 0; } /* Search free queue */ q = searchFreeArea(size, macb); if ( q != &macb->freeque ) { /* Free space available: first, isolate from free queue */ removeFreeQue(q); q = q - 1; } else { /* No free space, then allocate new page */ q = newPage(size, macb); if ( q == 0 ) { return 0; /* Insufficient memory */ } } /* Allocate memory */ return allocate(q, size, macb); }
/* * Memory allocation error check * If ptr != NULL, performs a memory allocation error check, * including a check to see whether memory allocation corresponds * properly with ptr allocated blocks. * If ptr == NULL, performs the memory allocation error check * only and returns TRUE if all is OK. */ EXPORT BOOL _mem_malloccheck( void *ptr, MACB *_macb ) { MACB *macb = AlignMACB(_macb); return chkalloc(ptr, 0, macb); }
/* * Memory allocation size change */ static void *_mem_realloc( void *ptr, RAW_U32 size, MACB *macb ) { LIST *aq; RAW_U32 oldsz, sz; if ( macb->testmode > 0 ) { if ( !chkalloc(ptr, 0, macb) ) { return 0; } } /* If smaller than minimum fragment size, allocate minimum fragment size */ if ( size > 0 && size < MIN_FRAGMENT ) { size = MIN_FRAGMENT; } size = ROUND(size); aq = (LIST *)ptr - 1; if ( ptr != 0 ) { /* Current allocation size */ oldsz = (RAW_U32)AreaSize(aq); /* Merge if next space is free space */ if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) { removeFreeQue(aq->next + 1); removeAreaQue(aq->next); } sz = (RAW_U32)AreaSize(aq); } else { sz = oldsz = 0; } if ( size <= sz ) { if ( size > 0 ) { /* Fragment current area and allocate */ allocate(aq, size, macb); } else { /* Release area */ _mem_free(ptr, macb); ptr = 0; } } else { /* Allocate new area */ void *newptr = _mem_malloc(size, macb); if ( newptr == 0 ) { /* Reallocate original area at original size */ if ( ptr != 0 ) { allocate(aq, oldsz, macb); } return 0; } if ( ptr != 0 ) { /* Copy contents */ raw_memcpy(newptr, ptr, oldsz); /* Release old area */ _mem_free(ptr, macb); } ptr = newptr; } return ptr; }