From 51e6d83ec158997ad0e4e813f624f0dee47e33bb Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 22 Oct 2015 02:50:00 +0300 Subject: [PATCH] Fix lock assert violation in GC_gcollect_inner if GC_ALWAYS_MULTITHREADED * alloc.c (GC_expand_hp): Do not hold the allocation lock when calling GC_init. * malloc.c (GC_alloc_large, GC_generic_malloc_inner): Likewise. * mallocx.c (GC_generic_malloc_many): Likewise. * misc.c (GC_enable_incremental): Likewise. * misc.c (GC_init): Surround GC_gcollect_inner call with LOCK/UNLOCK (only if GC_ASSERTIONS and GC_ALWAYS_MULTITHREADED otherwise redundant). --- alloc.c | 2 +- malloc.c | 10 +++++++++- mallocx.c | 2 +- misc.c | 13 ++++++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/alloc.c b/alloc.c index f043f059..4a2cf3c7 100644 --- a/alloc.c +++ b/alloc.c @@ -1303,8 +1303,8 @@ GC_API int GC_CALL GC_expand_hp(size_t bytes) int result; DCL_LOCK_STATE; - LOCK(); if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); + LOCK(); result = (int)GC_expand_hp_inner(divHBLKSZ((word)bytes)); if (result) GC_requested_heapsize += bytes; UNLOCK(); diff --git a/malloc.c b/malloc.c index 0f35fe24..1627bdb5 100644 --- a/malloc.c +++ b/malloc.c @@ -48,7 +48,12 @@ GC_INNER ptr_t GC_alloc_large(size_t lb, int k, unsigned flags) GC_ASSERT(I_HOLD_LOCK()); lb = ROUNDUP_GRANULE_SIZE(lb); n_blocks = OBJ_SZ_TO_BLOCKS(lb); - if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); + if (!EXPECT(GC_is_initialized, TRUE)) { + DCL_LOCK_STATE; + UNLOCK(); /* just to unset GC_lock_holder */ + GC_init(); + LOCK(); + } /* Do our share of marking work */ if (GC_incremental && !GC_dont_gc) GC_collect_a_little_inner((int)n_blocks); @@ -113,7 +118,10 @@ GC_INNER void * GC_generic_malloc_inner(size_t lb, int k) if (EXPECT(0 == op, FALSE)) { if (lg == 0) { if (!EXPECT(GC_is_initialized, TRUE)) { + DCL_LOCK_STATE; + UNLOCK(); /* just to unset GC_lock_holder */ GC_init(); + LOCK(); lg = GC_size_map[lb]; } if (0 == lg) { diff --git a/mallocx.c b/mallocx.c index d1928805..5a370609 100644 --- a/mallocx.c +++ b/mallocx.c @@ -307,8 +307,8 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t lb, int k, void **result) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); GC_DBG_COLLECT_AT_MALLOC(lb); - LOCK(); if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); + LOCK(); /* Do our share of marking work */ if (GC_incremental && !GC_dont_gc) { ENTER_GC(); diff --git a/misc.c b/misc.c index 17f65cf6..99f65f08 100644 --- a/misc.c +++ b/misc.c @@ -1259,6 +1259,7 @@ GC_API void GC_CALL GC_init(void) GC_is_initialized = TRUE; # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) # if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED) + DCL_LOCK_STATE; LOCK(); /* just to set GC_lock_holder */ GC_thr_init(); UNLOCK(); @@ -1272,7 +1273,15 @@ GC_API void GC_CALL GC_init(void) # endif COND_DUMP; /* Get black list set up and/or incremental GC started */ - if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); + if (!GC_dont_precollect || GC_incremental) { +# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED) + LOCK(); + GC_gcollect_inner(); + UNLOCK(); +# else + GC_gcollect_inner(); +# endif + } # ifdef STUBBORN_ALLOC GC_stubborn_init(); # endif @@ -1318,7 +1327,9 @@ GC_API void GC_CALL GC_enable_incremental(void) maybe_install_looping_handler(); /* Before write fault handler! */ GC_incremental = TRUE; if (!GC_is_initialized) { + UNLOCK(); GC_init(); + LOCK(); } else { GC_dirty_init(); } -- 2.40.0