From e786c2e12add1aa3078cba4c367764e4252748e9 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Mon, 4 May 2026 12:58:31 +0800 Subject: Defined arena for memory management. --- .gitignore | 3 ++ wv_err.h | 38 +++++++++++++++++++++++++ wv_mem.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wv_mem.h | 27 ++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 .gitignore create mode 100644 wv_err.h create mode 100644 wv_mem.c create mode 100644 wv_mem.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0b8288 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**/*a.out +**/*.swp +**/*.core diff --git a/wv_err.h b/wv_err.h new file mode 100644 index 0000000..43d5f84 --- /dev/null +++ b/wv_err.h @@ -0,0 +1,38 @@ +#ifndef WV_ERR_H +#define WV_ERR_H + +#ifdef __OpenBSD__ +#include +#else +#include +#include +#include +#include +#include + +static void err(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "wv: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": %s\n", strerror(errno)); + va_end(ap); + exit(eval); +} + +static void errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "wv: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(eval); +} +#endif /* !__OpenBSD__ */ + +#endif /* WV_ERR_H */ diff --git a/wv_mem.c b/wv_mem.c new file mode 100644 index 0000000..0bb32dc --- /dev/null +++ b/wv_mem.c @@ -0,0 +1,94 @@ +#include +#include +#include + +#include "wv_mem.h" +#include "wv_err.h" + +/* Detect alignment pre-C11 */ +union wv_max_align { long l; double d; void *p; }; + +#define WV_ALIGNOF(type) offsetof(struct { char c; type member; }, member) +#define WV_ALIGNMENT WV_ALIGNOF(union wv_max_align) +#define WV_ALIGN_MASK (WV_ALIGNMENT - 1) + +#define WV_ARENA_MIN_SIZE (256 * 1024) +#define WV_ARENA_RESERVED WV_ALIGNMENT /* Reserve 0 as the sentinel "null" ref */ + +struct wv_arena *wv_arena_create(size_t n) +{ + struct wv_arena *arena; + + if (n < WV_ARENA_MIN_SIZE) + n = WV_ARENA_MIN_SIZE; + + arena = malloc(sizeof(struct wv_arena)); + if (arena == NULL) + err(1, "malloc arena struct"); + + arena->buf = malloc(n); + if (arena->buf == NULL) + err(1, "malloc arena buffer"); + + arena->size = n; + arena->offset = WV_ARENA_RESERVED; + + return arena; +} + +wv_ref wv_alloc(struct wv_arena *arena, size_t n) +{ + wv_ref ref; + unsigned char *new_buf; + size_t aligned_n, new_size; + + if (n == 0) + errx(1, "wv_alloc: zero-size allocation"); + + if (n > SIZE_MAX - WV_ALIGN_MASK) + errx(1, "wv_alloc: allocation size overflow"); + + aligned_n = (n + WV_ALIGN_MASK) & ~WV_ALIGN_MASK; + + if (aligned_n > SIZE_MAX - arena->offset) + errx(1, "wv_alloc: arena offset overflow"); + + if (arena->offset + aligned_n > arena->size) { + new_size = arena->size; + while (new_size < arena->offset + aligned_n) { + if (new_size > SIZE_MAX / 2) + errx(1, "wv_alloc: arena growth overflow"); + new_size *= 2; + } + + new_buf = realloc(arena->buf, new_size); + if (new_buf == NULL) + err(1, "realloc arena failed at %zu bytes", new_size); + + arena->buf = new_buf; + arena->size = new_size; + } + + ref = (wv_ref)arena->offset; + arena->offset += aligned_n; + return ref; +} + +void wv_arena_reset(struct wv_arena *arena) +{ + if (arena == NULL) + return; + + memset(arena->buf, 0, arena->offset); + arena->offset = WV_ARENA_RESERVED; +} + +void wv_arena_destroy(struct wv_arena *arena) +{ + if (arena == NULL) + return; + + free(arena->buf); + free(arena); +} + diff --git a/wv_mem.h b/wv_mem.h new file mode 100644 index 0000000..9d23ae8 --- /dev/null +++ b/wv_mem.h @@ -0,0 +1,27 @@ +#ifndef WV_MEM_H +#define WV_MEM_H + +#include +#include + +/* Relative offset into the arena */ +typedef uint32_t wv_ref; + +/* 0 is our 'NULL' */ +#define WV_REF_NULL 0 + +/* Resolve a ref into a memory address */ +#define WV_ADDR(arena, ref) ((void *)((arena)->buf + (ref))) + +struct wv_arena { + size_t size; + size_t offset; + unsigned char *buf; +}; + +struct wv_arena* wv_arena_create(size_t n); +wv_ref wv_alloc(struct wv_arena *arena, size_t n); +void wv_arena_reset(struct wv_arena *arena); +void wv_arena_destroy(struct wv_arena *arena); + +#endif /* WV_MEM_H */ -- cgit v1.2.3