summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2026-05-04 12:58:31 +0800
committerSadeep Madurange <sadeep@asciimx.com>2026-05-04 17:42:39 +0800
commite786c2e12add1aa3078cba4c367764e4252748e9 (patch)
tree07461ccfd8cab329ce779d989bc712a2300da537
downloadweb-view-e786c2e12add1aa3078cba4c367764e4252748e9.tar.gz
Defined arena for memory management.
-rw-r--r--.gitignore3
-rw-r--r--wv_err.h38
-rw-r--r--wv_mem.c94
-rw-r--r--wv_mem.h27
4 files changed, 162 insertions, 0 deletions
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 <err.h>
+#else
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+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 <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#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 <stddef.h>
+#include <stdint.h>
+
+/* 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 */