diosmios/alloc.c

205 lines
6.2 KiB
C

#include "alloc.h"
#include "vsprintf.h"
u8 *RAM;//[_AHEAP_SIZE_TOTAL];
HeapInfoEntry *HeapInfoEntries=(HeapInfoEntry *)NULL;
extern u32 DRAMRead( u32 a );
extern void DRAMWrite( u32 a, u32 b );
void HeapInit( u8 *Offset )
{
//RAM = (u8*)0xFFFE4000;
//RAM = (u8*)0x13600000;
//RAM = (u8*)0x00600000;
RAM = Offset;
HeapInfoEntries = (HeapInfoEntry*)(RAM+_AHEAP_SIZE);
memset32( HeapInfoEntries, 0, _AHEAP_INFO_SIZE );
while( HeapInfoEntries[0].Offset != 0 )
{
EXIControl(1);
dbgprintf("Alloc:Failed to clear memory!:%08X", HeapInfoEntries[0].Offset );
Shutdown();
}
// dbgprintf("Cleared 0x%04X bytes Space for %d allocs\n", _AHEAP_INFO_SIZE, _AHEAP_INFO_SIZE / 8 );
}
void *malloc( u32 _size )
{
if( _size == 0 )
return NULL;
if( _size > _AHEAP_SIZE )
return NULL;
//align size to 32, easy cheat toallow all allocs to be aligned easily
u32 size = (_size+0x1F) & (~0x1F);
//find a free entry to be used
u32 entry = 0xdeadbeef;
u32 i;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
{
entry = i;
break;
}
}
if( entry == 0xdeadbeef )
{
EXIControl(1);
dbgprintf("Alloc: run out of entries!\n");
while(1);
}
//dbgprintf("Alloc:Using entry:%d to alloc %u(%u) bytes...\n", entry, size, _size );
//Now we search a used entry
u32 used_entry = 0xdeadbeef;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
continue;
used_entry = i;
break;
}
if( used_entry == 0xdeadbeef )
{
//dbgprintf("There are no other entries used atm\n");
HeapInfoEntries[entry].Offset = RAM;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc1: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
}
find_space:
;
//dbgprintf("[%02d]Offset:%08X Size:%08X\n", used_entry, HeapInfoEntries[used_entry].Offset, HeapInfoEntries[used_entry].Size );
//now we search for the next closest and the previous closest entry
u32 next = 0xdeadbeef;
u32 prev = 0xdeadbeef;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
continue;
if( used_entry == i )
continue;
if( next == 0xdeadbeef )
{
if( HeapInfoEntries[i].Offset > HeapInfoEntries[used_entry].Offset )
next = i;
} else {
if( HeapInfoEntries[i].Offset < HeapInfoEntries[next].Offset && HeapInfoEntries[i].Offset > HeapInfoEntries[used_entry].Offset )
next = i;
}
if( prev == 0xdeadbeef )
{
if( HeapInfoEntries[i].Offset < HeapInfoEntries[used_entry].Offset )
prev = i;
} else {
if( HeapInfoEntries[i].Offset > HeapInfoEntries[prev].Offset && HeapInfoEntries[i].Offset < HeapInfoEntries[used_entry].Offset )
prev = i;
}
}
if( next == 0xdeadbeef )
{
//dbgprintf("This is the last entry\n");
//check if there is engough space left for our alloc
if( (u32)(HeapInfoEntries[used_entry].Offset-RAM) + HeapInfoEntries[used_entry].Size + size <= _AHEAP_SIZE )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[used_entry].Offset + HeapInfoEntries[used_entry].Size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc2: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
}
;//dbgprintf("2Not enough space left only had:%d\n", HEAP_SIZE - ((u32)(HeapInfoEntries[used_entry].Offset-RAM) + HeapInfoEntries[used_entry].Size) );
} else if( (u32)(HeapInfoEntries[used_entry].Offset) + HeapInfoEntries[used_entry].Size + size < (u32)(HeapInfoEntries[next].Offset) )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[used_entry].Offset + HeapInfoEntries[used_entry].Size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc4: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
} else {
;//dbgprintf("4Not enough space left only had:%d %d:%d\n", (u32)( HeapInfoEntries[next].Offset - HeapInfoEntries[used_entry].Offset ) - HeapInfoEntries[used_entry].Size, next, used_entry );
}
if( prev == 0xdeadbeef )
{
//dbgprintf("This is the first entry\n");
if( (u32)(HeapInfoEntries[used_entry].Offset-RAM) >= size )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[used_entry].Offset - size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc3: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
}
;//dbgprintf("3Not enough space left only had:%d\n", (u32)(HeapInfoEntries[used_entry].Offset-RAM) );
} else if( (u32)(HeapInfoEntries[prev].Offset) + HeapInfoEntries[prev].Size + size < (u32)(HeapInfoEntries[used_entry].Offset) )
{
HeapInfoEntries[entry].Offset = HeapInfoEntries[prev].Offset + HeapInfoEntries[prev].Size;
HeapInfoEntries[entry].Size = size;
//dbgprintf("alloc5: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[entry].Offset, HeapInfoEntries[entry].Size, entry );
return HeapInfoEntries[entry].Offset;
} else {
;//dbgprintf("5Not enough space left only had:%d\n", (u32)(HeapInfoEntries[used_entry].Offset-HeapInfoEntries[prev].Offset) - HeapInfoEntries[prev].Size );
}
//if we land here we have to go to the next entry
u32 temp = used_entry + 1;
used_entry = 0xdeadbeef;
for( i=temp; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == 0 )
continue;
used_entry = i;
break;
}
if( used_entry != 0xdeadbeef )
goto find_space;
dbgprintf("Alloc:failed to alloc %d bytes\n", size );
return NULL;
}
void *malloca( u32 size, u32 align )
{
return malloc( size );
}
void free( void *ptr )
{
if( ptr == NULL )
return;
u32 i;
for( i=0; i < _AHEAP_INFO_SIZE / sizeof(HeapInfoEntry); ++i )
{
if( HeapInfoEntries[i].Offset == ptr )
{
//dbgprintf("free: ptr:%p size:%08X Entry:%d\n", HeapInfoEntries[i].Offset, HeapInfoEntries[i].Size, i );
HeapInfoEntries[i].Offset = NULL;
HeapInfoEntries[i].Size = 0;
ptr = NULL;
return;
}
}
}