]> granicus.if.org Git - gc/commitdiff
Fix lock assert violation in GC_gcollect_inner if GC_ALWAYS_MULTITHREADED
authorIvan Maidanski <ivmai@mail.ru>
Wed, 21 Oct 2015 23:50:00 +0000 (02:50 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 21 Oct 2015 23:50:00 +0000 (02:50 +0300)
* 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
malloc.c
mallocx.c
misc.c

diff --git a/alloc.c b/alloc.c
index f043f0599ba0d81328b9cec8f992045774d2503f..4a2cf3c784c165d024bde4dbeca6c0dcd3b17a1c 100644 (file)
--- 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();
index 0f35fe2421754a10f1fb22a7e614d757ee0de14f..1627bdb55b4ab9b68c1383c369353d717fa80137 100644 (file)
--- 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) {
index d1928805d76eb2b78466c2b0ee6a72dd1f35f200..5a370609aaaedb836d7d9e9349690625cb86dab1 100644 (file)
--- 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 17f65cf67dcb9285ee4cf1f3d806bd8c12a37afc..99f65f08c6b04797d801c546ddd08977ba352c5a 100644 (file)
--- 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();
         }