ctr_eFuse/cr_alloc.c
(no author) 42b718d775 Add first files.
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_eFuse@1 ff987cc8-cf2f-4642-8568-d52cce064691
2009-12-21 08:45:37 +00:00

478 lines
10 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}