From fdf227b16d5e822e1ce438d39c43f5e4ac5cda21 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 21 Sep 2017 11:36:30 +0300 Subject: [PATCH] Workaround Thread Sanitizer (TSan) false positive warnings * src/atomic_ops.h [__has_feature && __has_feature(thread_sanitizer)] (AO_THREAD_SANITIZER): New internal macro. * src/atomic_ops.h [!AO_ATTR_NO_SANITIZE_THREAD] (AO_ATTR_NO_SANITIZE_THREAD): Likewise. * src/atomic_ops/generalize-arithm.h: Regenerate. * src/atomic_ops/generalize-small.h: Likewise. * src/atomic_ops/generalize-arithm.template (AO_XSIZE_fetch_and_add_full, AO_XSIZE_fetch_and_add_acquire, AO_XSIZE_fetch_and_add_release, AO_XSIZE_fetch_and_add, AO_XSIZE_and_full, AO_XSIZE_or_full, AO_XSIZE_xor_full): Add AO_ATTR_NO_SANITIZE_THREAD attribute. * src/atomic_ops/generalize-small.template (AO_XSIZE_load_read, AO_XSIZE_load_full, AO_XSIZE_load_acquire, AO_XSIZE_load, AO_XSIZE_store_write, AO_XSIZE_store, AO_XSIZE_store_release, AO_XSIZE_store_full: Likewise. * src/atomic_ops_stack.c [AO_USE_ALMOST_LOCK_FREE] (AO_stack_push_explicit_aux_release): Likewise. * src/atomic_ops_stack.c [AO_HAVE_compare_double_and_swap_double] (AO_stack_push_release, AO_stack_pop_acquire): Likewise. * tests/test_malloc.c (cons): Likewise. * src/atomic_ops/sysdeps/gcc/x86.h [AO_GCC_ATOMIC_TEST_AND_SET && __clang__ && __x86_64__ && !__ILP32__ && AO_THREAD_SANITIZER] (AO_SKIPATOMIC_double_compare_and_swap_ANY, AO_SKIPATOMIC_double_load, AO_SKIPATOMIC_double_load_acquire, AO_SKIPATOMIC_double_store, AO_SKIPATOMIC_double_store_release): Define; update comment. * src/atomic_ops_malloc.c [AO_THREAD_SANITIZER] (AO_malloc, AO_free): Use AO_store/load to write/read log_sz value in object header. * tests/test_atomic.c (do_junk): New function (declared with AO_ATTR_NO_SANITIZE_THREAD attribute); multiply junk value by two different constant values. * tests/test_atomic.c (test_and_set_thr): Call do_junk() instead of operating on junk global variable directly. --- src/atomic_ops.h | 12 +++++ src/atomic_ops/generalize-arithm.h | 28 ++++++++++++ src/atomic_ops/generalize-arithm.template | 7 +++ src/atomic_ops/generalize-small.h | 75 ++++++++++++++++--------------- src/atomic_ops/generalize-small.template | 15 ++++--- src/atomic_ops/sysdeps/gcc/x86.h | 7 +-- src/atomic_ops_malloc.c | 12 ++++- src/atomic_ops_stack.c | 11 ++--- tests/test_atomic.c | 9 +++- tests/test_malloc.c | 4 +- 10 files changed, 124 insertions(+), 56 deletions(-) diff --git a/src/atomic_ops.h b/src/atomic_ops.h index 03f82a6..568a8c5 100644 --- a/src/atomic_ops.h +++ b/src/atomic_ops.h @@ -200,6 +200,9 @@ # if __has_feature(memory_sanitizer) # define AO_MEMORY_SANITIZER # endif +# if __has_feature(thread_sanitizer) +# define AO_THREAD_SANITIZER +# endif #endif #ifndef AO_ATTR_NO_SANITIZE_MEMORY @@ -211,6 +214,15 @@ # endif #endif /* !AO_ATTR_NO_SANITIZE_MEMORY */ +#ifndef AO_ATTR_NO_SANITIZE_THREAD +# if defined(AO_THREAD_SANITIZER) \ + && (!defined(__clang__) || AO_CLANG_PREREQ(3, 8)) +# define AO_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread"))) +# else +# define AO_ATTR_NO_SANITIZE_THREAD /* empty */ +# endif +#endif /* !AO_ATTR_NO_SANITIZE_THREAD */ + #if defined(__GNUC__) && !defined(__INTEL_COMPILER) # define AO_compiler_barrier() __asm__ __volatile__("" : : : "memory") #elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \ diff --git a/src/atomic_ops/generalize-arithm.h b/src/atomic_ops/generalize-arithm.h index e925b10..27ccf9b 100644 --- a/src/atomic_ops/generalize-arithm.h +++ b/src/atomic_ops/generalize-arithm.h @@ -135,6 +135,7 @@ && !defined(AO_HAVE_char_fetch_and_add_full) AO_INLINE unsigned/**/char AO_char_fetch_and_add_full(volatile unsigned/**/char *addr, unsigned/**/char incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -153,6 +154,7 @@ && !defined(AO_HAVE_char_fetch_and_add_acquire) AO_INLINE unsigned/**/char AO_char_fetch_and_add_acquire(volatile unsigned/**/char *addr, unsigned/**/char incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -171,6 +173,7 @@ && !defined(AO_HAVE_char_fetch_and_add_release) AO_INLINE unsigned/**/char AO_char_fetch_and_add_release(volatile unsigned/**/char *addr, unsigned/**/char incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -189,6 +192,7 @@ && !defined(AO_HAVE_char_fetch_and_add) AO_INLINE unsigned/**/char AO_char_fetch_and_add(volatile unsigned/**/char *addr, unsigned/**/char incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -602,6 +606,7 @@ && !defined(AO_HAVE_char_and_full) AO_INLINE void AO_char_and_full(volatile unsigned/**/char *addr, unsigned/**/char value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -684,6 +689,7 @@ && !defined(AO_HAVE_char_or_full) AO_INLINE void AO_char_or_full(volatile unsigned/**/char *addr, unsigned/**/char value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -765,6 +771,7 @@ && !defined(AO_HAVE_char_xor_full) AO_INLINE void AO_char_xor_full(volatile unsigned/**/char *addr, unsigned/**/char value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old; @@ -980,6 +987,7 @@ && !defined(AO_HAVE_short_fetch_and_add_full) AO_INLINE unsigned/**/short AO_short_fetch_and_add_full(volatile unsigned/**/short *addr, unsigned/**/short incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -998,6 +1006,7 @@ && !defined(AO_HAVE_short_fetch_and_add_acquire) AO_INLINE unsigned/**/short AO_short_fetch_and_add_acquire(volatile unsigned/**/short *addr, unsigned/**/short incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -1016,6 +1025,7 @@ && !defined(AO_HAVE_short_fetch_and_add_release) AO_INLINE unsigned/**/short AO_short_fetch_and_add_release(volatile unsigned/**/short *addr, unsigned/**/short incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -1034,6 +1044,7 @@ && !defined(AO_HAVE_short_fetch_and_add) AO_INLINE unsigned/**/short AO_short_fetch_and_add(volatile unsigned/**/short *addr, unsigned/**/short incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -1447,6 +1458,7 @@ && !defined(AO_HAVE_short_and_full) AO_INLINE void AO_short_and_full(volatile unsigned/**/short *addr, unsigned/**/short value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -1529,6 +1541,7 @@ && !defined(AO_HAVE_short_or_full) AO_INLINE void AO_short_or_full(volatile unsigned/**/short *addr, unsigned/**/short value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -1610,6 +1623,7 @@ && !defined(AO_HAVE_short_xor_full) AO_INLINE void AO_short_xor_full(volatile unsigned/**/short *addr, unsigned/**/short value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old; @@ -1825,6 +1839,7 @@ && !defined(AO_HAVE_int_fetch_and_add_full) AO_INLINE unsigned AO_int_fetch_and_add_full(volatile unsigned *addr, unsigned incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -1843,6 +1858,7 @@ && !defined(AO_HAVE_int_fetch_and_add_acquire) AO_INLINE unsigned AO_int_fetch_and_add_acquire(volatile unsigned *addr, unsigned incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -1861,6 +1877,7 @@ && !defined(AO_HAVE_int_fetch_and_add_release) AO_INLINE unsigned AO_int_fetch_and_add_release(volatile unsigned *addr, unsigned incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -1879,6 +1896,7 @@ && !defined(AO_HAVE_int_fetch_and_add) AO_INLINE unsigned AO_int_fetch_and_add(volatile unsigned *addr, unsigned incr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -2292,6 +2310,7 @@ && !defined(AO_HAVE_int_and_full) AO_INLINE void AO_int_and_full(volatile unsigned *addr, unsigned value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -2374,6 +2393,7 @@ && !defined(AO_HAVE_int_or_full) AO_INLINE void AO_int_or_full(volatile unsigned *addr, unsigned value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -2455,6 +2475,7 @@ && !defined(AO_HAVE_int_xor_full) AO_INLINE void AO_int_xor_full(volatile unsigned *addr, unsigned value) + AO_ATTR_NO_SANITIZE_THREAD { unsigned old; @@ -2670,6 +2691,7 @@ && !defined(AO_HAVE_fetch_and_add_full) AO_INLINE AO_t AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; @@ -2688,6 +2710,7 @@ && !defined(AO_HAVE_fetch_and_add_acquire) AO_INLINE AO_t AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; @@ -2706,6 +2729,7 @@ && !defined(AO_HAVE_fetch_and_add_release) AO_INLINE AO_t AO_fetch_and_add_release(volatile AO_t *addr, AO_t incr) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; @@ -2724,6 +2748,7 @@ && !defined(AO_HAVE_fetch_and_add) AO_INLINE AO_t AO_fetch_and_add(volatile AO_t *addr, AO_t incr) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; @@ -3137,6 +3162,7 @@ && !defined(AO_HAVE_and_full) AO_INLINE void AO_and_full(volatile AO_t *addr, AO_t value) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; @@ -3219,6 +3245,7 @@ && !defined(AO_HAVE_or_full) AO_INLINE void AO_or_full(volatile AO_t *addr, AO_t value) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; @@ -3300,6 +3327,7 @@ && !defined(AO_HAVE_xor_full) AO_INLINE void AO_xor_full(volatile AO_t *addr, AO_t value) + AO_ATTR_NO_SANITIZE_THREAD { AO_t old; diff --git a/src/atomic_ops/generalize-arithm.template b/src/atomic_ops/generalize-arithm.template index 24161a4..69735fd 100644 --- a/src/atomic_ops/generalize-arithm.template +++ b/src/atomic_ops/generalize-arithm.template @@ -135,6 +135,7 @@ && !defined(AO_HAVE_XSIZE_fetch_and_add_full) AO_INLINE XCTYPE AO_XSIZE_fetch_and_add_full(volatile XCTYPE *addr, XCTYPE incr) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; @@ -153,6 +154,7 @@ && !defined(AO_HAVE_XSIZE_fetch_and_add_acquire) AO_INLINE XCTYPE AO_XSIZE_fetch_and_add_acquire(volatile XCTYPE *addr, XCTYPE incr) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; @@ -171,6 +173,7 @@ && !defined(AO_HAVE_XSIZE_fetch_and_add_release) AO_INLINE XCTYPE AO_XSIZE_fetch_and_add_release(volatile XCTYPE *addr, XCTYPE incr) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; @@ -189,6 +192,7 @@ && !defined(AO_HAVE_XSIZE_fetch_and_add) AO_INLINE XCTYPE AO_XSIZE_fetch_and_add(volatile XCTYPE *addr, XCTYPE incr) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; @@ -602,6 +606,7 @@ && !defined(AO_HAVE_XSIZE_and_full) AO_INLINE void AO_XSIZE_and_full(volatile XCTYPE *addr, XCTYPE value) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; @@ -684,6 +689,7 @@ && !defined(AO_HAVE_XSIZE_or_full) AO_INLINE void AO_XSIZE_or_full(volatile XCTYPE *addr, XCTYPE value) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; @@ -765,6 +771,7 @@ && !defined(AO_HAVE_XSIZE_xor_full) AO_INLINE void AO_XSIZE_xor_full(volatile XCTYPE *addr, XCTYPE value) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old; diff --git a/src/atomic_ops/generalize-small.h b/src/atomic_ops/generalize-small.h index 94538af..8e26abf 100644 --- a/src/atomic_ops/generalize-small.h +++ b/src/atomic_ops/generalize-small.h @@ -313,7 +313,7 @@ && !defined(AO_HAVE_char_load_read) # define AO_char_CAS_BASED_LOAD_READ AO_INLINE unsigned/**/char - AO_char_load_read(const volatile unsigned/**/char *addr) + AO_char_load_read(const volatile unsigned/**/char *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char result; @@ -343,7 +343,7 @@ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_load_full) AO_INLINE unsigned/**/char - AO_char_load_full(const volatile unsigned/**/char *addr) + AO_char_load_full(const volatile unsigned/**/char *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char result; @@ -361,6 +361,7 @@ && !defined(AO_HAVE_char_load_acquire) AO_INLINE unsigned/**/char AO_char_load_acquire(const volatile unsigned/**/char *addr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char result; @@ -376,7 +377,7 @@ #if defined(AO_HAVE_char_compare_and_swap) && !defined(AO_HAVE_char_load) AO_INLINE unsigned/**/char - AO_char_load(const volatile unsigned/**/char *addr) + AO_char_load(const volatile unsigned/**/char *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char result; @@ -449,7 +450,7 @@ && !defined(AO_HAVE_char_store_write) AO_INLINE void AO_char_store_write(volatile unsigned/**/char *addr, unsigned/**/char new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old_val; @@ -479,7 +480,7 @@ #if defined(AO_HAVE_char_compare_and_swap) && !defined(AO_HAVE_char_store) AO_INLINE void AO_char_store(volatile unsigned/**/char *addr, unsigned/**/char new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old_val; @@ -495,7 +496,7 @@ && !defined(AO_HAVE_char_store_release) AO_INLINE void AO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old_val; @@ -511,7 +512,7 @@ && !defined(AO_HAVE_char_store_full) AO_INLINE void AO_char_store_full(volatile unsigned/**/char *addr, unsigned/**/char new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/char old_val; @@ -837,7 +838,7 @@ && !defined(AO_HAVE_short_load_read) # define AO_short_CAS_BASED_LOAD_READ AO_INLINE unsigned/**/short - AO_short_load_read(const volatile unsigned/**/short *addr) + AO_short_load_read(const volatile unsigned/**/short *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short result; @@ -867,7 +868,7 @@ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_load_full) AO_INLINE unsigned/**/short - AO_short_load_full(const volatile unsigned/**/short *addr) + AO_short_load_full(const volatile unsigned/**/short *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short result; @@ -885,6 +886,7 @@ && !defined(AO_HAVE_short_load_acquire) AO_INLINE unsigned/**/short AO_short_load_acquire(const volatile unsigned/**/short *addr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short result; @@ -900,7 +902,7 @@ #if defined(AO_HAVE_short_compare_and_swap) && !defined(AO_HAVE_short_load) AO_INLINE unsigned/**/short - AO_short_load(const volatile unsigned/**/short *addr) + AO_short_load(const volatile unsigned/**/short *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short result; @@ -973,7 +975,7 @@ && !defined(AO_HAVE_short_store_write) AO_INLINE void AO_short_store_write(volatile unsigned/**/short *addr, unsigned/**/short new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old_val; @@ -1003,7 +1005,7 @@ #if defined(AO_HAVE_short_compare_and_swap) && !defined(AO_HAVE_short_store) AO_INLINE void AO_short_store(volatile unsigned/**/short *addr, unsigned/**/short new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old_val; @@ -1019,7 +1021,7 @@ && !defined(AO_HAVE_short_store_release) AO_INLINE void AO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old_val; @@ -1035,7 +1037,7 @@ && !defined(AO_HAVE_short_store_full) AO_INLINE void AO_short_store_full(volatile unsigned/**/short *addr, unsigned/**/short new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned/**/short old_val; @@ -1361,7 +1363,7 @@ && !defined(AO_HAVE_int_load_read) # define AO_int_CAS_BASED_LOAD_READ AO_INLINE unsigned - AO_int_load_read(const volatile unsigned *addr) + AO_int_load_read(const volatile unsigned *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned result; @@ -1391,7 +1393,7 @@ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_load_full) AO_INLINE unsigned - AO_int_load_full(const volatile unsigned *addr) + AO_int_load_full(const volatile unsigned *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned result; @@ -1409,6 +1411,7 @@ && !defined(AO_HAVE_int_load_acquire) AO_INLINE unsigned AO_int_load_acquire(const volatile unsigned *addr) + AO_ATTR_NO_SANITIZE_THREAD { unsigned result; @@ -1424,7 +1427,7 @@ #if defined(AO_HAVE_int_compare_and_swap) && !defined(AO_HAVE_int_load) AO_INLINE unsigned - AO_int_load(const volatile unsigned *addr) + AO_int_load(const volatile unsigned *addr) AO_ATTR_NO_SANITIZE_THREAD { unsigned result; @@ -1497,7 +1500,7 @@ && !defined(AO_HAVE_int_store_write) AO_INLINE void AO_int_store_write(volatile unsigned *addr, unsigned new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned old_val; @@ -1527,7 +1530,7 @@ #if defined(AO_HAVE_int_compare_and_swap) && !defined(AO_HAVE_int_store) AO_INLINE void AO_int_store(volatile unsigned *addr, unsigned new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned old_val; @@ -1543,7 +1546,7 @@ && !defined(AO_HAVE_int_store_release) AO_INLINE void AO_int_store_release(volatile unsigned *addr, unsigned new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned old_val; @@ -1559,7 +1562,7 @@ && !defined(AO_HAVE_int_store_full) AO_INLINE void AO_int_store_full(volatile unsigned *addr, unsigned new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { unsigned old_val; @@ -1885,7 +1888,7 @@ && !defined(AO_HAVE_load_read) # define AO_CAS_BASED_LOAD_READ AO_INLINE AO_t - AO_load_read(const volatile AO_t *addr) + AO_load_read(const volatile AO_t *addr) AO_ATTR_NO_SANITIZE_THREAD { AO_t result; @@ -1915,7 +1918,7 @@ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_load_full) AO_INLINE AO_t - AO_load_full(const volatile AO_t *addr) + AO_load_full(const volatile AO_t *addr) AO_ATTR_NO_SANITIZE_THREAD { AO_t result; @@ -1933,6 +1936,7 @@ && !defined(AO_HAVE_load_acquire) AO_INLINE AO_t AO_load_acquire(const volatile AO_t *addr) + AO_ATTR_NO_SANITIZE_THREAD { AO_t result; @@ -1948,7 +1952,7 @@ #if defined(AO_HAVE_compare_and_swap) && !defined(AO_HAVE_load) AO_INLINE AO_t - AO_load(const volatile AO_t *addr) + AO_load(const volatile AO_t *addr) AO_ATTR_NO_SANITIZE_THREAD { AO_t result; @@ -2021,7 +2025,7 @@ && !defined(AO_HAVE_store_write) AO_INLINE void AO_store_write(volatile AO_t *addr, AO_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_t old_val; @@ -2051,7 +2055,7 @@ #if defined(AO_HAVE_compare_and_swap) && !defined(AO_HAVE_store) AO_INLINE void AO_store(volatile AO_t *addr, AO_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_t old_val; @@ -2067,7 +2071,7 @@ && !defined(AO_HAVE_store_release) AO_INLINE void AO_store_release(volatile AO_t *addr, AO_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_t old_val; @@ -2083,7 +2087,7 @@ && !defined(AO_HAVE_store_full) AO_INLINE void AO_store_full(volatile AO_t *addr, AO_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_t old_val; @@ -2409,7 +2413,7 @@ && !defined(AO_HAVE_double_load_read) # define AO_double_CAS_BASED_LOAD_READ AO_INLINE AO_double_t - AO_double_load_read(const volatile AO_double_t *addr) + AO_double_load_read(const volatile AO_double_t *addr) AO_ATTR_NO_SANITIZE_THREAD { AO_double_t result; @@ -2439,7 +2443,7 @@ #if defined(AO_HAVE_double_compare_and_swap_full) \ && !defined(AO_HAVE_double_load_full) AO_INLINE AO_double_t - AO_double_load_full(const volatile AO_double_t *addr) + AO_double_load_full(const volatile AO_double_t *addr) AO_ATTR_NO_SANITIZE_THREAD { AO_double_t result; @@ -2457,6 +2461,7 @@ && !defined(AO_HAVE_double_load_acquire) AO_INLINE AO_double_t AO_double_load_acquire(const volatile AO_double_t *addr) + AO_ATTR_NO_SANITIZE_THREAD { AO_double_t result; @@ -2472,7 +2477,7 @@ #if defined(AO_HAVE_double_compare_and_swap) && !defined(AO_HAVE_double_load) AO_INLINE AO_double_t - AO_double_load(const volatile AO_double_t *addr) + AO_double_load(const volatile AO_double_t *addr) AO_ATTR_NO_SANITIZE_THREAD { AO_double_t result; @@ -2545,7 +2550,7 @@ && !defined(AO_HAVE_double_store_write) AO_INLINE void AO_double_store_write(volatile AO_double_t *addr, AO_double_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_double_t old_val; @@ -2575,7 +2580,7 @@ #if defined(AO_HAVE_double_compare_and_swap) && !defined(AO_HAVE_double_store) AO_INLINE void AO_double_store(volatile AO_double_t *addr, AO_double_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_double_t old_val; @@ -2591,7 +2596,7 @@ && !defined(AO_HAVE_double_store_release) AO_INLINE void AO_double_store_release(volatile AO_double_t *addr, AO_double_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_double_t old_val; @@ -2607,7 +2612,7 @@ && !defined(AO_HAVE_double_store_full) AO_INLINE void AO_double_store_full(volatile AO_double_t *addr, AO_double_t new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { AO_double_t old_val; diff --git a/src/atomic_ops/generalize-small.template b/src/atomic_ops/generalize-small.template index 328f43e..99e96a1 100644 --- a/src/atomic_ops/generalize-small.template +++ b/src/atomic_ops/generalize-small.template @@ -313,7 +313,7 @@ && !defined(AO_HAVE_XSIZE_load_read) # define AO_XSIZE_CAS_BASED_LOAD_READ AO_INLINE XCTYPE - AO_XSIZE_load_read(const volatile XCTYPE *addr) + AO_XSIZE_load_read(const volatile XCTYPE *addr) AO_ATTR_NO_SANITIZE_THREAD { XCTYPE result; @@ -343,7 +343,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_load_full) AO_INLINE XCTYPE - AO_XSIZE_load_full(const volatile XCTYPE *addr) + AO_XSIZE_load_full(const volatile XCTYPE *addr) AO_ATTR_NO_SANITIZE_THREAD { XCTYPE result; @@ -361,6 +361,7 @@ && !defined(AO_HAVE_XSIZE_load_acquire) AO_INLINE XCTYPE AO_XSIZE_load_acquire(const volatile XCTYPE *addr) + AO_ATTR_NO_SANITIZE_THREAD { XCTYPE result; @@ -376,7 +377,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap) && !defined(AO_HAVE_XSIZE_load) AO_INLINE XCTYPE - AO_XSIZE_load(const volatile XCTYPE *addr) + AO_XSIZE_load(const volatile XCTYPE *addr) AO_ATTR_NO_SANITIZE_THREAD { XCTYPE result; @@ -449,7 +450,7 @@ && !defined(AO_HAVE_XSIZE_store_write) AO_INLINE void AO_XSIZE_store_write(volatile XCTYPE *addr, XCTYPE new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old_val; @@ -479,7 +480,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap) && !defined(AO_HAVE_XSIZE_store) AO_INLINE void AO_XSIZE_store(volatile XCTYPE *addr, XCTYPE new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old_val; @@ -495,7 +496,7 @@ && !defined(AO_HAVE_XSIZE_store_release) AO_INLINE void AO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old_val; @@ -511,7 +512,7 @@ && !defined(AO_HAVE_XSIZE_store_full) AO_INLINE void AO_XSIZE_store_full(volatile XCTYPE *addr, XCTYPE new_val) - AO_ATTR_NO_SANITIZE_MEMORY + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD { XCTYPE old_val; diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index 3ab1f76..f3c7d87 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -28,12 +28,13 @@ || (defined(__x86_64__) && !defined(__ILP32__) \ && (!(AO_CLANG_PREREQ(3, 5) \ || defined(AO_PREFER_BUILTIN_ATOMICS)) \ - || defined(AO_ADDRESS_SANITIZER)))) + || defined(AO_ADDRESS_SANITIZER) \ + || defined(AO_THREAD_SANITIZER)))) /* As of clang-3.8 i686 (NDK r11c), it requires -latomic for all */ /* the double-wide operations. Same for clang-3.4/x64. For now, */ /* we fall back to the non-intrinsic implementation by default. */ - /* As of clang-3.8, double-wide arguments are incorrectly passed to */ - /* atomic intrinsic operations for x64 target if ASan is enabled. */ + /* As of clang-4.0, double-wide arguments are incorrectly passed to */ + /* atomic intrinsic operations for x64 target if ASan/TSan enabled. */ # define AO_SKIPATOMIC_double_compare_and_swap_ANY # define AO_SKIPATOMIC_double_load # define AO_SKIPATOMIC_double_load_acquire diff --git a/src/atomic_ops_malloc.c b/src/atomic_ops_malloc.c index 4748e6a..30703ab 100644 --- a/src/atomic_ops_malloc.c +++ b/src/atomic_ops_malloc.c @@ -310,7 +310,11 @@ AO_malloc(size_t sz) add_chunk_as(chunk, log_sz); result = AO_stack_pop(AO_free_list+log_sz); } - *result = log_sz; +# ifdef AO_THREAD_SANITIZER + AO_store(result, log_sz); +# else + *result = log_sz; +# endif # ifdef AO_TRACE_MALLOC fprintf(stderr, "%p: AO_malloc(%lu) = %p\n", (void *)pthread_self(), (unsigned long)sz, (void *)(result + 1)); @@ -327,7 +331,11 @@ AO_free(void *p) if (0 == p) return; base = (AO_t *)p - 1; - log_sz = (int)(*base); +# ifdef AO_THREAD_SANITIZER + log_sz = (int)AO_load(base); +# else + log_sz = (int)(*base); +# endif # ifdef AO_TRACE_MALLOC fprintf(stderr, "%p: AO_free(%p sz:%lu)\n", (void *)pthread_self(), p, log_sz > LOG_MAX_SIZE ? (unsigned)log_sz : 1UL << log_sz); diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c index c14c47c..e1df09c 100644 --- a/src/atomic_ops_stack.c +++ b/src/atomic_ops_stack.c @@ -48,7 +48,7 @@ /* pointers with extra bits "or"ed into the low order bits. */ void AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, - AO_stack_aux *a) + AO_stack_aux *a) AO_ATTR_NO_SANITIZE_THREAD { AO_t x_bits = (AO_t)x; AO_t next; @@ -94,7 +94,7 @@ AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, do { next = AO_load(list); - *x = next; + *x = next; /* data race is OK here */ } while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(list, next, x_bits))); } @@ -203,12 +203,13 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) #endif void AO_stack_push_release(AO_stack_t *list, AO_t *element) + AO_ATTR_NO_SANITIZE_THREAD { AO_t next; do { next = AO_load(&(list -> ptr)); - *element = next; + *element = next; /* data race is OK here */ } while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(&(list -> ptr), next, (AO_t)element))); /* This uses a narrow CAS here, an old optimization suggested */ @@ -221,7 +222,7 @@ void AO_stack_push_release(AO_stack_t *list, AO_t *element) # endif } -AO_t *AO_stack_pop_acquire(AO_stack_t *list) +AO_t *AO_stack_pop_acquire(AO_stack_t *list) AO_ATTR_NO_SANITIZE_THREAD { # ifdef __clang__ AO_t *volatile cptr; @@ -238,7 +239,7 @@ AO_t *AO_stack_pop_acquire(AO_stack_t *list) cversion = AO_load_acquire(&(list -> version)); cptr = (AO_t *)AO_load(&(list -> ptr)); if (cptr == 0) return 0; - next = *cptr; + next = *cptr; /* data race is OK here */ } while (AO_EXPECT_FALSE(!AO_compare_double_and_swap_double_release(list, cversion, (AO_t)cptr, cversion+1, (AO_t)next))); diff --git a/tests/test_atomic.c b/tests/test_atomic.c index 5a25dac..8b57bd6 100644 --- a/tests/test_atomic.c +++ b/tests/test_atomic.c @@ -137,6 +137,12 @@ AO_TS_t lock = AO_TS_INITIALIZER; unsigned long locked_counter; volatile unsigned long junk = 13; +void do_junk(void) AO_ATTR_NO_SANITIZE_THREAD +{ + junk *= 17; + junk *= 19; +} + void * test_and_set_thr(void * id) { unsigned long i; @@ -164,8 +170,7 @@ void * test_and_set_thr(void * id) --locked_counter; AO_CLEAR(&lock); /* Spend a bit of time outside the lock. */ - junk *= 17; - junk *= 17; + do_junk(); } return 0; } diff --git a/tests/test_malloc.c b/tests/test_malloc.c index e9d924a..b51d4fb 100644 --- a/tests/test_malloc.c +++ b/tests/test_malloc.c @@ -68,9 +68,9 @@ typedef struct list_node { int data; } ln; -ln *cons(int d, ln *tail) +ln *cons(int d, ln *tail) AO_ATTR_NO_SANITIZE_THREAD { - static size_t extra = 0; + static size_t extra = 0; /* data race in extra is OK */ size_t my_extra = extra; ln *result; int * extras; -- 2.7.4