]> granicus.if.org Git - gc/commitdiff
Fix data race in GC_init_explicit_typing
authorIvan Maidanski <ivmai@mail.ru>
Tue, 1 Sep 2015 06:57:38 +0000 (09:57 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Fri, 29 Jan 2016 13:01:39 +0000 (16:01 +0300)
* typd_mlc.c: Force include atomic_ops.h if
GC_FORCE_INCLUDE_ATOMIC_OPS (by default it is included if
PARALLEL_MARK or pthreads are used).
* typd_mlc.c (GC_explicit_typing_initialized): Use AO_t if
AO_load_acquire() available.
* typd_mlc.c (GC_init_explicit_typing): Move locking (and
GC_explicit_typing_initialized access) outside to the caller
(GC_make_descriptor); remove comment; remove "register" keyword for
local variable.
* typd_mlc.c (GC_make_descriptor): Use AO_load_acquire (if available)
to fetch GC_explicit_typing_initialized value (to avoid data race and
avoid lock acquiring on each call).
* typd_mlc.c (GC_explicit_typing_initialized,
GC_malloc_explicitly_typed_ignore_off_page,
GC_calloc_explicitly_typed): Add assertion on
GC_explicit_typing_initialized is true.

typd_mlc.c

index b164f522f517eed362f349e5021456cf7bab485d..aba9f46c54e2c1ee959e759163c3ce881597378e 100644 (file)
@@ -41,8 +41,6 @@
 
 #define TYPD_EXTRA_BYTES (sizeof(word) - EXTRA_BYTES)
 
-STATIC GC_bool GC_explicit_typing_initialized = FALSE;
-
 STATIC int GC_explicit_kind = 0;
                         /* Object kind for objects with indirect        */
                         /* (possibly extended) descriptors.             */
@@ -100,6 +98,18 @@ STATIC size_t GC_avail_descr = 0;       /* Next available slot.         */
 STATIC int GC_typed_mark_proc_index = 0; /* Indices of my mark          */
 STATIC int GC_array_mark_proc_index = 0; /* procedures.                 */
 
+#if !defined(AO_HAVE_load_acquire) && defined(GC_FORCE_INCLUDE_ATOMIC_OPS)
+# include "atomic_ops.h"
+#endif
+
+STATIC
+# ifdef AO_HAVE_load_acquire
+    AO_t
+# else
+    GC_bool
+# endif
+  GC_explicit_typing_initialized = FALSE;
+
 STATIC void GC_push_typed_structures_proc(void)
 {
   GC_push_all((ptr_t)&GC_ext_descriptors,
@@ -344,19 +354,11 @@ STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
 STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr,
                                 mse * mark_stack_limit, word env);
 
-/* Caller does not hold allocation lock. */
 STATIC void GC_init_explicit_typing(void)
 {
-    register unsigned i;
-    DCL_LOCK_STATE;
+    unsigned i;
 
     GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0);
-    LOCK();
-    if (GC_explicit_typing_initialized) {
-      UNLOCK();
-      return;
-    }
-    GC_explicit_typing_initialized = TRUE;
     /* Set up object kind with simple indirect descriptor. */
       GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner();
       GC_explicit_kind = GC_new_kind_inner(
@@ -375,7 +377,6 @@ STATIC void GC_init_explicit_typing(void)
       for (i = 0; i < WORDSZ/2; i++) {
           GC_bm_table[i] = (((word)-1) << (WORDSZ - i)) | GC_DS_BITMAP;
       }
-    UNLOCK();
 }
 
 STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr,
@@ -537,9 +538,26 @@ GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * bm, size_t len)
     GC_descr result;
     signed_word i;
 #   define HIGH_BIT (((word)1) << (WORDSZ - 1))
+    DCL_LOCK_STATE;
 
-    if (!EXPECT(GC_explicit_typing_initialized, TRUE))
-      GC_init_explicit_typing();
+#   if defined(THREADS) && defined(AO_HAVE_load_acquire)
+      if (!EXPECT(AO_load_acquire(
+                        (volatile AO_t *)&GC_explicit_typing_initialized),
+                  TRUE))
+#   endif
+    {
+      LOCK();
+#     if defined(THREADS) && defined(AO_HAVE_load_acquire)
+        if (!GC_explicit_typing_initialized)
+#     else
+        if (!EXPECT(GC_explicit_typing_initialized, TRUE))
+#     endif
+      {
+        GC_init_explicit_typing();
+        GC_explicit_typing_initialized = TRUE;
+      }
+      UNLOCK();
+    }
 
     while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit))
       last_set_bit--;
@@ -589,8 +607,9 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_explicitly_typed(size_t lb,
     size_t lg;
     DCL_LOCK_STATE;
 
+    GC_ASSERT(GC_explicit_typing_initialized);
     lb += TYPD_EXTRA_BYTES;
-    if(SMALL_OBJ(lb)) {
+    if (SMALL_OBJ(lb)) {
         GC_DBG_COLLECT_AT_MALLOC(lb);
         lg = GC_size_map[lb];
         opp = &(GC_eobjfreelist[lg]);
@@ -626,6 +645,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL
     size_t lg;
     DCL_LOCK_STATE;
 
+    GC_ASSERT(GC_explicit_typing_initialized);
     lb += TYPD_EXTRA_BYTES;
     if( SMALL_OBJ(lb) ) {
         GC_DBG_COLLECT_AT_MALLOC(lb);
@@ -667,6 +687,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n,
     struct LeafDescriptor leaf;
     DCL_LOCK_STATE;
 
+    GC_ASSERT(GC_explicit_typing_initialized);
     descr_type = GC_make_array_descriptor((word)n, (word)lb, d,
                                           &simple_descr, &complex_descr, &leaf);
     switch(descr_type) {