diff options
Diffstat (limited to 'src/salloc.c')
-rw-r--r-- | src/salloc.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/salloc.c b/src/salloc.c new file mode 100644 index 0000000..6c20b41 --- /dev/null +++ b/src/salloc.c @@ -0,0 +1,115 @@ +#include "salloc.h" + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +struct spicy_allocation { + size_t pagenum; + size_t size; + size_t *start; + size_t *prev; +}; + +struct spicy_page { + size_t *start; + size_t *current; + size_t free; +}; + +static struct { + size_t pagecount; + size_t pagesize; + size_t *c; + size_t max_pages; + size_t max_allocs; + size_t csize; + struct spicy_page *pages; + struct spicy_allocation *allocs; +} spicy_arena = { + .pagecount = 0, + .pagesize = 10240, + .c = NULL, + .max_pages = 1024, + .max_allocs = 10240, + .csize = (1024 * sizeof(struct spicy_page)) + (1024 * sizeof(struct spicy_allocation)), + .pages = NULL, + .allocs = NULL +}; + +int salloc_configure(size_t pagesize, size_t max_pages, size_t max_allocs) { + if (spicy_arena.c != NULL) return -1; // allocator already used! + spicy_arena.pagesize = pagesize; + spicy_arena.max_pages = max_pages; + spicy_arena.max_allocs = max_allocs; + spicy_arena.csize = max_pages + max_allocs; + return 0; +} + +void *salloc(size_t size) { + if (spicy_arena.c == NULL) { + spicy_arena.c = malloc(spicy_arena.csize); + if (spicy_arena.c == NULL) return NULL; + } + if (spicy_arena.pages == NULL) { + spicy_arena.pages = (struct spicy_page *)spicy_arena.c; + } + if (spicy_arena.allocs == NULL) { + spicy_arena.allocs = (struct spicy_allocation *)(spicy_arena.c + (spicy_arena.max_pages * sizeof(struct spicy_page))); + } + if (spicy_arena.pagecount == 0) { + spicy_arena.pages[0].start = malloc(spicy_arena.pagesize); + if (spicy_arena.pages[0].start == NULL) return NULL; + spicy_arena.pages[0].current = spicy_arena.pages[0].start; + spicy_arena.pages[0].free = spicy_arena.pagesize; + spicy_arena.pagecount++; + } + // This is inefficient! + for (size_t i = 0; i < spicy_arena.max_allocs; i++) { + if (spicy_arena.allocs[i].start == NULL) { + if (spicy_arena.allocs[i].size >= size) { + spicy_arena.allocs[i].start = spicy_arena.allocs[i].prev; + return (void *)spicy_arena.allocs[i].start; + } + if (spicy_arena.allocs[i].size == 0) { + for (size_t x = 0; x < spicy_arena.pagecount; x++) { + if (spicy_arena.pages[x].free >= size) { + void *ret = spicy_arena.pages[x].current; + spicy_arena.pages[x].current += size; + spicy_arena.pages[x].free -= size; + return ret; + } + } + spicy_arena.pages[spicy_arena.pagecount].start = malloc(spicy_arena.pagesize); + if (spicy_arena.pages[spicy_arena.pagecount].start == NULL) return NULL; + void *ret = spicy_arena.pages[spicy_arena.pagecount].start; + spicy_arena.pages[spicy_arena.pagecount].current = spicy_arena.pages[spicy_arena.pagecount].start + size; + spicy_arena.pages[spicy_arena.pagecount].free = spicy_arena.pagesize - size; + spicy_arena.pagecount++; + return ret; + } + } + } + return NULL; +} + +void *scalloc(size_t count, size_t size) { + void *ret = salloc(count * size); + if (ret != NULL) { + memset(ret, 0, count * size); + return ret; + } + return NULL; +} + +void sfree(void *ptr) { + if (ptr == NULL) return; + for (size_t i = 0; i < spicy_arena.max_allocs; i++) { + if (ptr == spicy_arena.allocs[i].start) { + spicy_arena.allocs[i].prev = spicy_arena.allocs[i].start; + spicy_arena.allocs[i].start = NULL; + ptr = NULL; + } + } +} + |