From e093be94e1569e05a25c454c2c47a1863c679c56 Mon Sep 17 00:00:00 2001 From: Jake Hughes Date: Wed, 21 Aug 2024 21:17:22 +0100 Subject: [PATCH] Revert to using old GC_finalize mechanism Using an extension of the disclaim API proved difficult because of the need to re-mark objects pointed to by finalisable objects before a finaliser is run. This would have led to complex changes to the mark-phase for no real benefit. Instead, by switching back to the GC_finalize mechanism but ensuring that finalisers are run off of mutator threads, we get this desired behaviour 'for free'. This approach uses a simple condition variable to sleep the finaliser thread when there is no finalisation work to do. This is then potentially resumed at the end of a GC cycle if that cycle discovered finalisable objects. --- include/private/gc_priv.h | 10 +++++----- reclaim.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 893c6372b..74aa27825 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -341,6 +341,7 @@ typedef struct hblkhdr hdr; #include "gc/gc_inline.h" +<<<<<<< HEAD #ifdef BUFFERED_FINALIZATION typedef struct GC_finalization_buffer_hdr GC_finalization_buffer_hdr; @@ -355,6 +356,9 @@ struct GC_current_buffer { }; GC_INNER void GC_maybe_spawn_finalize_thread(); +======= +GC_INNER void GC_maybe_wake_finalizer_thread(); +>>>>>>> b44b0a3e (Revert to using old GC_finalize mechanism) #endif @@ -402,11 +406,7 @@ GC_INNER void GC_maybe_spawn_finalize_thread(); EXTERN_C_BEGIN #ifndef GC_NO_FINALIZATION -#ifdef BUFFERED_FINALIZATION -# define GC_INVOKE_FINALIZERS() GC_maybe_spawn_finalize_thread() -#else -# define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers() -#endif +# define GC_INVOKE_FINALIZERS() GC_maybe_wake_finalizer_thread() GC_INNER void GC_notify_or_invoke_finalizers(void); /* If GC_finalize_on_demand is not set, invoke */ /* eligible finalizers. Otherwise: */ diff --git a/reclaim.c b/reclaim.c index ae6a420c9..9675fa199 100644 --- a/reclaim.c +++ b/reclaim.c @@ -21,6 +21,13 @@ # include "gc/gc_disclaim.h" #endif +#ifdef GC_PTHREADS +static pthread_mutex_t flzr_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t flzr_t_has_work = PTHREAD_COND_INITIALIZER; +#elif +#error "This fork of BDWGC only supports POSIX threads" +#endif + GC_INNER signed_word GC_bytes_found = 0; /* Number of bytes of memory reclaimed */ /* minus the number of bytes originally */ @@ -876,3 +883,33 @@ GC_API void GC_CALL GC_enumerate_reachable_objects_inner( ed.client_data = client_data; GC_apply_to_all_blocks(GC_do_enumerate_reachable_objects, (word)&ed); } + +static void* init_finalize_thread(void *arg) +{ + while(1) { + pthread_mutex_lock(&flzr_mtx); + while (GC_should_invoke_finalizers() == 0) { + pthread_cond_wait(&flzr_t_has_work, &flzr_mtx); + } + pthread_mutex_unlock(&flzr_mtx); + GC_invoke_finalizers(); + } + return arg; +} + +GC_INNER void GC_maybe_wake_finalizer_thread() +{ + if (!GC_finalizer_thread_exists) { + pthread_t t; + pthread_create(&t, NULL, init_finalize_thread, NULL /* arg */); + GC_finalizer_thread_exists = 1; + return; + } + + if (GC_should_invoke_finalizers() == 0) + return; + + pthread_mutex_lock(&flzr_mtx); + pthread_cond_signal(&flzr_t_has_work); + pthread_mutex_unlock(&flzr_mtx); +}