From 8e058bbfe6215bb8278554cbf35f93b562ab0f01 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Wed, 29 Nov 2017 11:46:05 +0300 Subject: [PATCH] Eliminate TSan false positive for stop_info.stack_ptr (v2) Without this patch, Thread Sanitizer reports a data race between GC_has_other_debug_info() and the code which sets stop_info.stack_ptr. * include/private/pthread_support.h [THREAD_SANITIZER]: Include dbg_mlc.h file. * include/private/pthread_support.h [THREAD_SANITIZER] (GC_Thread_Rep): Add dummy field (as the first field of the structure). * pthread_support.c [THREAD_SANITIZER && CPPCHECK] (GC_new_thread): Call GC_noop1(first_thread.dummy[0]) (to suppress cppcheck warning about unused field). --- include/private/pthread_support.h | 12 ++++++++++++ pthread_support.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h index 233b59d7..12c3f1af 100644 --- a/include/private/pthread_support.h +++ b/include/private/pthread_support.h @@ -32,6 +32,10 @@ # include "thread_local_alloc.h" #endif +#ifdef THREAD_SANITIZER +# include "dbg_mlc.h" /* for oh type */ +#endif + /* We use the allocation lock to protect thread-related data structures. */ /* The set of all known threads. We intercept thread creation and */ @@ -40,6 +44,14 @@ /* Some of this should be declared volatile, but that's inconsistent */ /* with some library routine declarations. */ typedef struct GC_Thread_Rep { +# ifdef THREAD_SANITIZER + char dummy[sizeof(oh)]; /* A dummy field to avoid TSan false */ + /* positive about the race between */ + /* GC_has_other_debug_info and */ + /* GC_suspend_handler_inner (which */ + /* sets store_stop.stack_ptr). */ +# endif + struct GC_Thread_Rep * next; /* More recently allocated threads */ /* with a given pthread id come */ /* first. (All but the first are */ diff --git a/pthread_support.c b/pthread_support.c index 2d68293e..b6489fc1 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -548,6 +548,9 @@ STATIC GC_thread GC_new_thread(pthread_t id) if (!EXPECT(first_thread_used, TRUE)) { result = &first_thread; first_thread_used = TRUE; +# if defined(THREAD_SANITIZER) && defined(CPPCHECK) + GC_noop1(result->dummy[0]); +# endif } else { result = (struct GC_Thread_Rep *) GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL); -- 2.40.0