diff cos/kernel/malloc.c @ 40:24ce177e01e8

Added more malloc stuff. Added mem usage
author windel
date Tue, 24 Jan 2012 17:54:16 +0100
parents 7e3bdcb391dc
children
line wrap: on
line diff
--- a/cos/kernel/malloc.c	Mon Jan 16 21:38:55 2012 +0100
+++ b/cos/kernel/malloc.c	Tue Jan 24 17:54:16 2012 +0100
@@ -5,104 +5,153 @@
 
 uint64_t placement_address = (uint64_t)&kernel_end;
 
-void* kmalloc_int(uint64_t size)
-{
-   uint64_t tmp = placement_address;
-   placement_address += size;
-   return (void*)tmp;
-}
-
-void* kmalloc_aligned_int(uint64_t size)
-{
-   if ( (placement_address | 0xFFF) != 0 )
-   {
-      placement_address &= ~(0xFFF);
-      placement_address += 0x1000;
-   }
-   uint64_t tmp = placement_address;
-   placement_address += size;
-   return (void*)tmp;
-}
-
-
 // ================= Other malloc
 // TODO: move this to user space?
 
 #define HEAP_MAGIC 0xc0ffee
-#define HEAP_START 0x400000
-#define HEAP_SIZE  0x200000
 #define HEAP_INUSE 1
 #define HEAP_FREE 0
 
-typedef struct {
-   uint64_t magic;
-   uint64_t state;
-   uint64_t size;
-} heap_t;
-
 /*
   malloc and free divide the chunks of memory present at the heap
   of the kernel into smaller parts.
   The heap is located at: 0x
 */
 
-static heap_t* kernel_heap = (heap_t*) 0x400000; // 4 MB - 6 MB is heap
+static heap_t* kernel_heap = 0; 
+
+void expand_heap(heap_t *heap, uint64_t newsize);
+
 /* Allocates 'size' bytes and returns the pointer if succesfull.
+   Before the kernel is initialized, placement malloc is used.
    Kernelpanic in case of failure..
 */
-
-void* kmalloc(uint64_t size) 
+static void* kmalloc_int(uint64_t size, uint64_t aligned) 
 {
-   return kmalloc_int(size);
-
-   // Start at the beginning of our heap and search a free block:
-   heap_t *current = kernel_heap;
-   while (current->magic == HEAP_MAGIC)
+   // Check if there exists a kernel heap. If not, use placement malloc for now.
+   if (kernel_heap == 0)
    {
-      if ((current->state == HEAP_FREE) && (current->size >= size))
+      // Before that the heap is initialized, use placement malloc
+      if (aligned == 1)
       {
-         // Mark block as used:
-         current->state = HEAP_INUSE;
+         // Align placement address
+         if ( (placement_address | 0xFFF) != 0 )
+         {
+            placement_address &= ~(0xFFF);
+            placement_address += 0x1000;
+         }
+      }
+      uint64_t tmp = placement_address;
+      placement_address += size;
+      return (void*)tmp;
+   }
+   else
+   {
+      // We have a kernel heap, search the heap for a block of suitable size.
 
-         // Insert a heap header if required:
-         if (current->size > size + sizeof(heap_t) + 1)
+      // Start at the beginning of our heap and search a free block:
+      heap_header_t *current = kernel_heap->first_block;
+      while (current->magic == HEAP_MAGIC)
+      {
+         if ((current->state == HEAP_FREE) && (current->size >= size))
          {
-            // Calculate location of the inserted header:
-            heap_t *newheader = (heap_t*) (((char*)current)+size+sizeof(heap_t));
+            // We found a hole with suitable size. Determine if split is of any use.
+
+            // Insert a heap header if required:
+            if (current->size > size + sizeof(heap_t) + 1)
+            {
+               // Calculate location of the inserted header:
+               heap_header_t *newheader = (heap_header_t*) (((uint64_t)current)+size+sizeof(heap_header_t));
 
-            // Set the new header fields:
-            newheader->size = current->size - size - sizeof(heap_t);
-            newheader->state = HEAP_FREE;
-            newheader->magic = HEAP_MAGIC;
+               // Set the new header fields:
+               newheader->size = current->size - size - sizeof(heap_header_t);
+               newheader->state = HEAP_FREE;
+               newheader->magic = HEAP_MAGIC;
 
-            // Set the size of this block
-            current->size = size; 
+               // Set the size of this block
+               current->size = size; 
+            }
+            else
+            {
+               // We allocate this whole block
+               // Mark block as used:
+               current->state = HEAP_INUSE;
+            }
+            // Calculate the size of the block:
+            char *address = ((char*)current)+sizeof(heap_header_t);
+            return address;
+            
          }
-         else
-         {
-            // We allocate this whole block
-         }
-         // Calculate the size of the block:
-         char *address = ((char*)current)+sizeof(heap_t);
-         return address;
-         
+         // Goto next heap block:
+         current = (heap_header_t*)(((uint64_t) current) + current->size + sizeof(heap_header_t));
       }
-      // Goto next heap block:
-      current = (heap_t*)(((char*) current) + current->size + sizeof(heap_t));
+
+      // We did not find a block large enough. Expand the heap and try again.
+      expand_heap(kernel_heap, 0x10000000);
+      return kmalloc_int(size, aligned); 
    }
-   return 0x0;
+}
+
+// Convenient wrappers:
+void* kmalloc(uint64_t size)
+{
+   return kmalloc_int(size, 0);
+}
+
+void* kmalloc_a(uint64_t size)
+{
+   return kmalloc_int(size, 1);
 }
 
 void kfree(void* ptr) 
 {
-  printf("Free address %x\n", ptr);
+   printf("Free address %x\n", ptr);
+   if (kernel_heap == 0)
+   {
+      return;
+   }
+   else
+   {
+      // TODO
+   }
+   // TODO: free blocks:
 }
 
-void init_heap(void)
+heap_t* create_heap(uint64_t location, uint64_t size)
 {
-   // Initialize the kernel heap:
-   kernel_heap->magic = HEAP_MAGIC;
-   kernel_heap->state = HEAP_FREE;
-   kernel_heap->size = HEAP_SIZE - sizeof(heap_t);
+   // Make sure that the new heap location is mapped into the address space:
+   uint64_t i = 0;
+   while (i < size)
+   {
+      alloc_frame( get_page(location + i, kernel_map));
+      i += 0x1000;
+   }
+
+   // create new heap structure:
+   heap_t* h = (heap_t*)kmalloc(sizeof(heap_t));
+   
+   // Create one big hole:
+   h->first_block = (heap_header_t*)location; // Place header at beginning of heap
+   h->first_block->magic = HEAP_MAGIC;
+   h->first_block->state = HEAP_FREE;
+   h->first_block->size = size - sizeof(heap_header_t);
+   return h;
 }
 
+// Make the total heap bigger:
+void expand_heap(heap_t *heap, uint64_t newsize)
+{
+   uint64_t oldsize = heap->end_address - heap->start_address;
+   if (newsize < oldsize)
+   {
+      panic("Cannot expand heap to a smaller size\n");
+   }
+
+   uint64_t i = oldsize;
+   while (i < newsize)
+   {
+      alloc_frame( get_page(heap->start_address + i, kernel_map));
+      i += 0x1000;
+   }
+}
+