summaryrefslogtreecommitdiff
path: root/libddekit/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libddekit/malloc.c')
-rw-r--r--libddekit/malloc.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/libddekit/malloc.c b/libddekit/malloc.c
new file mode 100644
index 00000000..5f0ae0fc
--- /dev/null
+++ b/libddekit/malloc.c
@@ -0,0 +1,94 @@
+/*
+ * \brief Simple allocator implementation
+ * \author Christian Helmuth
+ * \date 2006-10-30
+ *
+ * This simple allocator provides malloc() and free() using dm_mem dataspaces
+ * as backing store. The actual list-based allocator implementation is from
+ * l4util resp. Fiasco.
+ *
+ * For large allocations and slab-based OS-specific allocators
+ * ddekit_large_malloc and ddekit_slab_*() should be used. The blocks
+ * allocated via this allocator CANNOT be used for DMA or other device
+ * operations, i.e., there exists no virt->phys mapping.
+ *
+ * FIXME check thread-safety and add locks where appropriate
+ */
+
+#include <l4/dde/ddekit/memory.h>
+#include <l4/dde/ddekit/printf.h>
+#include <l4/dde/ddekit/panic.h>
+
+#include <l4/sys/consts.h>
+#include <l4/util/list_alloc.h>
+#include <l4/dm_mem/dm_mem.h>
+#include <l4/lock/lock.h>
+
+/* configuration */
+#define ALLOC_SIZE (4 * L4_PAGESIZE)
+
+/* malloc pool is a list allocator */
+static l4la_free_t *malloc_pool;
+static l4lock_t malloc_lock = L4LOCK_UNLOCKED;
+
+
+/**
+ * Allocate memory block via simple allocator
+ *
+ * \param size block size
+ * \return pointer to new memory block
+ *
+ * The blocks allocated via this allocator CANNOT be used for DMA or other
+ * device operations, i.e., there exists no virt->phys mapping.
+ *
+ * Each chunk stores its size in the first word for free() to work.
+ */
+void *ddekit_simple_malloc(unsigned size)
+{
+ l4lock_lock(&malloc_lock);
+ /* we store chunk size in the first word of the chunk */
+ size += sizeof(unsigned);
+
+ /* try to allocate */
+ unsigned *p = l4la_alloc(&malloc_pool, size, 0);
+
+ /* fill pool if allocation fails */
+ if (!p) {
+ /* size of allocated dataspace is at least ALLOC_SIZE */
+ unsigned ds_size = l4_round_page(size);
+ ds_size = (ds_size > ALLOC_SIZE) ? ds_size : ALLOC_SIZE;
+
+ void *res = l4dm_mem_allocate_named(ds_size, L4RM_MAP, "ddekit malloc");
+ if (!res)
+ p = NULL;
+ else
+ {
+ l4la_free(&malloc_pool, res, ds_size);
+ p = l4la_alloc(&malloc_pool, size, 0);
+ }
+ }
+
+ /* store chunk size */
+ if (p) {
+ *p = size;
+ p++;
+ }
+
+ l4lock_unlock(&malloc_lock);
+ return p;
+}
+
+
+/**
+ * Free memory block via simple allocator
+ *
+ * \param p pointer to memory block
+ */
+void ddekit_simple_free(void *p)
+{
+ l4lock_lock(&malloc_lock);
+ unsigned *chunk = (unsigned *)p - 1;
+ if (p)
+ l4la_free(&malloc_pool, chunk, *chunk);
+ l4lock_unlock(&malloc_lock);
+}