Merged the unaligned and aligned heap APIs and simplified the code.
authorMichael Brown <mcb30@etherboot.org>
Thu, 12 May 2005 16:34:57 +0000 (16:34 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 12 May 2005 16:34:57 +0000 (16:34 +0000)
src/core/heap.c
src/include/heap.h [new file with mode: 0644]

index 7f69829..3476f4d 100644 (file)
@@ -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 (file)
index 0000000..2b25a45
--- /dev/null
@@ -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 */