From f00da23cae44697b56f55b08cb5bb848dbe9c833 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 30 May 2019 22:53:12 +0300 Subject: [PATCH] New API standalone functions to acquire and release the allocator lock Issue #282 (bdwgc). Public GC_alloc_lock() and GC_alloc_unlock() are introduced to simplify dealing with the GC lock compared to GC_call_with_alloc_lock(). * include/gc.h [GC_THREADS] (GC_alloc_lock, GC_alloc_unlock): Declare new API function. * include/gc.h [!GC_THREADS] (GC_alloc_lock, GC_alloc_unlock): Define as a no-op macro. * misc.c [THREADS] (GC_alloc_lock, GC_alloc_unlock): Define API function. * tests/test.c (reachable_objs_count_enumerator): Remove function. * tests/test.c (check_heap_stats): Call GC_alloc_lock(); call GC_enumerate_reachable_objects_inner() directly; call GC_alloc_unlock(). --- include/gc.h | 12 ++++++++++++ misc.c | 12 ++++++++++++ tests/test.c | 11 +++-------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/include/gc.h b/include/gc.h index a7164c3..4afcf75 100644 --- a/include/gc.h +++ b/include/gc.h @@ -1403,6 +1403,18 @@ typedef GC_word GC_hidden_pointer; # define REVEAL_POINTER(p) GC_REVEAL_POINTER(p) #endif +/* The routines to acquire/release the allocator lock. */ +/* The lock is not reentrant. GC_alloc_unlock() should not be called */ +/* unless the lock is acquired by the current thread. */ +#ifdef GC_THREADS + GC_API void GC_CALL GC_alloc_lock(void); + GC_API void GC_CALL GC_alloc_unlock(void); +#else + /* No need for real locking if the client is single-threaded. */ +# define GC_alloc_lock() (void)0 +# define GC_alloc_unlock() (void)0 +#endif /* !GC_THREADS */ + typedef void * (GC_CALLBACK * GC_fn_type)(void * /* client_data */); GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type /* fn */, void * /* client_data */) GC_ATTR_NONNULL(1); diff --git a/misc.c b/misc.c index 322422f..15570ca 100644 --- a/misc.c +++ b/misc.c @@ -2310,6 +2310,18 @@ GC_API GC_word GC_CALL GC_get_gc_no(void) return GC_parallel; } + GC_API void GC_CALL GC_alloc_lock(void) + { + DCL_LOCK_STATE; + LOCK(); + } + + GC_API void GC_CALL GC_alloc_unlock(void) + { + /* no DCL_LOCK_STATE */ + UNLOCK(); + } + GC_INNER GC_on_thread_event_proc GC_on_thread_event = 0; GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc fn) diff --git a/tests/test.c b/tests/test.c index c533800..79c8d4d 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1648,12 +1648,6 @@ void GC_CALLBACK reachable_objs_counter(void *obj, size_t size, (*(unsigned *)pcounter)++; } -void * GC_CALLBACK reachable_objs_count_enumerator(void *pcounter) -{ - GC_enumerate_reachable_objects_inner(reachable_objs_counter, pcounter); - return NULL; -} - #define NUMBER_ROUND_UP(v, bound) ((((v) + (bound) - 1) / (bound)) * (bound)) void check_heap_stats(void) @@ -1733,8 +1727,9 @@ void check_heap_stats(void) FAIL; } } - (void)GC_call_with_alloc_lock(reachable_objs_count_enumerator, - &obj_count); + GC_alloc_lock(); + GC_enumerate_reachable_objects_inner(reachable_objs_counter, &obj_count); + GC_alloc_unlock(); GC_printf("Completed %u tests\n", n_tests); GC_printf("Allocated %d collectable objects\n", (int)collectable_count); GC_printf("Allocated %d uncollectable objects\n", -- 2.7.4