diff options
author | Michael Brown | 2005-05-12 18:34:57 +0200 |
---|---|---|
committer | Michael Brown | 2005-05-12 18:34:57 +0200 |
commit | eff4fa5a04ba63faefdc2ffdc51ba9981e5d1e68 (patch) | |
tree | f29d2fc793729b672321539c97b1f7e46d6f9d93 | |
parent | Use the global load_buffer, and the boot_image function. (diff) | |
download | ipxe-eff4fa5a04ba63faefdc2ffdc51ba9981e5d1e68.tar.gz ipxe-eff4fa5a04ba63faefdc2ffdc51ba9981e5d1e68.tar.xz ipxe-eff4fa5a04ba63faefdc2ffdc51ba9981e5d1e68.zip |
Merged the unaligned and aligned heap APIs and simplified the code.
-rw-r--r-- | src/core/heap.c | 135 | ||||
-rw-r--r-- | src/include/heap.h | 62 |
2 files changed, 116 insertions, 81 deletions
diff --git a/src/core/heap.c b/src/core/heap.c index 7f69829d..3476f4d2 100644 --- a/src/core/heap.c +++ b/src/core/heap.c @@ -1,6 +1,14 @@ #include "etherboot.h" #include "init.h" #include "memsizes.h" +#include "heap.h" + +#define ASSERT(...) + +struct heap_block { + size_t size; + char data[0]; +}; size_t heap_ptr, heap_top, heap_bot; @@ -86,94 +94,59 @@ static void init_heap(void) heap_ptr = heap_bot; } -static void reset_heap(void) -{ - heap_ptr = heap_bot; -} - -void *allot(size_t size) -{ - void *ptr; - size_t *mark, addr; - /* Get an 16 byte aligned chunk of memory off of the heap - * An extra sizeof(size_t) bytes is allocated to track - * the size of the object allocated on the heap. - */ - addr = (heap_ptr - (size + sizeof(size_t))) & ~15; - if (addr < heap_top) { - ptr = 0; - } else { - mark = phys_to_virt(addr); - *mark = size; - heap_ptr = addr; - ptr = phys_to_virt(addr + sizeof(size_t)); +/* + * Allocate a block from the heap. + * + */ +void * emalloc ( size_t size, unsigned int align ) { + physaddr_t addr; + struct heap_block *block; + + ASSERT ( ! ( align & ( align - 1 ) ) ); + + addr = ( ( ( heap_ptr - size ) & ~( align - 1 ) ) + - sizeof ( struct heap_block ) ); + if ( addr < heap_top ) { + return NULL; } - return ptr; + + block = phys_to_virt ( addr ); + block->size = ( heap_ptr - addr ); + heap_ptr = addr; + return block->data; } -//if mask = 0xf, it will be 16 byte aligned -//if mask = 0xff, it will be 256 byte aligned -//For DMA memory allocation, because it has more reqiurement on alignment -void *allot2(size_t size, uint32_t mask) -{ - void *ptr; - size_t *mark, addr; - uint32_t *mark1; - - addr = ((heap_ptr - size ) & ~mask) - sizeof(size_t) - sizeof(uint32_t); - if (addr < heap_top) { - ptr = 0; - } else { - mark = phys_to_virt(addr); - *mark = size; - mark1 = phys_to_virt(addr+sizeof(size_t)); - *mark1 = mask; - heap_ptr = addr; - ptr = phys_to_virt(addr + sizeof(size_t) + sizeof(uint32_t)); - } - return ptr; -} +/* + * Allocate all remaining space on the heap + * + */ +void * emalloc_all ( size_t *size ) { + *size = heap_ptr - heap_top - sizeof ( struct heap_block ); + return emalloc ( *size, sizeof ( void * ) ); +} -void forget(void *ptr) -{ - size_t *mark, addr; - size_t size; +/* + * Free a heap block + * + */ +void efree ( void *ptr ) { + struct heap_block *block; - if (!ptr) { - return; - } - addr = virt_to_phys(ptr); - mark = phys_to_virt(addr - sizeof(size_t)); - size = *mark; - addr += (size + 15) & ~15; + ASSERT ( ptr == ( heap_ptr + sizeof ( size_t ) ) ); - if (addr > heap_bot) { - addr = heap_bot; - } - heap_ptr = addr; -} - -void forget2(void *ptr) -{ - size_t *mark, addr; - size_t size; - uint32_t mask; - uint32_t *mark1; + block = ( struct heap_block * ) + ( ptr - offsetof ( struct heap_block, data ) ); + heap_ptr += block->size; - if (!ptr) { - return; - } - addr = virt_to_phys(ptr); - mark = phys_to_virt(addr - sizeof(size_t) - sizeof(uint32_t)); - size = *mark; - mark1 = phys_to_virt(addr - sizeof(uint32_t)); - mask = *mark1; - addr += (size + mask) & ~mask; + ASSERT ( heap_ptr <= heap_bot ); +} - if (addr > heap_bot) { - addr = heap_bot; - } - heap_ptr = addr; +/* + * Free all allocated heap blocks + * + */ +void efree_all ( void ) { + heap_ptr = heap_bot; } -INIT_FN ( INIT_HEAP, init_heap, reset_heap, NULL ); +INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL ); diff --git a/src/include/heap.h b/src/include/heap.h new file mode 100644 index 00000000..2b25a45e --- /dev/null +++ b/src/include/heap.h @@ -0,0 +1,62 @@ +#ifndef HEAP_H +#define HEAP_H + +/* + * Allocate a block with specified (physical) alignment + * + * "align" must be a power of 2. + * + * Note that "align" affects the alignment of the physical address, + * not the virtual address. This is almost certainly what you want. + * + */ +extern void * emalloc ( size_t size, unsigned int align ); + +/* + * Allocate a block, with no particular alignment requirements. + * + */ +static inline void * malloc ( size_t size ) { + return emalloc ( size, sizeof ( void * ) ); +} + +/* + * Allocate all remaining space on the heap + * + */ +extern void * emalloc_all ( size_t *size ); + +/* + * Free a block. + * + * The caller must ensure that the block being freed is the last (most + * recent) block allocated on the heap, otherwise heap corruption will + * occur. + * + */ +extern void efree ( void *ptr ); + +static inline void free ( void *ptr ) { + efree ( ptr ); +} + +/* + * Free all allocated blocks on the heap + * + */ +extern void efree_all ( void ); + +/* + * Resize a block. + * + * The caller must ensure that the block being resized is the last + * (most recent) block allocated on the heap, otherwise heap + * corruption will occur. + * + */ +static inline void * erealloc ( void *ptr, size_t size, unsigned int align ) { + efree ( ptr ); + return emalloc ( size, align ); +} + +#endif /* HEAP_H */ |