Author: blueswirl Date: 2007-06-27 22:09:08 +0200 (Wed, 27 Jun 2007) New Revision: 153
Modified: openbios-devel/arch/sparc32/lib.c Log: Get a real memory allocator for Sparc, based on PPC ofmem
Modified: openbios-devel/arch/sparc32/lib.c =================================================================== --- openbios-devel/arch/sparc32/lib.c 2007-06-27 20:07:37 UTC (rev 152) +++ openbios-devel/arch/sparc32/lib.c 2007-06-27 20:09:08 UTC (rev 153) @@ -32,16 +32,127 @@ return i; }
+typedef struct alloc_desc { + struct alloc_desc *next; + int size; /* size (including) this struct */ +} alloc_desc_t; + +typedef struct mem_range { + struct mem_range *next; + ulong start; + ulong size; +} range_t; + +typedef struct trans { + struct trans *next; + ulong virt; /* chain is sorted by virt */ + ulong size; + ulong phys; + int mode; +} translation_t; + +static struct { + char *next_malloc; + int left; + alloc_desc_t *mfree; /* list of free malloc blocks */ + + range_t *phys_range; + range_t *virt_range; + + translation_t *trans; /* this is really a translation_t */ +} ofmem; +#define ALLOC_BLOCK (64 * 1024) + void *malloc(int size) { - extern struct mem cmem; + alloc_desc_t *d, **pp; + char *ret; + extern struct mem cmem;
- return mem_alloc(&cmem, size, 4); + if( !size ) + return NULL; + + if( size & 3 ) + size += 4 - (size & 3); + size += sizeof(alloc_desc_t); + + /* look in the freelist */ + for( pp=&ofmem.mfree; *pp && (**pp).size < size; pp = &(**pp).next ) + ; + + /* waste at most 4K by taking an entry from the freelist */ + if( *pp && (**pp).size < size + 0x1000 ) { + ret = (char*)*pp + sizeof(alloc_desc_t); + memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) ); + *pp = (**pp).next; + return ret; + } + + if( !ofmem.next_malloc || ofmem.left < size) { + unsigned long alloc_size = ALLOC_BLOCK; + if (size > ALLOC_BLOCK) + alloc_size = size; + // Recover possible leftover + if (ofmem.left > sizeof(alloc_desc_t) + 4) { + alloc_desc_t *d; + + d = (alloc_desc_t*)ofmem.next_malloc; + d->size = ofmem.left - sizeof(alloc_desc_t); + free((unsigned long)d + sizeof(alloc_desc_t)); + } + + ofmem.next_malloc = mem_alloc(&cmem, alloc_size, 4); + ofmem.left = alloc_size; + } + + if( ofmem.left < size) { + printk("out of malloc memory (%x)!\n", size ); + return NULL; + } + d = (alloc_desc_t*) ofmem.next_malloc; + ofmem.next_malloc += size; + ofmem.left -= size; + + d->next = NULL; + d->size = size; + + ret = (char*)d + sizeof(alloc_desc_t); + memset( ret, 0, size - sizeof(alloc_desc_t) ); + return ret; }
void free(void *ptr) { - /* Nothing yet */ + alloc_desc_t **pp, *d; + + /* it is legal to free NULL pointers (size zero allocations) */ + if( !ptr ) + return; + + d = (alloc_desc_t*)((unsigned long)ptr - sizeof(alloc_desc_t)); + d->next = ofmem.mfree; + + /* insert in the (sorted) freelist */ + for( pp=&ofmem.mfree; *pp && (**pp).size < d->size ; pp = &(**pp).next ) + ; + d->next = *pp; + *pp = d; }
+void * +realloc( void *ptr, size_t size ) +{ + alloc_desc_t *d = (alloc_desc_t*)((unsigned long)ptr - sizeof(alloc_desc_t)); + char *p;
+ if( !ptr ) + return malloc( size ); + if( !size ) { + free( ptr ); + return NULL; + } + p = malloc( size ); + memcpy( p, ptr, MIN(d->size - sizeof(alloc_desc_t),size) ); + free( ptr ); + return p; +}