#include #include #include typedef int BOOL; typedef signed char s8; typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef unsigned long long u64; #include "cr_alloc.h" #define OFFSET(n, a) (((u32) (n)) & ((a) - 1)) #define TRUNC(n, a) (((u32) (n)) & ~((a) - 1)) #define ROUND(n, a) (((u32) (n) + (a) - 1) & ~((a) - 1)) #define ALIGNMENT 32 // alignment in bytes #define MINOBJSIZE (HEADERSIZE + ALIGNMENT) // smallest object #define HEADERSIZE ROUND(sizeof(Cell), ALIGNMENT) //---- InRange(): True if a <= targ < b #define InRange(targ, a, b) \ ((u32)(a) <= (u32)(targ) && (u32)(targ) < (u32)(b)) //---- RangeOverlap(): True if the ranges a and b overlap in any way. #define RangeOverlap(aStart, aEnd, bStart, bEnd) \ (((u32)(bStart) <= (u32)(aStart)) && ((u32)(aStart) < (u32)(bEnd)) || \ ((u32)(bStart) < (u32)(aEnd)) && ((u32)(aEnd) <= (u32)(bEnd)) ) //---- RangeSubset(): True if range a is a subset of range b // Assume (aStart < aEnd) and (bStart < bEnd) #define RangeSubset(aStart, aEnd, bStart, bEnd) \ ((u32)(bStart) <= (u32)(aStart) && (u32)(aEnd) <= (u32)(bEnd)) typedef struct Cell Cell; typedef struct HeapDesc HeapDesc; struct Cell { struct Cell *prev; struct Cell *next; long size; // size of object plus HEADERSIZE }; struct HeapDesc { long size; // if -1 then heap is free. Note OS_AllocFixed() // could make a heap empty. Cell *free; // pointer to the first free cell Cell *allocated; // pointer to the first used cell }; typedef struct { // volatile because some functions use this as hidden macro parameter void *arenaStart; void *arenaEnd; HeapDesc *heapArray; } OSHeapInfo; /* -- heapInfo - arenaStart (OSHeapInfo) -- heapArray -- (HeapDesc) -- arenaStart -- */ static OSHeapInfo *_sys_heapInfo; static Cell *DLAddFront(Cell * list, Cell * cell) { cell->next = list; cell->prev = NULL; if (list) { list->prev = cell; } return cell; } static Cell *DLExtract(Cell * list, Cell * cell) { if (cell->next) { cell->next->prev = cell->prev; } if (cell->prev == NULL) { return cell->next; } else { cell->prev->next = cell->next; return list; } } static Cell *DLInsert(Cell * list, Cell * cell) { Cell *prev; Cell *next; for (next = list, prev = NULL; next; prev = next, next = next->next) { if (cell <= next) { break; } } cell->next = next; cell->prev = prev; if (next) { next->prev = cell; if ((char *)cell + cell->size == (char *)next) { //---- Coalesce forward cell->size += next->size; cell->next = next = next->next; if (next) { next->prev = cell; } } } if (prev) { prev->next = cell; if ((char *)prev + prev->size == (char *)cell) { //---- Coalesce back prev->size += cell->size; prev->next = next; if (next) { next->prev = prev; } } return list; } else { return cell; // cell becomes new head of list } } static void *cr_alloc_Alloc( u32 size) { OSHeapInfo *heapInfo; HeapDesc *hd; Cell *cell; // candidate block Cell *newCell; // ptr to leftover block long leftoverSize; // size of any leftover heapInfo = _sys_heapInfo; hd = heapInfo->heapArray; // printf("heapArray 2 0x%p\n", hd); // Enlarge size to smallest possible cell size size += HEADERSIZE; size = ROUND(size, ALIGNMENT); // Search for block large enough for (cell = hd->free; cell != NULL; cell = cell->next) { if ((long)size <= cell->size) { break; } } if (cell == NULL) { // miya printf("%s %d\n",__FUNCTION__,__LINE__); return NULL; } leftoverSize = cell->size - (long)size; if (leftoverSize < MINOBJSIZE) { //---- Just extract this cell out since it's too small to split hd->free = DLExtract(hd->free, cell); } else { //---- cell is large enough to split into two pieces cell->size = (long)size; //---- Create a new cell newCell = (Cell *) ((char *)cell + size); newCell->size = leftoverSize; //---- Leave newCell in free, and take cell away newCell->prev = cell->prev; newCell->next = cell->next; if (newCell->next != NULL) { newCell->next->prev = newCell; } if (newCell->prev != NULL) { newCell->prev->next = newCell; } else { // SDK_TASSERTMSG(hd->free == cell, OS_ERR_ALLOCFROMHEAP_BROKENHEAP); hd->free = newCell; } } //---- Add to allocated list hd->allocated = DLAddFront(hd->allocated, cell); return (void *)((char *)cell + HEADERSIZE); } static void cr_alloc_Free( void *ptr) { OSHeapInfo *heapInfo; HeapDesc *hd; Cell *cell; heapInfo = _sys_heapInfo; cell = (Cell *) ((char *)ptr - HEADERSIZE); hd = heapInfo->heapArray; hd->allocated = DLExtract(hd->allocated, cell); hd->free = DLInsert(hd->free, cell); } u32 OSi_GetTotalAllocSize(BOOL isHeadInclude) { OSHeapInfo *heapInfo; Cell *cell; u32 sum = 0; heapInfo = _sys_heapInfo; if (isHeadInclude) { for (cell = heapInfo->heapArray->allocated; cell; cell = cell->next) { sum += (u32)(cell->size); } } else { for (cell = heapInfo->heapArray->allocated; cell; cell = cell->next) { sum += (u32)(cell->size - HEADERSIZE); } } return sum; } u32 cr_alloc_GetTotalFreeSize(void) { OSHeapInfo *heapInfo; Cell *cell; u32 sum = 0; heapInfo = _sys_heapInfo; for (cell = heapInfo->heapArray->free; cell; cell = cell->next) { sum += (u32)(cell->size - HEADERSIZE); } return sum; } u32 cr_alloc_GetMaxFreeSize(void) { OSHeapInfo *heapInfo; Cell *cell; u32 candidate = 0; heapInfo = _sys_heapInfo; for (cell = heapInfo->heapArray->free; cell; cell = cell->next) { u32 size = (u32)(cell->size - HEADERSIZE); if (size > candidate) { candidate = size; } } return candidate; } static void *cr_alloc_InitAlloc(void *arenaStart, void *arenaEnd) { OSHeapInfo *heapInfo; HeapDesc *hd; Cell *cell; heapInfo = arenaStart; _sys_heapInfo = heapInfo; heapInfo->heapArray = (void *)((u32)arenaStart + sizeof(OSHeapInfo)); /* -- heapInfo - arenaStart (OSHeapInfo) -- heapArray -- (HeapDesc) -- arenaStart -- */ hd = heapInfo->heapArray; hd->size = -1; hd->free = hd->allocated = NULL; //---- Set OSi_CurrentHeap to an invalid value //---- Reset arenaStart to the nearest reasonable location arenaStart = (void *)((char *)heapInfo->heapArray + sizeof(HeapDesc) ); arenaStart = (void *)ROUND(arenaStart, ALIGNMENT); heapInfo->arenaStart = arenaStart; heapInfo->arenaEnd = (void *)TRUNC(arenaEnd, ALIGNMENT); hd = heapInfo->heapArray; if (hd->size < 0) { // hd->size = (char *)end - (char *)start; hd->size = (char *)(heapInfo->arenaEnd)- (char *)(heapInfo->arenaStart); // cell = (Cell *) start; cell = (Cell *)(heapInfo->arenaStart); cell->prev = NULL; cell->next = NULL; cell->size = hd->size; hd->free = cell; hd->allocated = 0; } return heapInfo->arenaStart; } /* */ static int alloc_counter = 0; static int alloc_counter2 = 0; //#define TSIZE_KERNEL_BUFFER 0x30000 #define TSIZE_KERNEL_BUFFER 0x20000 static u32 __kernel_bufmgr_buffer[TSIZE_KERNEL_BUFFER/sizeof(u32)]; int cr_mem_get_counter(void) { return alloc_counter; } int cr_mem_get_counter2(void) { return alloc_counter2; } void cr_mem_bufmgr_initialize(void) { //miya printf("%s %d\n",__FUNCTION__,__LINE__); memset(__kernel_bufmgr_buffer, 0, TSIZE_KERNEL_BUFFER); (void)cr_alloc_InitAlloc((void *)__kernel_bufmgr_buffer, (void *)&(__kernel_bufmgr_buffer[TSIZE_KERNEL_BUFFER/sizeof(u32)])); alloc_counter = 0; alloc_counter2 = 0; } void *cr_mem_malloc(size_t size) { void *p_blk; alloc_counter++; p_blk = cr_alloc_Alloc( size ); if( NULL == p_blk ) { //miya fprintf(stderr, "Error:%s %d\n",__FUNCTION__,__LINE__); return NULL; } memset( p_blk, 0 , size); return p_blk; } void cr_mem_free(void *ptr) { cr_alloc_Free( ptr ); alloc_counter--; } void *cr_mem_calloc(size_t nmemb, size_t size) { void *p_blk; alloc_counter++; p_blk = cr_alloc_Alloc( size * nmemb ); if( NULL == p_blk ) { //miya fprintf(stderr, "Error:%s %d\n",__FUNCTION__,__LINE__); return NULL; } return p_blk; } void *cr_mem_realloc(void *ptr, size_t size) { void *p_blk; // OSHeapInfo *heapInfo; // HeapDesc *hd; // heapInfo = _sys_heapInfo; // hd = heapInfo->heapArray; // KMEMB *hdr; Cell *cell; p_blk = cr_alloc_Alloc( size ); if( NULL == p_blk ) { //miya fprintf(stderr, "Error:call realloc error %d\n",alloc_counter); return NULL; } // hdr = (KMEMB *)ptr - 1; cell = (Cell *) ((char *)ptr - HEADERSIZE); #if 0 if( hdr->size > size ) { memcpy(p_blk, ptr, size); } else { memcpy(p_blk, ptr, hdr->size); } #else if( cell->size > size ) { memcpy(p_blk, ptr, size); } else { memcpy(p_blk, ptr, cell->size); } #endif cr_alloc_Free( ptr ); return p_blk; }