added: `alloc.gc.untrack` to untrack a GC'd allocation
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 15 Mar 2023 01:25:08 +0000 (20:25 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 15 Mar 2023 01:25:08 +0000 (20:25 -0500)
core/alloc/gc.onyx
core/alloc/heap.onyx

index bd3291c3c6325b41fdfe7aa1e1cb71c7dc8565e2..8ff2ebbfa7f44e8eb965b3fe7d749d81ff6f0869 100644 (file)
@@ -21,7 +21,6 @@ GCState :: struct {
     first: &GCLink;
 }
 
-#local
 GCLink :: struct {
     prev: &GCLink;
     next: &GCLink;
@@ -37,7 +36,12 @@ make :: (backing := context.allocator) -> GCState {
 clear :: (hs: &GCState) {
     while l := hs.first; l != null {
         n := l.next;
-        raw_free(hs.backing_allocator, l);
+
+        if l.magic_number == GC_Link_Magic_Number {
+            l.magic_number = 0;
+            raw_free(hs.backing_allocator, l);
+        }
+
         l = n;
     }
 
@@ -76,8 +80,10 @@ auto :: #match {
 }
 
 
-#local
-GC_Link_Magic_Number :: 0x1337face
+
+GC_Manually_Free_Magic_Number :: 0xface1337
+
+#local GC_Link_Magic_Number :: 0x1337face
 
 #local gc_alloc_proc :: (data: &GCState, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
 
@@ -108,6 +114,10 @@ GC_Link_Magic_Number :: 0x1337face
         }
     }
 
+    //                                                   \/
+    // HEAP DATA              | GCLINK                   | Your actual allocation
+    // POINTERS MAGIC NUMBERS | prev, next, magic_number | bytes of data...
+
     newptr: &GCLink = data.backing_allocator.func(
         data.backing_allocator.data, aa,
         size + sizeof GCLink, align, old);
@@ -128,3 +138,15 @@ GC_Link_Magic_Number :: 0x1337face
 
     return newptr + 1;
 }
+
+untrack :: (ptr: rawptr) -> bool {
+    link := (cast(&GCLink) ptr) - 1;
+
+    if link.magic_number != GC_Link_Magic_Number {
+        return false;
+    }
+
+    link.magic_number = GC_Manually_Free_Magic_Number;
+    return true;
+}
+
index 6848c14d7312735b82c24e5bec7a5808b247430a..79f90c8d5ac653e8b23e6e61cea91e4b16014d62 100644 (file)
@@ -178,12 +178,20 @@ get_freed_size :: () => {
 
     heap_free :: (ptr: rawptr) {
         #if Enable_Debug do assert(ptr != null, "Trying to free a null pointer.");
+        
+        hb_ptr := cast(&heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
+
+        //
+        // If this block was originally allocated from the GC space,
+        // and then marked an "manually managed", we can free the block
+        // as normal here, but we have to go back some more bytes.
+        if hb_ptr.magic_number == core.alloc.gc.GC_Manually_Free_Magic_Number  {
+            hb_ptr = ~~(cast(uintptr) (cast(&core.alloc.gc.GCLink, ptr) - 1) - sizeof heap_allocated_block);
+        }
+
         #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex);
 
-        hb_ptr := cast(&heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
         #if Enable_Debug {
-            // assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it.");
-
             if cast(uintptr) hb_ptr < cast(uintptr) __heap_start {
                 log(.Error, "Core", "FREEING STATIC DATA");
                 return;