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