diff options
| author | Alejandro Sior <aho@sior.be> | 2022-07-23 22:53:47 +0200 |
|---|---|---|
| committer | Alejandro Sior <aho@sior.be> | 2022-07-23 22:53:47 +0200 |
| commit | ef805e9373fd946bf1fe667bf18a54dfed6d1045 (patch) | |
| tree | 7762f9574bbd56c502d4dbba1a9d5f3535035211 /mem | |
kernel: add basic modules: arch, mem, rt
Diffstat (limited to 'mem')
| -rw-r--r-- | mem/README | 2 | ||||
| -rw-r--r-- | mem/allocator.c | 23 | ||||
| -rw-r--r-- | mem/allocator.h | 23 | ||||
| -rw-r--r-- | mem/framer.c | 63 | ||||
| -rw-r--r-- | mem/framer.h | 39 | ||||
| -rw-r--r-- | mem/meson.build | 8 |
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 |
