From 5ee7865458aa386a585aceb2fc4ecb555c18be89 Mon Sep 17 00:00:00 2001
From: Dan Hirsch <thequux@thequux.com>
Date: Mon, 23 Apr 2012 00:35:58 +0100
Subject: [PATCH] Added allocator and first cut at makefile

---
 .gitignore      |  2 ++
 config.mk       |  2 ++
 lib/Makefile    |  6 ++++
 lib/allocator.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/allocator.h | 12 ++++++++
 5 files changed, 95 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 config.mk
 create mode 100644 lib/Makefile
 create mode 100644 lib/allocator.c
 create mode 100644 lib/allocator.h

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..a70237a6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+*~
diff --git a/config.mk b/config.mk
new file mode 100644
index 00000000..16209be9
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,2 @@
+CFLAGS := $(shell pkg-config --cflags glib-2.0)
+LDFLAGS := $(shell pkg-config --libs glib-2.0)
\ No newline at end of file
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 00000000..de2a9af1
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,6 @@
+include ../config.mk
+
+all: allocator.o
+
+%.o: %.c
+	gcc $(CFLAGS) -c -o $@ $^
\ No newline at end of file
diff --git a/lib/allocator.c b/lib/allocator.c
new file mode 100644
index 00000000..77f14ea3
--- /dev/null
+++ b/lib/allocator.c
@@ -0,0 +1,73 @@
+#include <glib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "allocator.h"
+
+struct arena_link {
+  // TODO:
+  // For efficiency, we should probably allocate the arena links in 
+  // their own slice, and link to a block directly. That can be
+  // implemented later, though, with no change in interface.
+  struct arena_link *next; // It is crucial that this be the first item; so that 
+                           // any arena link can be casted to struct arena_link**.
+
+  size_t free;
+  size_t used;
+  uint8_t rest[];
+} ;
+
+struct arena {
+  struct arena_link *head;
+  size_t block_size;
+};
+
+arena_t new_arena(size_t block_size) {
+  struct arena *ret = g_new(struct arena, 1);
+  struct arena_link *link = (struct arena_link*)g_malloc0(sizeof(struct arena_link) + block_size);
+  link->free = block_size;
+  link->used = 0;
+  link->next = NULL;
+  ret->head = link;
+  ret->block_size = 0;
+
+  return ret;
+}
+
+void* arena_malloc(arena_t arena, size_t size) {
+  if (size <= arena->head->free) {
+    // fast path..
+    void* ret = arena->head->rest + arena->head->used;
+    arena->head->used += size;
+    arena->head->free -= size;
+    return ret;
+  } else if (size > arena->block_size) {
+    // We need a new, dedicated block for it, because it won't fit in a standard sized one.
+    // This involves some annoying casting...
+    void* link = g_malloc(size + sizeof(struct arena_link*));
+    *(struct arena_link**)link = arena->head->next;
+    arena->head->next = (struct arena_link*)link;
+    return (void*)((uint8_t*)link + sizeof(struct arena_link*));
+  } else {
+    // we just need to allocate an ordinary new block.
+    struct arena_link *link = (struct arena_link*)g_malloc0(sizeof(struct arena_link) + arena->block_size);
+    link->free = arena->block_size - size;
+    link->used = size;
+    link->next = arena->head;
+    arena->head = link;
+    return link->rest;
+  }
+}
+    
+void delete_arena(arena_t arena) {
+  struct arena_link *link = arena->head;
+  while (link) {
+    struct arena_link *next = link->next; 
+    // Even in the case of a special block, without the full arena
+    // header, this is correct, because the next pointer is the first
+    // in the structure.
+    g_free(link);
+    link = next;
+  }
+  g_free(arena);
+}
diff --git a/lib/allocator.h b/lib/allocator.h
new file mode 100644
index 00000000..3cea5906
--- /dev/null
+++ b/lib/allocator.h
@@ -0,0 +1,12 @@
+#ifndef LIB_ALLOCATOR__H__
+#define LIB_ALLOCATOR__H__
+#include <sys/types.h>
+
+typedef struct arena* arena_t; // hidden implementation
+
+arena_t new_arena(size_t block_size); // pass 0 for default...
+void* arena_malloc(arena_t arena, size_t count); // TODO: needs the malloc attribute
+void delete_arena(arena_t arena);
+
+
+#endif // #ifndef LIB_ALLOCATOR__H__
-- 
GitLab