From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- src/base/mem/arena.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++ src/base/mem/buffer.c | 45 ++++++++++++++++++ src/base/mem/interface.c | 36 ++++++++++++++ src/base/mem/internal.h | 4 ++ src/base/mem/rules.mk | 5 ++ src/base/mem/set64.c | 13 ++++++ 6 files changed, 222 insertions(+) create mode 100644 src/base/mem/arena.c create mode 100644 src/base/mem/buffer.c create mode 100644 src/base/mem/interface.c create mode 100644 src/base/mem/internal.h create mode 100644 src/base/mem/rules.mk create mode 100644 src/base/mem/set64.c (limited to 'src/base/mem') diff --git a/src/base/mem/arena.c b/src/base/mem/arena.c new file mode 100644 index 0000000..b2ce044 --- /dev/null +++ b/src/base/mem/arena.c @@ -0,0 +1,119 @@ +#include "internal.h" + +#define ARENA_ALIGN 8 +#define ARENA_BLOCK_SIZE 1024 * 1024 + +#define ALIGN_DOWN(n, a) ((n) & ~((a)-1)) +#define ALIGN_UP(n, a) ALIGN_DOWN((n) + (a)-1, (a)) +#define ALIGN_DOWN_PTR(p, a) ((void*)ALIGN_DOWN((uintptr)(p), (a))) +#define ALIGN_UP_PTR(p, a) ((void*)ALIGN_UP((uintptr)(p), (a))) + +struct Block +{ + struct Block *next; + byte buf[]; +}; + +struct mem·Arena +{ + void *heap; + mem·Allocator mem; + + byte *off; + byte *end; + struct Block *curr; + struct Block first; +}; + +static +void* +·arenaalloc(void *heap, uint n, ulong size) +{ + return mem·arenaalloc(heap, n, size); +} + +static +void +·arenafree(void *heap, void *ptr) +{ + /* no-op */ +} + +mem·Allocator mem·ArenaAllocator = { + .alloc = ·arenaalloc, + .free = ·arenafree, +}; + + +static +void +grow(mem·Arena *a, vlong min) +{ + uintptr size; + struct Block *blk; + + size = ALIGN_UP(MAX(min, ARENA_BLOCK_SIZE), ARENA_ALIGN); + blk = a->mem.alloc(a->heap, 1, sizeof(*blk) + size); + a->off = blk->buf; + a->end = a->off + size; + + assert(a->curr->next == nil); + assert(a->off == ALIGN_DOWN_PTR(a->off, ARENA_ALIGN)); + + a->curr->next = blk; + a->curr = blk; +} + +mem·Arena* +mem·makearena(mem·Allocator from, void *impl) +{ + mem·Arena *a = from.alloc(impl, 1, sizeof(*a) + ARENA_BLOCK_SIZE); + a->mem = from; + a->heap = impl; + a->off = a->first.buf; + a->end = a->first.buf + ARENA_BLOCK_SIZE; + a->curr = &a->first; + a->first.next = nil; + + return a; +} + +void +mem·freearena(mem·Arena *a) +{ + struct Block *it, *next; + + it = a->first.next; + while (it != nil) { + next = it->next; + a->mem.free(a->heap, it); + it = next; + } + + a->mem.free(a->heap, a); +} + +void* +mem·arenaalloc(mem·Arena *a, uint n, ulong size) +{ + if(!n) { + return nil; + } + + void *ptr; + // TODO(nnoll): check for overflow + size = n * size; + + if (size > (ulong)(a->end - a->off)) { + grow(a, size); + assert(size <= (uintptr)(a->end - a->off)); + } + + ptr = a->off; + a->off = ALIGN_UP_PTR(a->off + size, ARENA_ALIGN); + + assert(a->off <= a->end); + assert(ptr == ALIGN_DOWN_PTR(ptr, ARENA_ALIGN)); + + return ptr; +} diff --git a/src/base/mem/buffer.c b/src/base/mem/buffer.c new file mode 100644 index 0000000..b684d35 --- /dev/null +++ b/src/base/mem/buffer.c @@ -0,0 +1,45 @@ +#include "internal.h" + +/* Grow to particular size */ +void* +·bufgrow(void* buf, vlong newLen, vlong eltsize) +{ + assert(bufcap(buf) <= (SIZE_MAX - 1) / 2); + + vlong newCap = MAX(16, MAX(1 + 2 * bufcap(buf), newLen)); + + assert(newLen <= newCap); + assert(newCap <= (SIZE_MAX - offsetof(BufHdr, buf)) / eltsize); + + vlong newSize = offsetof(BufHdr, buf) + newCap * eltsize; + + BufHdr* newHdr; + if (buf) { + newHdr = bufhdr(buf); + newHdr = (BufHdr*)realloc((void*)newHdr, newSize); + } else { + newHdr = (BufHdr*)malloc(newSize); + newHdr->len = 0; + } + + newHdr->cap = newCap; + return (void*)newHdr->buf; +} + +/* Pop out a value */ +void +·bufdel(void *buf, int i, vlong eltsize) +{ + int n; + byte *b; + byte stk[1024]; + assert(eltsize < sizeof(stk)); + + b = (byte*)buf; + if(n = buflen(buf), i < n) { + memcpy(stk, b+eltsize*i, eltsize); + memcpy(b+eltsize*i, b+eltsize*(i+1), eltsize*(n-i-1)); + memcpy(b+eltsize*(n-1), stk, eltsize); + } + bufhdr(buf)->len--; +} diff --git a/src/base/mem/interface.c b/src/base/mem/interface.c new file mode 100644 index 0000000..4d7d1ce --- /dev/null +++ b/src/base/mem/interface.c @@ -0,0 +1,36 @@ +#include "internal.h" + +static +void +·free(void *_, void *ptr) { + return free(ptr); +} + +static +void * +·alloc(void *_, uint n, ulong size) { + return malloc(n*size); +} + +static +void * +·calloc(void *_, uint n, ulong size) { + return calloc(n, size); +} + +static +void * +·realloc(void *_, void *ptr, uint n, ulong size) { + return realloc(ptr, n*size); +} + +mem·Allocator sys·Memory = { + .alloc = ·calloc, + .free = ·free +}; + +mem·Reallocator sys·FullMemory = { + .alloc = ·calloc, + .realloc = ·realloc, + .free = ·free +}; diff --git a/src/base/mem/internal.h b/src/base/mem/internal.h new file mode 100644 index 0000000..302c035 --- /dev/null +++ b/src/base/mem/internal.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/src/base/mem/rules.mk b/src/base/mem/rules.mk new file mode 100644 index 0000000..b912d0c --- /dev/null +++ b/src/base/mem/rules.mk @@ -0,0 +1,5 @@ +SRCS_$(d)+=\ + $(d)/mem/arena.c\ + $(d)/mem/buffer.c\ + $(d)/mem/interface.c\ + $(d)/mem/set64.c\ diff --git a/src/base/mem/set64.c b/src/base/mem/set64.c new file mode 100644 index 0000000..464b3ad --- /dev/null +++ b/src/base/mem/set64.c @@ -0,0 +1,13 @@ +#include "internal.h" + +void +mem·set64(void *dst, uint64 val, uintptr size) +{ + intptr i; + + for(i = 0; i < (size & (~7)); i += 8) + memcpy((byte*)dst + i, &val, 8); + + for(; i < size; i++) + ((byte*)dst)[i] = ((byte*)&val)[i&7]; +} -- cgit v1.2.1