greatbridf 4 лет назад
Родитель
Сommit
f64531c224
3 измененных файлов с 143 добавлено и 0 удалено
  1. 1 0
      include/kernel/errno.h
  2. 23 0
      include/kernel/mem.h
  3. 119 0
      src/kernel/mem.c

+ 1 - 0
include/kernel/errno.h

@@ -7,3 +7,4 @@ extern uint32_t* _get_errno(void);
 #define errno (*_get_errno())
 
 #define ENOMEM 0
+#define ENOTFOUND 1

+ 23 - 0
include/kernel/mem.h

@@ -9,3 +9,26 @@ struct mem_size_info {
 };
 
 extern struct mem_size_info asm_mem_size_info;
+
+// TODO: decide heap start address according
+//   to user's memory size
+#define HEAP_START ((void*)0x01000000)
+
+struct mem_blk_flags {
+    uint8_t is_free;
+    uint8_t has_next;
+    uint8_t _unused2;
+    uint8_t _unused3;
+};
+
+struct mem_blk {
+    size_t size;
+    struct mem_blk_flags flags;
+    // the first byte of the memory space
+    // the minimal allocated space is 4 bytes
+    uint8_t data[4];
+};
+
+void init_heap(void);
+
+void* k_malloc(size_t size);

+ 119 - 0
src/kernel/mem.c

@@ -1 +1,120 @@
+#include <asm/port_io.h>
+#include <kernel/errno.h>
 #include <kernel/mem.h>
+#include <kernel/vga.h>
+#include <kernel_main.h>
+
+static void* p_start;
+static void* p_break;
+
+static int32_t set_heap_start(void* start_addr)
+{
+    p_start = start_addr;
+    return 0;
+}
+
+static int32_t brk(void* addr)
+{
+    p_break = addr;
+    return 0;
+}
+
+// sets errno when failed to increase heap pointer
+static void* sbrk(size_t increment)
+{
+    if (brk(p_break + increment) != 0) {
+        errno = ENOMEM;
+        return 0;
+    } else {
+        errno = 0;
+        return p_break;
+    }
+}
+
+void init_heap(void)
+{
+    // start of the available address space
+    // TODO: adjust heap start address
+    //   according to user's memory size
+    set_heap_start(HEAP_START);
+
+    if (brk(HEAP_START) != 0) {
+        vga_printk("Failed to initialize heap, halting...", 0x0fu);
+        MAKE_BREAK_POINT();
+        asm_cli();
+        asm_hlt();
+    }
+    struct mem_blk* p_blk = sbrk(0);
+    p_blk->size = 4;
+    p_blk->flags.has_next = 0;
+    p_blk->flags.is_free = 1;
+}
+
+// @param start_pos position where to start finding
+// @param size the size of the block we're looking for
+// @return found block if suitable block exists, if not, the last block
+static struct mem_blk*
+find_blk(
+    struct mem_blk* start_pos,
+    size_t size)
+{
+    while (1) {
+        if (start_pos->flags.is_free && start_pos->size >= size) {
+            errno = 0;
+            return start_pos;
+        } else {
+            if (!start_pos->flags.has_next) {
+                errno = ENOTFOUND;
+                return start_pos;
+            }
+            start_pos = ((void*)start_pos)
+                + sizeof(struct mem_blk)
+                + start_pos->size
+                - 4 * sizeof(uint8_t);
+        }
+    }
+}
+
+static struct mem_blk*
+allocate_new_block(
+    struct mem_blk* blk_before,
+    size_t size)
+{
+    sbrk(sizeof(struct mem_blk) + size - 4 * sizeof(uint8_t));
+    if (errno) {
+        return 0;
+    }
+
+    struct mem_blk* blk = ((void*)blk_before)
+        + sizeof(struct mem_blk)
+        + blk_before->size
+        - 4 * sizeof(uint8_t);
+
+    blk_before->flags.has_next = 1;
+
+    blk->flags.has_next = 0;
+    blk->flags.is_free = 1;
+    blk->size = size;
+
+    errno = 0;
+    return blk;
+}
+
+void* k_malloc(size_t size)
+{
+    struct mem_blk* block_allocated;
+
+    block_allocated = find_blk(p_start, size);
+    if (errno == ENOTFOUND) {
+        // 'block_allocated' in the argument list is the pointer
+        // pointing to the last block
+        block_allocated = allocate_new_block(block_allocated, size);
+        // no need to check errno and return value
+        // preserve these for the caller
+    } else {
+        // TODO: split block
+    }
+
+    block_allocated->flags.is_free = 0;
+    return block_allocated->data;
+}