From: Ivan Maidanski Date: Tue, 1 Sep 2015 06:57:38 +0000 (+0300) Subject: Fix data race in GC_init_explicit_typing X-Git-Tag: gc7_4_4~80 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69527f21d06e790a22197ca732580299c832e9ec;p=gc Fix data race in GC_init_explicit_typing * 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. --- diff --git a/typd_mlc.c b/typd_mlc.c index b164f522..aba9f46c 100644 --- a/typd_mlc.c +++ b/typd_mlc.c @@ -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) {