diff --git a/fnlz_mlc.c b/fnlz_mlc.c index 110439d39..2ab918a3d 100644 --- a/fnlz_mlc.c +++ b/fnlz_mlc.c @@ -134,9 +134,6 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb, # ifdef BUFFERED_FINALIZATION -STATIC GC_finalization_buffer_hdr* start_buffer; -STATIC struct GC_current_buffer cur_buffer; - static void* init_finalize_thread(void *arg) { while (1) { @@ -176,28 +173,28 @@ STATIC int GC_CALLBACK GC_push_object_to_fin_buffer(void *obj) return 0; } - if (start_buffer == NULL) { + if (GC_finalizer_buffer_head == NULL) { /* This can happen for two reasons: * 1) This is first time a finalizable object is unreachable and no * finalization buffers have been created yet. * * 2) The buffer(s) have already passed to a finalization thread * which is processing them. We must start again. */ - start_buffer = GC_new_buffer(); - cur_buffer.hdr = start_buffer; - cur_buffer.cursor = (void**) (start_buffer + 1); + GC_finalizer_buffer_head = GC_new_buffer(); + GC_finalizer_buffer_current.hdr = GC_finalizer_buffer_head; + GC_finalizer_buffer_current.cursor = (void**) (GC_finalizer_buffer_head + 1); } - void** last = (void**) ((void *)cur_buffer.hdr + GC_page_size); - if (cur_buffer.cursor == last) { + void** last = (void**) ((void *)GC_finalizer_buffer_current.hdr + GC_page_size); + if (GC_finalizer_buffer_current.cursor == last) { GC_finalization_buffer_hdr* next = GC_new_buffer(); - cur_buffer.hdr->next = next; - cur_buffer.hdr = next; - cur_buffer.cursor = (void**) (next + 1); + GC_finalizer_buffer_current.hdr->next = next; + GC_finalizer_buffer_current.hdr = next; + GC_finalizer_buffer_current.cursor = (void**) (next + 1); } - *cur_buffer.cursor = obj; - cur_buffer.cursor++; + *GC_finalizer_buffer_current.cursor = obj; + GC_finalizer_buffer_current.cursor++; return 1; } @@ -225,8 +222,6 @@ GC_API void GC_CALL GC_init_buffered_finalization(void) GC_register_disclaim_proc_inner(GC_fin_q_kind, GC_push_object_to_fin_buffer, TRUE); UNLOCK(); - pthread_t t; - pthread_create(&t, NULL, init_finalize_thread, NULL /* arg */); } void GC_finalize_buffer(GC_finalization_buffer_hdr* buffer) { @@ -256,8 +251,8 @@ GC_API void GC_CALL GC_finalize_objects(void) { * collection, so the finalisation thread will always load the up-to-date * version of this global. */ GC_disable(); - GC_finalization_buffer_hdr* buffer = start_buffer; - start_buffer = NULL; + GC_finalization_buffer_hdr* buffer = GC_finalizer_buffer_head; + GC_finalizer_buffer_head = NULL; GC_enable(); while(buffer != NULL) @@ -270,6 +265,16 @@ GC_API void GC_CALL GC_finalize_objects(void) { } } +GC_INNER void GC_maybe_spawn_finalize_thread() +{ + if (GC_finalizer_thread_exists || !GC_finalizer_buffer_head) + return; + + pthread_t t; + pthread_create(&t, NULL, init_finalize_thread, NULL /* arg */); + GC_finalizer_thread_exists = 1; +} + # endif #endif /* ENABLE_DISCLAIM */ diff --git a/include/gc/gc_disclaim.h b/include/gc/gc_disclaim.h index 334008106..ebc6f16d1 100644 --- a/include/gc/gc_disclaim.h +++ b/include/gc/gc_disclaim.h @@ -69,17 +69,6 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL const struct GC_finalizer_closure * /* fc */) GC_ATTR_NONNULL(2); -typedef struct GC_finalization_buffer_hdr GC_finalization_buffer_hdr; - -struct GC_finalization_buffer_hdr { - GC_finalization_buffer_hdr* next; -}; - -struct GC_current_buffer { - GC_finalization_buffer_hdr* hdr; - void** cursor; -}; - /* This API is defined only if the library has been suitably compiled */ /* (i.e. with ENABLE_DISCLAIM defined). */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 2fcabefaf..6c6b199c3 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -324,6 +324,23 @@ typedef unsigned int unsigned32; #include "gc/gc_inline.h" +#ifdef BUFFERED_FINALIZATION + +typedef struct GC_finalization_buffer_hdr GC_finalization_buffer_hdr; + +struct GC_finalization_buffer_hdr { + GC_finalization_buffer_hdr* next; +}; + +struct GC_current_buffer { + GC_finalization_buffer_hdr* hdr; + void** cursor; +}; + +GC_INNER void GC_maybe_spawn_finalize_thread(); + +#endif + /*********************************/ /* */ /* Definitions for conservative */ @@ -368,7 +385,11 @@ typedef unsigned int unsigned32; 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 GC_INNER void GC_notify_or_invoke_finalizers(void); /* If GC_finalize_on_demand is not set, invoke */ /* eligible finalizers. Otherwise: */ @@ -1557,8 +1578,16 @@ struct _GC_arrays { # ifdef ENABLE_DISCLAIM # define GC_finalized_kind GC_arrays._finalized_kind unsigned _finalized_kind; +# ifdef BUFFERED_FINALIZATION # define GC_fin_q_kind GC_arrays._fin_q_kind unsigned _fin_q_kind; +# define GC_finalizer_buffer_head GC_arrays._fin_buffer_head + GC_finalization_buffer_hdr* _fin_buffer_head; +# define GC_finalizer_buffer_current GC_arrays._fin_buffer_current + struct GC_current_buffer _fin_buffer_current; +# define GC_finalizer_thread_exists GC_arrays._fin_thread_exists + int _fin_thread_exists; +# endif # endif # define n_root_sets GC_arrays._n_root_sets # define GC_excl_table_entries GC_arrays._excl_table_entries diff --git a/misc.c b/misc.c index 6a3b589d5..61f33577d 100644 --- a/misc.c +++ b/misc.c @@ -2069,9 +2069,11 @@ GC_API void GC_CALL GC_enable(void) LOCK(); GC_ASSERT(GC_dont_gc != 0); /* ensure no counter underflow */ GC_dont_gc--; +#ifndef BUFFERED_FINALIZATION if (!GC_dont_gc && GC_heapsize > GC_heapsize_on_gc_disable) WARN("Heap grown by %" WARN_PRIuPTR " KiB while GC was disabled\n", (GC_heapsize - GC_heapsize_on_gc_disable) >> 10); +#endif UNLOCK(); }