From ace65b453151845bc361f21f3e5b651c35f9f126 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Wed, 22 May 2024 13:00:41 -0400 Subject: massive refactor for mp and organization --- memory/alloc/realloc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 memory/alloc/realloc.c (limited to 'memory/alloc/realloc.c') diff --git a/memory/alloc/realloc.c b/memory/alloc/realloc.c new file mode 100644 index 0000000..1b90e8c --- /dev/null +++ b/memory/alloc/realloc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) Jon Santmyer. + * This source file is released under the LGPL Version 3 as detailed in + * the LICENSE file provided in the following repository: + * https://git.jonsantmyer.com/heap/ + * */ + +#include "malloc.h" +#include "assert.h" +#include "string.h" + +void* +__realloc_impl(heap_cache_t *cache, void *ptr, size_t w) +{ + if(w == 0) { + DBGPRINT("realloc: called with w == 0, freeing %p\n", ptr); + __free_impl(cache, ptr); + return NULL; + } + if(ptr == NULL) { + DBGPRINT("realloc: called with NULL ptr, alloc %i\n", w); + return __malloc_impl(cache, w); + } + + w = REALW(w); + bucket_obj_t *obj = OBJ_FROM_PTR(ptr); + + assert(OBJ_VALID(obj)); + size_t objw = OBJ_WIDTH(obj); + if(objw > w) return ptr; + + size_t wdiff = w - objw; + DBGPRINT("realloc: ptr %p needs %i new bytes\n", ptr, wdiff); + + bucket_obj_t *after = OBJ_AFTER(obj); + size_t afterw = 0; + bucket_t *bucket = __bucket_from_obj(cache, obj); + void *newptr = NULL; + + if(bucket == NULL) + goto resize_fail; + + if((uintptr_t)after > bucket->limit) goto resize_fail; + assert(OBJ_VALID(after)); + afterw = OBJ_WIDTH(after); + + if(OBJ_TAKEN(after)) + goto resize_fail; + + DBGPRINT("realloc: obj %p after obj %p is free (w %i)\n", after, obj, afterw); + if(objw + sizeof(bucket_obj_t) + afterw < w) + goto resize_fail; + + obj->size_taken = w | 1; + if(bucket->firstfree == after) + bucket->firstfree = OBJ_AFTER(obj); + + after = OBJ_AFTER(obj); + *after = (bucket_obj_t){ + .checksum = OBJ_CHECKSUM, + .size_taken = afterw - wdiff + }; + DBGPRINT("realloc: moved obj %p (%i) to resize obj %p (%i)\n", + after, after->size_taken, obj, obj->size_taken); + return ptr; + +resize_fail: + DBGPRINT("realloc: could not resize existing object, calling malloc\n"); + newptr = __malloc_impl(cache, w); + memcpy(newptr, ptr, obj->size_taken & ~1); + __free_impl(cache, ptr); + return newptr; +} -- cgit v1.2.1