# 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
# 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__) \
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
&& !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;
#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;
&& !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;
#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;
&& !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;
#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;
&& !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;
&& !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;
&& !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;
#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;
&& !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;
#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;
&& !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;
#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;
&& !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;
&& !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;
&& !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;
#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;
&& !defined(AO_HAVE_int_load_acquire)
AO_INLINE unsigned
AO_int_load_acquire(const volatile unsigned *addr)
+ AO_ATTR_NO_SANITIZE_THREAD
{
unsigned result;
#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;
&& !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;
#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;
&& !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;
&& !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;
&& !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;
#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;
&& !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;
#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;
&& !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;
#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;
&& !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;
&& !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;
&& !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;
#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;
&& !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;
#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;
&& !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;
#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;
&& !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;
&& !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;
&& !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;
#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;
&& !defined(AO_HAVE_XSIZE_load_acquire)
AO_INLINE XCTYPE
AO_XSIZE_load_acquire(const volatile XCTYPE *addr)
+ AO_ATTR_NO_SANITIZE_THREAD
{
XCTYPE result;
#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;
&& !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;
#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;
&& !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;
&& !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;
|| (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
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));
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);
/* 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;
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)));
}
#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 */
# 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;
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)));
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;
--locked_counter;
AO_CLEAR(&lock);
/* Spend a bit of time outside the lock. */
- junk *= 17;
- junk *= 17;
+ do_junk();
}
return 0;
}
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;