first: &GCLink;
}
-#local
GCLink :: struct {
prev: &GCLink;
next: &GCLink;
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;
}
}
-#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 {
}
}
+ // \/
+ // 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);
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;
+}
+
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;