summaryrefslogtreecommitdiff
path: root/mem
diff options
context:
space:
mode:
authorAlejandro Sior <aho@sior.be>2022-07-23 22:53:47 +0200
committerAlejandro Sior <aho@sior.be>2022-07-23 22:53:47 +0200
commitef805e9373fd946bf1fe667bf18a54dfed6d1045 (patch)
tree7762f9574bbd56c502d4dbba1a9d5f3535035211 /mem
kernel: add basic modules: arch, mem, rt
Diffstat (limited to 'mem')
-rw-r--r--mem/README2
-rw-r--r--mem/allocator.c23
-rw-r--r--mem/allocator.h23
-rw-r--r--mem/framer.c63
-rw-r--r--mem/framer.h39
-rw-r--r--mem/meson.build8
6 files changed, 158 insertions, 0 deletions
diff --git a/mem/README b/mem/README
new file mode 100644
index 0000000..bb27b25
--- /dev/null
+++ b/mem/README
@@ -0,0 +1,2 @@
+The [mem] module maintains abstraction and facilities aiming
+to manipulate memory and allocators. \ No newline at end of file
diff --git a/mem/allocator.c b/mem/allocator.c
new file mode 100644
index 0000000..b4d9068
--- /dev/null
+++ b/mem/allocator.c
@@ -0,0 +1,23 @@
+#include "allocator.h"
+
+/* Dispatches the alloc call */
+void *mem_alloc(MemAllocator *self, usize n) {
+ if (self->alloc)
+ return self->alloc(self, n);
+
+ return nil;
+}
+
+/* Dispatches the realloc call */
+void *mem_realloc(MemAllocator *self, void *ptr, usize n) {
+ if (self->realloc)
+ return self->realloc(self, ptr, n);
+
+ return nil;
+}
+
+/* Dispatches the free call */
+void mem_free(MemAllocator *self, void *ptr) {
+ if (self->free)
+ self->free(self, ptr);
+} \ No newline at end of file
diff --git a/mem/allocator.h b/mem/allocator.h
new file mode 100644
index 0000000..535965a
--- /dev/null
+++ b/mem/allocator.h
@@ -0,0 +1,23 @@
+#ifndef MEM_ALLOCATOR_H
+#define MEM_ALLOCATOR_H
+
+#include <rt.h>
+
+typedef struct mem_allocator MemAllocator;
+
+typedef void *(*MemAlloc)(MemAllocator *, usize);
+typedef void *(*MemRealloc)(MemAllocator *, void *, usize);
+typedef void (*MemFree)(MemAllocator *, void *);
+
+/* Abstract object representing an allocator */
+struct mem_allocator {
+ MemAlloc alloc;
+ MemRealloc realloc;
+ MemFree free;
+};
+
+void *mem_alloc(MemAllocator *self, usize n);
+void *mem_realloc(MemAllocator *self, void *ptr, usize n);
+void mem_free(MemAllocator *self, void *ptr);
+
+#endif \ No newline at end of file
diff --git a/mem/framer.c b/mem/framer.c
new file mode 100644
index 0000000..9a66feb
--- /dev/null
+++ b/mem/framer.c
@@ -0,0 +1,63 @@
+#include "framer.h"
+
+/* Installs a MemFramer at the specified address */
+MemFramer *mem_framer_install(void *addr, usize end, uint blksz) {
+ MemFramer *self = addr;
+ usize selfend = (usize)(self + 1);
+ usize next = ALIGN_UP(selfend, blksz);
+
+ *self = (MemFramer) {
+ .allocator = (MemAllocator) {
+ .alloc = mem_framer_alloc,
+ .free = mem_framer_free
+ },
+ .next = next,
+ .end = end,
+ .blksz = blksz
+ };
+
+ return self;
+}
+
+/* Allocates a frame */
+void *mem_framer_alloc(MemAllocator *inner, usize n) {
+ /* When allocating a frame, we have two paths:
+ 1. The freelist is not empty: give away
+ the last freed frame
+ 2. The freelist is empty: bump away the next
+ frame (pointed at by the next member)
+ The alloc must fail the freelist is empty and that
+ the next is beyond the end of the region */
+
+ MemFramer *self = (MemFramer*)inner;
+
+ /* The implementation does not support more than
+ one frame */
+ if (n == 0 || n > self->blksz)
+ return nil;
+
+ void *ptr = nil;
+
+ if (self->free) {
+ ptr = self->free;
+ self->free = self->free->next;
+ } else if (self->next + self->blksz <= self->end) {
+ ptr = (void*)self->next;
+ self->next += self->blksz;
+ }
+
+ return ptr;
+}
+
+/* Frees a frame */
+void mem_framer_free(MemAllocator *inner, void *ptr) {
+ /* NOTE: this implementation does make the assumption
+ that the given pointer is the base of the allocated
+ region without correction */
+
+ MemFramer *self = (MemFramer*)inner;
+
+ MemFramerFreed *freed = ptr;
+ freed->next = self->free;
+ self->free = freed;
+} \ No newline at end of file
diff --git a/mem/framer.h b/mem/framer.h
new file mode 100644
index 0000000..6d7034b
--- /dev/null
+++ b/mem/framer.h
@@ -0,0 +1,39 @@
+#ifndef MEM_FRAMER_H
+#define MEM_FRAMER_H
+
+#include <rt.h>
+
+#include "allocator.h"
+
+typedef struct mem_framer_freed {
+ struct mem_framer_freed *next;
+} MemFramerFreed;
+
+/* Allocator for frames: aligned regions of memory of same size */
+typedef struct mem_framer {
+ MemAllocator allocator;
+
+ /* The next frame to be given off to the caller
+ in case the freelist is empty */
+ usize next;
+
+ /* The end of the region covered by the memory allocator */
+ usize end;
+
+ /* The address of the last frame that has been added in
+ the freelist
+ NOTE: the freelist is a singly-linked list comprising
+ all frames that have been previously allocated
+ and then freed */
+ MemFramerFreed *free;
+
+ /* The size of a frame. This value also defines the alignment
+ that the frames must respect */
+ uint blksz;
+} MemFramer;
+
+MemFramer *mem_framer_install(void *addr, usize end, uint blksz);
+void *mem_framer_alloc(MemAllocator *self, usize n);
+void mem_framer_free(MemAllocator *self, void *ptr);
+
+#endif \ No newline at end of file
diff --git a/mem/meson.build b/mem/meson.build
new file mode 100644
index 0000000..ec4a984
--- /dev/null
+++ b/mem/meson.build
@@ -0,0 +1,8 @@
+mem_src = [
+ 'allocator.c',
+ 'framer.c'
+]
+
+mem = static_library('mem', mem_src, include_directories: kernel_inc)
+
+kernel_mod += mem \ No newline at end of file