arena: add __arena_create() and __arena_destroy()
These are lower level interfaces where the caller handles memory. If
you want any half-way usable self-sourced arena, you're going to embed
it in another struct, and container_of() to that struct in the arena
alloc/free funcs.
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/include/arena.h b/kern/include/arena.h
index 0f49c74..1c35c9f 100644
--- a/kern/include/arena.h
+++ b/kern/include/arena.h
@@ -104,6 +104,12 @@
/* Adds segment [@base, @base + @size) to @arena. */
void *arena_add(struct arena *arena, void *base, size_t size, int flags);
void arena_destroy(struct arena *arena);
+/* Lower-level create/destroy interface; caller manages the memory */
+void __arena_create(struct arena *arena, const char *name, size_t quantum,
+ void *(*afunc)(struct arena *, size_t, int),
+ void (*ffunc)(struct arena *, void *, size_t),
+ struct arena *source, size_t qcache_max);
+void __arena_destroy(struct arena *arena);
void *arena_alloc(struct arena *arena, size_t size, int flags);
void arena_free(struct arena *arena, void *addr, size_t size);
diff --git a/kern/src/arena.c b/kern/src/arena.c
index c23ac41..75d7cd6 100644
--- a/kern/src/arena.c
+++ b/kern/src/arena.c
@@ -182,10 +182,10 @@
arena->qcaches = NULL;
}
-static void arena_init(struct arena *arena, const char *name, size_t quantum,
- void *(*afunc)(struct arena *, size_t, int),
- void (*ffunc)(struct arena *, void *, size_t),
- struct arena *source, size_t qcache_max)
+void __arena_create(struct arena *arena, const char *name, size_t quantum,
+ void *(*afunc)(struct arena *, size_t, int),
+ void (*ffunc)(struct arena *, void *, size_t),
+ struct arena *source, size_t qcache_max)
{
static_assert((ARENA_ALLOC_STYLES & MEM_FLAGS) == 0);
@@ -262,7 +262,7 @@
arena = kmalloc(sizeof(struct arena), flags);
if (!arena)
return 0;
- arena_init(arena, name, quantum, afunc, ffunc, source, qcache_max);
+ __arena_create(arena, name, quantum, afunc, ffunc, source, qcache_max);
if (base) {
if (!arena_add(arena, base, size, flags)) {
warn("Failed to add base to arena %s, aborting!",
@@ -290,7 +290,7 @@
return false;
}
-void arena_destroy(struct arena *arena)
+void __arena_destroy(struct arena *arena)
{
struct btag *bt_i, *temp;
@@ -339,6 +339,11 @@
/* Now the remaining BTs are the first on their page. */
BSD_LIST_FOREACH_SAFE(bt_i, &arena->unused_btags, misc_link, temp)
arena_free(find_my_base(arena), bt_i, PGSIZE);
+}
+
+void arena_destroy(struct arena *arena)
+{
+ __arena_destroy(arena);
kfree(arena);
}
@@ -1397,7 +1402,7 @@
static_assert(sizeof(struct arena) + 2 * sizeof(struct btag) <= PGSIZE);
- arena_init(a, name, quantum, afunc, ffunc, source, qcache_max);
+ __arena_create(a, name, quantum, afunc, ffunc, source, qcache_max);
if (!source)
a->is_base = TRUE;
BSD_LIST_INSERT_HEAD(&a->unused_btags, &two_tags[0], misc_link);