#include "salloc.h" #include #include #include struct spicy_allocation { size_t pagenum; size_t size; size_t *start; size_t *prev; }; struct spicy_page { uint8_t *start; uint8_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; memset(spicy_arena.c, 0 , spicy_arena.csize); } 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; if (spicy_arena.allocs == 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; } } } void sfreea() { if (spicy_arena.pages != NULL && spicy_arena.c != NULL) { for (size_t i = 0; i < spicy_arena.pagecount; i++) { free(spicy_arena.pages[i].start); } free(spicy_arena.c); spicy_arena.pagecount = 0; spicy_arena.pages = NULL; spicy_arena.allocs = NULL; } }