#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; }