commit ad46289a0cad4fb6b5af97ed07bff46bea3408e6
parent 6cc1c83e9d4bfd4834b2449147443ff85a467647
Author: Louis Burda <quent.burda@gmail.com>
Date: Fri, 15 Mar 2024 22:52:28 +0100
Merge commit 'edbd9752c787098c55401f8241b3aa03564765a3' as 'src/lib/liballoc'
Diffstat:
11 files changed, 350 insertions(+), 0 deletions(-)
diff --git a/src/lib/liballoc/.gitignore b/src/lib/liballoc/.gitignore
@@ -0,0 +1,7 @@
+compile_commands.json
+build
+build.jst
+.cache
+vgcore*
+.gdb_history
+test
diff --git a/src/lib/liballoc/LICENSE b/src/lib/liballoc/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Louis Burda
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/lib/liballoc/Makefile b/src/lib/liballoc/Makefile
@@ -0,0 +1,45 @@
+PREFIX ?= /usr/local
+LIBDIR ?= /lib
+INCLDIR ?= /include
+
+CFLAGS = -I include
+
+ifeq "$(DEBUG)" "1"
+CFLAGS += -Og -g
+else
+CFLAGS += -O2
+endif
+
+all: build/liballoc.so build/liballoc.a build/test
+
+clean:
+ rm -rf build
+
+cleanall: clean
+
+build:
+ mkdir build
+
+build/liballoc.a: src/allocator.c | build
+ $(CC) -o build/tmp.o src/allocator.c $(CFLAGS) -r
+ objcopy --keep-global-symbols=liballoc.api build/tmp.o build/fixed.o
+ ar rcs $@ build/fixed.o
+
+build/liballoc.so: src/allocator.c include/allocator.h | build
+ $(CC) -o $@ src/allocator.c $(CFLAGS) \
+ -shared -Wl,-version-script liballoc.lds
+
+build/test: src/test.c build/liballoc.a | build
+ $(CC) -o $@ $^ -I include
+
+install:
+ install -m755 include/allocator.h -t "$(DESTDIR)$(PREFIX)$(INCLDIR)"
+ install -m755 build/liballoc.a -t "$(DESTDIR)$(PREFIX)$(LIBDIR)"
+ install -m755 build/liballoc.so -t "$(DESTDIR)$(PREFIX)$(LIBDIR)"
+
+uninstall:
+ rm -f "$(DESTDIR)$(PREFIX)$(INCLDIR)/allocator.h"
+ rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/liballoc.a"
+ rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/liballoc.so"
+
+.PHONY: all clean cleanall install uninstall
diff --git a/src/lib/liballoc/build.jst.tmpl b/src/lib/liballoc/build.jst.tmpl
@@ -0,0 +1,60 @@
+#default PREFIX /usr/local
+#default INCLDIR /include
+#default LIBDIR /lib
+#default CC gcc
+
+#ifdef DEBUG
+#define OPT_CFLAGS -Og -g
+#else
+#define OPT_CFLAGS -O2
+#endif
+
+cflags = -Wunused-function -Wunused-variable -Wconversion -Wformat
+ -I include #{OPT_CFLAGS} #{EXTRA_CFLAGS}
+
+rule liba
+ gcc -o $out.tmp.o $in $cflags -r
+ objcopy --keep-global-symbols=liballoc.api $out.tmp.o $out.fixed.o
+ ar rcs $out $out.fixed.o
+ rm $out.tmp.o $out.fixed.o
+
+rule libso
+ gcc -o $out $in $cflags -shared -Wl,-version-script liballoc.lds
+
+rule cc
+ gcc -o $out $in $cflags
+
+rule mkdir
+ mkdir $out
+
+target build
+ mkdir
+
+target build/liballoc.a
+ liba src/allocator.c | include/allocator.h build
+
+target build/liballoc.so
+ libso src/allocator.c | include/allocator.h build
+
+target build/test
+ cc src/test.c build/liballoc.a | build
+
+command clean
+ rm -rf build
+
+command cleanall
+ just clean
+
+command install
+ install -m755 build/liballoc.a -t "#{DESTDIR}#{PREFIX}#{LIBDIR}"
+ install -m755 build/liballoc.so -t "#{DESTDIR}#{PREFIX}#{LIBDIR}"
+ install -m644 include/allocator.h -t "#{DESTDIR}#{PREFIX}#{INCLDIR}"
+
+command uninstall
+ rm -f "#{DESTDIR}#{PREFIX}#{LIBDIR}/liballoc.a"
+ rm -f "#{DESTDIR}#{PREFIX}#{LIBDIR}/liballoc.so"
+ rm -f "#{DESTDIR}#{PREFIX}#{INCLDIR}/allocator.h"
+
+command all
+ just build/liballoc.a build/liballoc.so build/test
+
diff --git a/src/lib/liballoc/common.mk b/src/lib/liballoc/common.mk
@@ -0,0 +1,9 @@
+LIBALLOC_A = build/liballoc.a
+LIBALLOC_A_SRC = src/allocator.c
+LIBALLOC_A_DEP = $(LIBALLOC_A_SRC) include/allocator.h
+LIBALLOC_A_SRCDEP = $(LIBALLOC_A_DEP)
+
+LIBALLOC_SO = build/liballoc.so
+LIBALLOC_SO_SRC = src/allocator.c
+LIBALLOC_SO_DEP = $(LIBALLOC_SO_SRC) include/allocator.h
+LIBALLOC_SO_SRCDEP = $(LIBALLOC_SO_DEP)
diff --git a/src/lib/liballoc/configure b/src/lib/liballoc/configure
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+tmpl "$@" build.jst.tmpl > build.jst
diff --git a/src/lib/liballoc/include/allocator.h b/src/lib/liballoc/include/allocator.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <stddef.h>
+
+struct allocator {
+ void *(*alloc)(const struct allocator *allocator,
+ size_t size, int *rc);
+ void *(*realloc)(const struct allocator *allocator,
+ void *p, size_t size, int *rc);
+ int (*free)(const struct allocator *allocator, void *p);
+};
+
+struct strict_allocator {
+ const struct allocator *allocator_ul;
+ struct allocator allocator;
+};
+
+void strict_allocator_init(struct strict_allocator *strict_allocator_init,
+ const struct allocator *allocator_ul);
+
+extern const struct allocator stdlib_heap_allocator;
+extern const struct allocator stdlib_strict_heap_allocator;
diff --git a/src/lib/liballoc/liballoc.api b/src/lib/liballoc/liballoc.api
@@ -0,0 +1,4 @@
+strict_allocator_init
+
+stdlib_heap_allocator
+stdlib_strict_heap_allocator
diff --git a/src/lib/liballoc/liballoc.lds b/src/lib/liballoc/liballoc.lds
@@ -0,0 +1,7 @@
+LIBALLOC_2.1 {
+ global:
+ strict_allocator_init;
+ stdlib_heap_allocator;
+ stdlib_strict_heap_allocator;
+ local: *;
+};
diff --git a/src/lib/liballoc/src/allocator.c b/src/lib/liballoc/src/allocator.c
@@ -0,0 +1,150 @@
+#include "allocator.h"
+
+#include <errno.h>
+#include <stdlib.h>
+
+static void *stdlib_heap_alloc(const struct allocator *allocator,
+ size_t size, int *rc);
+static void *stdlib_heap_realloc(const struct allocator *allocator,
+ void *p, size_t size, int *rc);
+static int stdlib_heap_free(const struct allocator *allocator, void *p);
+
+static void *stdlib_strict_heap_alloc(const struct allocator *allocator,
+ size_t size, int *rc);
+static void *stdlib_strict_heap_realloc(const struct allocator *allocator,
+ void *p, size_t size, int *rc);
+static int stdlib_strict_heap_free(const struct allocator *allocator, void *p);
+
+const struct allocator stdlib_heap_allocator = {
+ .alloc = stdlib_heap_alloc,
+ .realloc = stdlib_heap_realloc,
+ .free = stdlib_heap_free
+};
+
+const struct allocator stdlib_strict_heap_allocator = {
+ .alloc = stdlib_strict_heap_alloc,
+ .realloc = stdlib_strict_heap_realloc,
+ .free = stdlib_strict_heap_free
+};
+
+void *
+stdlib_heap_alloc(const struct allocator *allocator, size_t size, int *rc)
+{
+ void *p;
+
+ p = malloc(size);
+ if (rc && !p) *rc = errno;
+
+ return p;
+}
+
+void *
+stdlib_heap_realloc(const struct allocator *allocator,
+ void *p, size_t size, int *rc)
+{
+ void *np;
+
+ np = realloc(p, size);
+ if (rc && !np) *rc = errno;
+
+ return np;
+}
+
+int
+stdlib_heap_free(const struct allocator *allocator, void *p)
+{
+ free(p);
+
+ return 0;
+}
+
+void *
+stdlib_strict_heap_alloc(const struct allocator *allocator,
+ size_t size, int *rc)
+{
+ void *p;
+
+ p = malloc(size);
+ if (!p) abort();
+
+ return p;
+}
+
+void *
+stdlib_strict_heap_realloc(const struct allocator *allocator,
+ void *p, size_t size, int *rc)
+{
+ void *np;
+
+ np = realloc(p, size);
+ if (!np) abort();
+
+ return np;
+}
+
+int
+stdlib_strict_heap_free(const struct allocator *allocator, void *p)
+{
+ free(p);
+
+ return 0;
+}
+
+void *
+strict_allocator_alloc(const struct allocator *allocator, size_t size, int *rc)
+{
+ const struct strict_allocator *strict_allocator;
+ void *p;
+
+ strict_allocator = ((void *) allocator)
+ - offsetof(struct strict_allocator, allocator);
+
+ p = strict_allocator->allocator_ul->alloc(
+ strict_allocator->allocator_ul, size, rc);
+ if (!p) abort();
+
+ return p;
+}
+
+void *
+strict_allocator_realloc(const struct allocator *allocator,
+ void *p, size_t size, int *rc)
+{
+ const struct strict_allocator *strict_allocator;
+ void *np;
+
+ strict_allocator = ((void *) allocator)
+ - offsetof(struct strict_allocator, allocator);
+
+ np = strict_allocator->allocator_ul->realloc(
+ strict_allocator->allocator_ul, p, size, rc);
+ if (!np) abort();
+
+ return np;
+}
+
+int
+strict_allocator_free(const struct allocator *allocator, void *p)
+{
+ const struct strict_allocator *strict_allocator;
+ int rc;
+
+ strict_allocator = ((void *) allocator)
+ - offsetof(struct strict_allocator, allocator);
+
+ rc = strict_allocator->allocator_ul->free(
+ strict_allocator->allocator_ul, p);
+ if (rc) abort();
+
+ return 0;
+}
+
+void
+strict_allocator_init(struct strict_allocator *strict_allocator,
+ const struct allocator *allocator_ul)
+{
+ strict_allocator->allocator_ul = allocator_ul;
+ strict_allocator->allocator.alloc = strict_allocator_alloc;
+ strict_allocator->allocator.realloc = strict_allocator_realloc;
+ strict_allocator->allocator.free = strict_allocator_free;
+}
diff --git a/src/lib/liballoc/src/test.c b/src/lib/liballoc/src/test.c
@@ -0,0 +1,22 @@
+#include "allocator.h"
+
+#include <err.h>
+#include <string.h>
+#include <stdlib.h>
+
+const struct allocator *ga = &stdlib_heap_allocator;
+
+int
+main(int argc, const char **argv)
+{
+ struct test *test;
+ int rc;
+
+ if (argc <= 1) exit(1);
+
+ test = ga->alloc(ga, strtoull(argv[1], NULL, 10), &rc);
+ if (!test) errx(1, "alloc: %s", strerror(rc));
+
+ rc = ga->free(ga, test);
+ if (rc) errx(1, "free: %s", strerror(rc));
+}