aboutsummaryrefslogtreecommitdiff
path: root/lib/alloc/static_scratch_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/alloc/static_scratch_alloc.c')
-rw-r--r--lib/alloc/static_scratch_alloc.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/lib/alloc/static_scratch_alloc.c b/lib/alloc/static_scratch_alloc.c
new file mode 100644
index 0000000..2489b98
--- /dev/null
+++ b/lib/alloc/static_scratch_alloc.c
@@ -0,0 +1,44 @@
+#include <errno.h>
+#include <setjmp.h>
+#include <stdckdint.h>
+#include <stdint.h>
+
+#include "alloc.h"
+#include "errors.h"
+
+[[noreturn]] static void oom(jmp_buf *env);
+
+void *
+static_scratch_alloc(allocator_t mem, alloc_mode_t mode, void *,
+ ptrdiff_t, ptrdiff_t newnmemb, ptrdiff_t elemsz,
+ ptrdiff_t align)
+{
+ st_buf_t *ctx = mem.ctx;
+
+ switch (mode) {
+ case ALLOC_NEW:
+ case ALLOC_RESIZE:
+ ptrdiff_t pad, avail, total;
+ if (ckd_mul(&total, newnmemb, elemsz))
+ oom(mem.err);
+ pad = -(uintptr_t)ctx->buf & (align - 1);
+ avail = ctx->len - pad;
+ if (avail < 0 || total > avail)
+ oom(mem.err);
+ return (char *)ctx->buf + pad;
+ case ALLOC_FREE:
+ case ALLOC_FREEALL:
+ return nullptr;
+ default:
+ unreachable();
+ }
+}
+
+void
+oom(jmp_buf *env)
+{
+ errno = ENOMEM;
+ if (env != nullptr)
+ longjmp(*env, 1);
+ err("static_scratch_alloc:");
+}