summaryrefslogtreecommitdiffstats
path: root/memory/alloc/realloc.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2024-05-22 13:00:41 -0400
committerJon Santmyer <jon@jonsantmyer.com>2024-05-22 13:00:41 -0400
commitace65b453151845bc361f21f3e5b651c35f9f126 (patch)
tree262ebd29b0ca1d8584f0b6f1efa7a00d9f4f3e43 /memory/alloc/realloc.c
parentf004c1ade8d617a82cea2fe249434cccb47a2358 (diff)
downloadjove-kernel-ace65b453151845bc361f21f3e5b651c35f9f126.tar.gz
jove-kernel-ace65b453151845bc361f21f3e5b651c35f9f126.tar.bz2
jove-kernel-ace65b453151845bc361f21f3e5b651c35f9f126.zip
massive refactor for mp and organizationHEADmaster
Diffstat (limited to 'memory/alloc/realloc.c')
-rw-r--r--memory/alloc/realloc.c73
1 files changed, 73 insertions, 0 deletions
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;
+}