summaryrefslogtreecommitdiff
path: root/archive/Podium/p_allocators.c
diff options
context:
space:
mode:
authorVasco <[email protected]>2026-08-24 00:56:24 +0100
committerVasco <[email protected]>2026-08-24 00:56:24 +0100
commit5dc2716abd43166cd65133625f408ad36a6623b3 (patch)
tree19d89b838206b6bb11cc0b9f88311d855999d447 /archive/Podium/p_allocators.c
parentdc96fcd771bea09d726a760266739906e95c09a6 (diff)
Peak 0.4.0 and Draw
Diffstat (limited to 'archive/Podium/p_allocators.c')
-rw-r--r--archive/Podium/p_allocators.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/archive/Podium/p_allocators.c b/archive/Podium/p_allocators.c
new file mode 100644
index 0000000..7e59807
--- /dev/null
+++ b/archive/Podium/p_allocators.c
@@ -0,0 +1,301 @@
+PODEF bool
+is_power_of_two(uintptr x) {
+ return (x & (x-1)) == 0;
+}
+
+PODEF uintptr
+align_forward(uintptr ptr, usize align)
+{
+ uintptr p, a, remainder;
+ assert(is_power_of_two(align));
+
+ p = ptr;
+ a = (uintptr)align;
+ remainder = p & (a-1);
+
+ return (remainder != 0) ? p + a - remainder : p;
+}
+
+PODEF void
+p_arena_create(Arena *a, void *backing_buffer, usize backing_buffer_length)
+{
+ a->buf = (unsigned char *)backing_buffer;
+ a->buf_len = backing_buffer_length;
+ a->curr_offset = 0;
+ a->prev_offset = 0;
+}
+
+PODEF void*
+p_arena_alloc_align(Arena *a, usize s, usize align)
+{
+
+ // Align 'curr_offset' forward to the specified alignment
+ uintptr curr_ptr = (uintptr)a->buf + (uintptr)a->curr_offset;
+ uintptr offset = align_forward(curr_ptr, align);
+ offset -= (uintptr)a->buf; // Change to relative offset
+
+ // Check to see if the backing memory has space left
+ if (offset+s <= a->buf_len) {
+ void *ptr = &a->buf[offset];
+ a->prev_offset = offset;
+ a->curr_offset = offset+s;
+
+ memset(ptr, 0, s);
+ return ptr;
+ }
+
+ return NULL;
+}
+
+PODEF void*
+p_arena_alloc(Arena *a, usize s) {
+ return p_arena_alloc_align(a, s, DEFAULT_ALIGNMENT);
+}
+
+PODEF void*
+p_arena_resize_align(Arena *a, void *old_memory, usize old_size, usize new_size, usize align)
+{
+ assert(is_power_of_two(align));
+ unsigned char *old_mem = (unsigned char *)old_memory;
+
+ if (old_mem == NULL || old_size == 0) {
+ return p_arena_alloc_align(a, new_size, align);
+ } else if (a->buf <= old_mem && old_mem < a->buf+a->buf_len) {
+ if (a->buf+a->prev_offset == old_mem) {
+ a->curr_offset = a->prev_offset + new_size;
+ if (new_size > old_size) {
+ // Zero the new memory by default
+ memset(&a->buf[a->curr_offset], 0, new_size-old_size);
+ }
+ return old_memory;
+ } else {
+ void *new_memory = p_arena_alloc_align(a, new_size, align);
+ size_t copy_size = old_size < new_size ? old_size : new_size;
+ memmove(new_memory, old_memory, copy_size);
+ return new_memory;
+ }
+
+ } else {
+ assert(0 && "Memory is out of bounds of the buffer in this arena");
+ return NULL;
+ }
+}
+
+PODEF void*
+p_arena_resize(Arena *a, void *old_memory, usize old_size, usize new_size)
+{
+ return p_arena_resize_align(a, old_memory, old_size, new_size, DEFAULT_ALIGNMENT);
+}
+
+PODEF void
+p_arena_free_all(Arena *a)
+{
+ a->curr_offset = 0;
+ a->prev_offset = 0;
+}
+
+PODEF void
+p_arena_destroy(Arena* a)
+{
+ a->buf_len = 0;
+ a->curr_offset = 0;
+ a->prev_offset = 0;
+}
+
+PODEF void
+p_stack_create(Stack *s, void *backing_buffer, usize backing_buffer_length)
+{
+ s->buf = (unsigned char*) backing_buffer;
+ s->buf_len = backing_buffer_length;
+ s->offset = 0;
+}
+
+PODEF usize
+calc_padding_with_header(uintptr ptr, uintptr alignment, usize header_size)
+{
+ uintptr p, a, modulo, padding, needed_space;
+
+ assert(is_power_of_two(alignment));
+
+ p = ptr;
+ a = alignment;
+ modulo = p & (a-1); // (p % a) as it assumes alignment is a power of two
+
+ padding = 0;
+ needed_space = 0;
+
+ if (modulo != 0) { // Same logic as 'align_forward'
+ padding = a - modulo;
+ }
+
+ needed_space = (uintptr)header_size;
+
+ if (padding < needed_space) {
+ needed_space -= padding;
+
+ if ((needed_space & (a-1)) != 0) {
+ padding += a * (1+(needed_space/a));
+ } else {
+ padding += a * (needed_space/a);
+ }
+ }
+
+ return (usize)padding;
+}
+
+PODEF void*
+p_stack_alloc(Stack *s, usize len, usize alignment)
+{
+ uintptr curr_addr, next_addr;
+ usize padding;
+ Stack_Allocation_Header *header;
+
+ assert(is_power_of_two(alignment));
+
+ if (alignment > 128) {
+ // As the padding is 8 bits (1 byte), the largest alignment that can
+ // be used is 128 bytes
+ alignment = 128;
+ }
+
+ curr_addr = (uintptr)s->buf + (uintptr)s->offset;
+ padding = calc_padding_with_header(curr_addr, (uintptr)alignment, sizeof(Stack_Allocation_Header));
+ if (s->offset + padding + len > s->buf_len) {
+ // Stack allocator is out of memory
+ return NULL;
+ }
+ s->offset += padding;
+
+ next_addr = curr_addr + (uintptr)padding;
+ header = (Stack_Allocation_Header *)(next_addr - sizeof(Stack_Allocation_Header));
+ header->padding = (u8)padding;
+
+ s->offset += len;
+
+ return memset((void *)next_addr, 0, len);
+}
+
+PODEF void
+p_stack_free(Stack *s, void *ptr)
+{
+ if (ptr != NULL) {
+ uintptr start, end, curr_addr;
+ Stack_Allocation_Header *header;
+ usize prev_offset;
+
+ start = (uintptr)s->buf;
+ end = start + (uintptr)s->buf_len;
+ curr_addr = (uintptr)ptr;
+
+ if (!(start <= curr_addr && curr_addr < end)) {
+ assert(0 && "Out of bounds memory address passed to stack allocator (free)");
+ return;
+ }
+
+ if (curr_addr >= start+(uintptr)s->offset) {
+ // Allow double frees
+ return;
+ }
+
+ header = (Stack_Allocation_Header *)(curr_addr - sizeof(Stack_Allocation_Header));
+ prev_offset = (usize)(curr_addr - (uintptr)header->padding - start);
+
+ s->offset = prev_offset;
+ }
+}
+
+PODEF void
+p_stack_free_all(Stack* s)
+{
+ s->offset = 0;
+}
+
+PODEF void
+p_stack_destroy(Stack* s)
+{
+ s->buf = 0;
+ s->buf_len = 0;
+ s->offset = 0;
+}
+
+PODEF void
+p_pool_create(Pool *p, void *buf, usize buf_len, usize chunk_size, usize chunk_align)
+{
+ /* align start */
+ uintptr start = (uintptr) buf;
+ uintptr aligned = align_forward(start, chunk_align);
+ buf_len -= (aligned - start);
+
+ /* align chunk usize */
+ chunk_size = (usize) align_forward(chunk_size, chunk_align);
+
+ assert(chunk_size >= sizeof(Pool_Free_Node) && "Chunk usize is too small");
+ assert(buf_len >= chunk_size && "Backing buffer length is smaller than the chunk size");
+
+ p->buf = (unsigned char *) buf;
+ p->pool_size = buf_len;
+ p->chunk_size = chunk_size;
+ p->head = NULL;
+
+ p_pool_free_all(p);
+}
+
+PODEF void*
+p_pool_alloc(Pool *p)
+{
+ Pool_Free_Node *node = p->head;
+
+ assert(node != NULL && "Pool allocator has no free memory");
+
+ p->head = p->head->next;
+
+ return memset(node, 0 , p->chunk_size);
+}
+
+PODEF void
+p_pool_free(Pool *p, void *ptr)
+{
+ Pool_Free_Node *node;
+
+ void *start = p->buf;
+ void *end = &p->buf[p->pool_size];
+
+ if (ptr == NULL) {
+ return;
+ }
+
+ if (!(start <= ptr && ptr < end)) {
+ assert(0 && "Memory is out of bounds of the buffer in this pool");
+ return;
+ }
+
+ node = (Pool_Free_Node *)ptr;
+ node->next = p->head;
+ p->head = node;
+}
+
+PODEF void
+p_pool_free_all(Pool *p)
+{
+ usize chunk_count = p->pool_size / p->chunk_size;
+ usize i;
+
+ for (i = 0; i < chunk_count; i++) {
+ void *ptr = &p->buf[i * p->chunk_size];
+ Pool_Free_Node *node = (Pool_Free_Node *)ptr;
+
+ // Push free node onto thte free list
+ node->next = p->head;
+ p->head = node;
+ }
+}
+
+PODEF void
+p_pool_destroy(Pool *p)
+{
+ p->buf = NULL;
+ p->pool_size = 0;
+ p->chunk_size = 0;
+ p->head = NULL;
+}
+