From e52ef4b2c54ce163c5aa496b0e2acdf6e89816c9 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 1 Sep 2015 09:57:38 +0300 Subject: [PATCH] Fix data race in GC_init_explicit_typing (Cherry-pick commits 69527f2, c0492a7 from 'release-7_4' branch.) * 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 volatile AO_t if AO_load_acquire() and AO_store_release() are both 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 and AO_store_release to set GC_explicit_typing_initialized (to avoid data race and avoid lock acquiring on each call); otherwise use locked checking of GC_explicit_typing_initialized. * 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 | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/typd_mlc.c b/typd_mlc.c index e08f5a99..28dcef41 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,16 @@ 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 + +#ifdef AO_HAVE_load_acquire + STATIC volatile AO_t GC_explicit_typing_initialized = FALSE; +#else + STATIC GC_bool GC_explicit_typing_initialized = FALSE; +#endif + STATIC void GC_push_typed_structures_proc(void) { GC_push_all((ptr_t)&GC_ext_descriptors, @@ -343,19 +351,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( @@ -377,7 +377,6 @@ STATIC void GC_init_explicit_typing(void) d |= GC_DS_BITMAP; GC_bm_table[i] = d; } - UNLOCK(); } STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr, @@ -545,11 +544,30 @@ GC_API GC_descr GC_CALL GC_make_descriptor(GC_bitmap bm, size_t len) GC_descr result; signed_word i; # define HIGH_BIT (((word)1) << (WORDSZ - 1)) + DCL_LOCK_STATE; + +# if defined(AO_HAVE_load_acquire) && defined(AO_HAVE_store_release) + if (!EXPECT(AO_load_acquire(&GC_explicit_typing_initialized), TRUE)) { + LOCK(); + if (!GC_explicit_typing_initialized) { + GC_init_explicit_typing(); + AO_store_release(&GC_explicit_typing_initialized, TRUE); + } + UNLOCK(); + } +# else + LOCK(); + if (!EXPECT(GC_explicit_typing_initialized, TRUE)) { + GC_init_explicit_typing(); + GC_explicit_typing_initialized = TRUE; + } + UNLOCK(); +# endif - if (!GC_explicit_typing_initialized) GC_init_explicit_typing(); while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit)) last_set_bit--; if (last_set_bit < 0) return(0 /* no pointers */); + # if ALIGNMENT == CPP_WORDSZ/8 { register GC_bool all_bits_set = TRUE; @@ -594,6 +612,7 @@ GC_API void * GC_CALL GC_malloc_explicitly_typed(size_t lb, GC_descr d) size_t lg; DCL_LOCK_STATE; + GC_ASSERT(GC_explicit_typing_initialized); lb = SIZET_SAT_ADD(lb, TYPD_EXTRA_BYTES); if (SMALL_OBJ(lb)) { lg = GC_size_map[lb]; @@ -629,6 +648,7 @@ GC_API void * GC_CALL GC_malloc_explicitly_typed_ignore_off_page(size_t lb, size_t lg; DCL_LOCK_STATE; + GC_ASSERT(GC_explicit_typing_initialized); lb = SIZET_SAT_ADD(lb, TYPD_EXTRA_BYTES); if (SMALL_OBJ(lb)) { lg = GC_size_map[lb]; @@ -668,6 +688,7 @@ GC_API void * GC_CALL GC_calloc_explicitly_typed(size_t n, size_t lb, 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); if ((lb | n) > GC_SQRT_SIZE_MAX /* fast initial check */ -- 2.40.0