From 4f2a816128c3c556f7d72f409a528b2105d9352a Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Mon, 14 Oct 2024 00:19:18 +0200 Subject: [PATCH] Generated CMakeLists.txt, implemented some of TracingHeap --- src/TracingHeap/CMakeLists.txt | 1 + src/TracingHeap/TracingHeap.c | 169 +++++++++++++++++++++++++++++++++ src/TracingHeap/TracingHeap.h | 49 ++++++++++ 3 files changed, 219 insertions(+) create mode 100644 src/TracingHeap/CMakeLists.txt create mode 100644 src/TracingHeap/TracingHeap.c create mode 100644 src/TracingHeap/TracingHeap.h diff --git a/src/TracingHeap/CMakeLists.txt b/src/TracingHeap/CMakeLists.txt new file mode 100644 index 0000000..1a221f3 --- /dev/null +++ b/src/TracingHeap/CMakeLists.txt @@ -0,0 +1 @@ +add_library(TracingHeap STATIC TracingHeap.c) diff --git a/src/TracingHeap/TracingHeap.c b/src/TracingHeap/TracingHeap.c new file mode 100644 index 0000000..3eeb20a --- /dev/null +++ b/src/TracingHeap/TracingHeap.c @@ -0,0 +1,169 @@ +#include "TracingHeap.h" + +#include "../pointers/pointers.h" + +int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_function, allocator_t* allocator) +{ + if (self == NULL) { + return EDESTADDRREQ; + } + + self->allocator = allocator; + self->tracing_function = tracing_function; + + self->objects = NULL; + self->black_objects = NULL; + self->white_objects = NULL; + self->grey_objects = NULL; + + self->reachable_color = TRACINGCOLOR_WHITE; + self->unreachable_color = TRACINGCOLOR_BLACK; + + return EXIT_SUCCESS; +} + +void TracingHeap_Destroy(TracingHeap* self) +{ + if (self == NULL) { + return; + } + + // TODO: Deallocate all objects + memset(self, 0, sizeof(*self)); +} + +static TracingObject* _TracingObject_FromDataPointer(void* datap) +{ + return rewindp(datap, sizeof(TracingObject)); +} + +static void _TracingObject_ChangeObjectColor(TracingObject* object, enum TracingColor new_color, TracingObject** list_start) +{ + if (object->color != new_color) { + object->color_prev->color_next = object->color_next; + object->color_next->color_prev = object->color_prev; + + object->color = new_color; + object->color_prev = NULL; + object->color_next = *list_start; + (*list_start)->color_prev = object; + *list_start = object; + } +} + +static TracingObject** _TracingHeap_ColorListStart(TracingHeap* self, enum TracingColor color) +{ + TracingObject** list_start; + switch (color) { + case TRACINGCOLOR_BLACK: + list_start = &self->black_objects; + break; + case TRACINGCOLOR_GREY: + list_start = &self->grey_objects; + break; + case TRACINGCOLOR_WHITE: + list_start = &self->white_objects; + break; + } + + return list_start; +} + +static void _TracingHeap_MakeReachable(TracingHeap* self, TracingObject* object) +{ + TracingObject** reachable_list_start = _TracingHeap_ColorListStart(self, self->reachable_color); + _TracingObject_ChangeObjectColor(object, self->reachable_color, reachable_list_start); +} + +static TracingObject* _TracingHeap_PopColorList(TracingHeap* self, enum TracingColor color) +{ + TracingObject** list_start = _TracingHeap_ColorListStart(self, color); + + TracingObject* popped = *list_start; + popped->color_next->color_prev = NULL; // unlink next element from popped + *list_start = popped->color_next; // link list to next element + popped->color_next = NULL; // unlink popped from next element + + return popped; +} + +static int _TracingHeap_TraceReferenceCallback(void* context, void* reference) +{ + TracingHeap* self = context; + TracingObject* object = _TracingObject_FromDataPointer(reference); + + if (object->color == self->unreachable_color) { + _TracingObject_ChangeObjectColor(object, TRACINGCOLOR_GREY, &self->grey_objects); + } + + return EXIT_SUCCESS; +} + +int TracingHeap_AddTracingRoot(TracingHeap* self, void* data) +{ + if (self == NULL) { + return EDESTADDRREQ; + } + + TracingObject* root_object = _TracingObject_FromDataPointer(data); + _TracingObject_ChangeObjectColor(root_object, TRACINGCOLOR_GREY, &self->grey_objects); + + return EXIT_SUCCESS; +} + +int TracingHeap_TraceOnce(TracingHeap* self) +{ + if (self == NULL) { + return EDESTADDRREQ; + } + + if (self->grey_objects == NULL) { + return EBADSTATE; + } + + TracingObject* trace_object = _TracingHeap_PopColorList(self, TRACINGCOLOR_GREY); + + int tracing_code = self->tracing_function( + self->tracing_function_context, + trace_object->data, + _TracingHeap_TraceReferenceCallback, + self + ); + if (tracing_code) { + return tracing_code; + } + + _TracingHeap_MakeReachable(self, trace_object); + + return EXIT_SUCCESS; +} + +void* TracingHeap_Allocate(TracingHeap* self, size_t bytes) +{ + if (self == NULL) { + return NULL; + } + + TracingObject* object = Allocator_Allocate(self->allocator, sizeof(TracingObject) + bytes); + if (object == NULL) { + return NULL; + } + + object->color = self->reachable_color; + + if (self->reachable_color == TRACINGCOLOR_WHITE) { + object->color_next = self->white_objects; + self->white_objects = object; + } else { + // black + object->color_next = self->black_objects; + self->black_objects = object; + } + object->color_prev = NULL; + + + object->global_next = self->objects; + self->objects = object; + + return object->data; +} diff --git a/src/TracingHeap/TracingHeap.h b/src/TracingHeap/TracingHeap.h new file mode 100644 index 0000000..0ea6d00 --- /dev/null +++ b/src/TracingHeap/TracingHeap.h @@ -0,0 +1,49 @@ +#ifndef UTILITIEC_TRACINGHEAP_H +#define UTILITIEC_TRACINGHEAP_H + +#include "../allocator-interface/allocator-interface.h" + +#include + +enum TracingColor { + TRACINGCOLOR_BLACK, + TRACINGCOLOR_GREY, + TRACINGCOLOR_WHITE, +}; + +typedef struct TracingObject { + struct TracingObject* global_next; + struct TracingObject* color_next; + struct TracingObject* color_prev; + enum TracingColor color; + + // data member of the requested size + alignas(void*) char data[]; +} TracingObject; + +typedef int (*TraceReferenceCallback) (void* context, void* reference); +typedef int (*ReferenceTracingFunction) (void* context, void* object, TraceReferenceCallback trace_callback, void* callback_context); + +typedef struct TracingHeap_s { + TracingObject* objects; + TracingObject* white_objects; + TracingObject* grey_objects; + TracingObject* black_objects; + + ReferenceTracingFunction tracing_function; + void* tracing_function_context; + + enum TracingColor reachable_color; + enum TracingColor unreachable_color; + + allocator_t* allocator; +} TracingHeap; + +int TracingHeap_Create(TracingHeap* self, ReferenceTracingFunction tracing_function, allocator_t* allocator); +void TracingHeap_Destroy(TracingHeap* self); + +void* TracingHeap_Allocate(TracingHeap* self, size_t bytes); + +int TracingHeap_AddTracingRoot(TracingHeap* self, void* data); + +#endif // header