aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--lib/heap.c81
-rw-r--r--lib/heap.h43
3 files changed, 125 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 1115d75..f326a41 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ TERM_RESET:=$(shell echo -e "\e[0;0m")
## Lib setup
LIB_DIST=$(DIST)/lib
LIB_SRC=lib
-LIB_CODE:=$(addprefix $(LIB_SRC)/, base.c darr.c inst.c)
+LIB_CODE:=$(addprefix $(LIB_SRC)/, base.c darr.c heap.c inst.c)
LIB_OBJECTS:=$(LIB_CODE:$(LIB_SRC)/%.c=$(LIB_DIST)/%.o)
LIB_DEPS:=$(LIB_OBJECTS:%.o=%.d)
LIB_CFLAGS=$(CFLAGS)
diff --git a/lib/heap.c b/lib/heap.c
new file mode 100644
index 0000000..d4d9938
--- /dev/null
+++ b/lib/heap.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2023 Aryadev Chavali
+
+ * You may distribute and modify this code under the terms of the
+ * GPLv2 license. You should have received a copy of the GPLv2
+ * license with this file. If not, please write to:
+ * aryadev@aryadevchavali.com.
+
+ * Created: 2023-11-01
+ * Author: Aryadev Chavali
+ * Description: Arena allocator
+ */
+
+#include "./heap.h"
+
+page_t *page_create(size_t max, page_t *next)
+{
+ page_t *page = calloc(1, sizeof(*page) + max);
+ page->used = 0;
+ page->available = max;
+ page->next = next;
+ return page;
+}
+
+size_t page_space_left(page_t *page)
+{
+ return WORD_SAFE_SUB(page->available, page->used);
+}
+
+void page_delete(page_t *page)
+{
+ free(page);
+}
+
+void heap_create(heap_t *heap)
+{
+ heap->beg = page_create(PAGE_DEFAULT_SIZE, NULL);
+ heap->end = heap->beg;
+ heap->pages = 1;
+}
+
+byte *heap_allocate(heap_t *heap, size_t requested)
+{
+ page_t *ptr = heap->beg;
+ while (page_space_left(ptr) < requested)
+ ptr = ptr->next;
+ if (ptr)
+ {
+ byte *data = ptr->used + ptr->data;
+ ptr->used += requested;
+ return data;
+ }
+ // Otherwise we are at the end of the heap, and we need to allocate
+ // a new page
+
+ // Create new page and get the pointer to the start of requested data
+ page_t *new_page = page_create(MAX(PAGE_DEFAULT_SIZE, requested), NULL);
+ byte *data = new_page->used + new_page->data;
+
+ // Set the end of the heap to the new page (update linked list)
+ heap->end->next = new_page;
+ heap->end = new_page;
+ new_page->used += requested;
+ ++heap->pages;
+
+ return data;
+}
+
+void heap_stop(heap_t *heap)
+{
+ page_t *ptr = heap->beg;
+ for (size_t i = 0; i < heap->pages; ++i)
+ {
+ page_t *cur = ptr;
+ page_t *next = ptr->next;
+ page_delete(cur);
+ ptr = next;
+ }
+ heap->beg = NULL;
+ heap->end = NULL;
+ heap->pages = 0;
+}
diff --git a/lib/heap.h b/lib/heap.h
new file mode 100644
index 0000000..b84baf0
--- /dev/null
+++ b/lib/heap.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2023 Aryadev Chavali
+
+ * You may distribute and modify this code under the terms of the
+ * GPLv2 license. You should have received a copy of the GPLv2
+ * license with this file. If not, please write to:
+ * aryadev@aryadevchavali.com.
+
+ * Created: 2023-11-01
+ * Author: Aryadev Chavali
+ * Description: Arena allocator
+ */
+
+#ifndef HEAP_H
+#define HEAP_H
+
+#include "./base.h"
+
+#include <stdlib.h>
+
+#define PAGE_DEFAULT_SIZE 64
+
+typedef struct Page
+{
+ struct Page *next;
+ size_t used, available;
+ byte data[];
+} page_t;
+
+page_t *page_create(size_t, page_t *);
+size_t page_space_left(page_t *);
+void page_delete(page_t *);
+
+typedef struct
+{
+ page_t *beg, *end;
+ size_t pages;
+} heap_t;
+
+void heap_create(heap_t *);
+byte *heap_allocate(heap_t *, size_t);
+void heap_stop(heap_t *);
+
+#endif