• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- tsan_interface_atomic.cc ------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 // ThreadSanitizer atomic operations are based on C++11/C1x standards.
15 // For background see C++11 standard.  A slightly older, publicly
16 // available draft of the standard (not entirely up-to-date, but close enough
17 // for casual browsing) is available here:
18 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
19 // The following page contains more background information:
20 // http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
21 
22 #include "sanitizer_common/sanitizer_placement_new.h"
23 #include "sanitizer_common/sanitizer_stacktrace.h"
24 #include "sanitizer_common/sanitizer_mutex.h"
25 #include "tsan_flags.h"
26 #include "tsan_rtl.h"
27 
28 using namespace __tsan;  // NOLINT
29 
30 #define SCOPED_ATOMIC(func, ...) \
31     const uptr callpc = (uptr)__builtin_return_address(0); \
32     uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
33     mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
34     ThreadState *const thr = cur_thread(); \
35     if (thr->ignore_interceptors) \
36       return NoTsanAtomic##func(__VA_ARGS__); \
37     AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
38     ScopedAtomic sa(thr, callpc, a, mo, __func__); \
39     return Atomic##func(thr, pc, __VA_ARGS__); \
40 /**/
41 
42 // These should match declarations from public tsan_interface_atomic.h header.
43 typedef unsigned char      a8;
44 typedef unsigned short     a16;  // NOLINT
45 typedef unsigned int       a32;
46 typedef unsigned long long a64;  // NOLINT
47 #if defined(__SIZEOF_INT128__) \
48     || (__clang_major__ * 100 + __clang_minor__ >= 302)
49 __extension__ typedef __int128 a128;
50 # define __TSAN_HAS_INT128 1
51 #else
52 # define __TSAN_HAS_INT128 0
53 #endif
54 
55 // Protects emulation of 128-bit atomic operations.
56 static StaticSpinMutex mutex128;
57 
58 // Part of ABI, do not change.
59 // http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/atomic?view=markup
60 typedef enum {
61   mo_relaxed,
62   mo_consume,
63   mo_acquire,
64   mo_release,
65   mo_acq_rel,
66   mo_seq_cst
67 } morder;
68 
69 class ScopedAtomic {
70  public:
ScopedAtomic(ThreadState * thr,uptr pc,const volatile void * a,morder mo,const char * func)71   ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
72                morder mo, const char *func)
73       : thr_(thr) {
74     FuncEntry(thr_, pc);
75     DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
76   }
~ScopedAtomic()77   ~ScopedAtomic() {
78     ProcessPendingSignals(thr_);
79     FuncExit(thr_);
80   }
81  private:
82   ThreadState *thr_;
83 };
84 
AtomicStatInc(ThreadState * thr,uptr size,morder mo,StatType t)85 static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) {
86   StatInc(thr, StatAtomic);
87   StatInc(thr, t);
88   StatInc(thr, size == 1 ? StatAtomic1
89              : size == 2 ? StatAtomic2
90              : size == 4 ? StatAtomic4
91              : size == 8 ? StatAtomic8
92              :             StatAtomic16);
93   StatInc(thr, mo == mo_relaxed ? StatAtomicRelaxed
94              : mo == mo_consume ? StatAtomicConsume
95              : mo == mo_acquire ? StatAtomicAcquire
96              : mo == mo_release ? StatAtomicRelease
97              : mo == mo_acq_rel ? StatAtomicAcq_Rel
98              :                    StatAtomicSeq_Cst);
99 }
100 
IsLoadOrder(morder mo)101 static bool IsLoadOrder(morder mo) {
102   return mo == mo_relaxed || mo == mo_consume
103       || mo == mo_acquire || mo == mo_seq_cst;
104 }
105 
IsStoreOrder(morder mo)106 static bool IsStoreOrder(morder mo) {
107   return mo == mo_relaxed || mo == mo_release || mo == mo_seq_cst;
108 }
109 
IsReleaseOrder(morder mo)110 static bool IsReleaseOrder(morder mo) {
111   return mo == mo_release || mo == mo_acq_rel || mo == mo_seq_cst;
112 }
113 
IsAcquireOrder(morder mo)114 static bool IsAcquireOrder(morder mo) {
115   return mo == mo_consume || mo == mo_acquire
116       || mo == mo_acq_rel || mo == mo_seq_cst;
117 }
118 
IsAcqRelOrder(morder mo)119 static bool IsAcqRelOrder(morder mo) {
120   return mo == mo_acq_rel || mo == mo_seq_cst;
121 }
122 
func_xchg(volatile T * v,T op)123 template<typename T> T func_xchg(volatile T *v, T op) {
124   T res = __sync_lock_test_and_set(v, op);
125   // __sync_lock_test_and_set does not contain full barrier.
126   __sync_synchronize();
127   return res;
128 }
129 
func_add(volatile T * v,T op)130 template<typename T> T func_add(volatile T *v, T op) {
131   return __sync_fetch_and_add(v, op);
132 }
133 
func_sub(volatile T * v,T op)134 template<typename T> T func_sub(volatile T *v, T op) {
135   return __sync_fetch_and_sub(v, op);
136 }
137 
func_and(volatile T * v,T op)138 template<typename T> T func_and(volatile T *v, T op) {
139   return __sync_fetch_and_and(v, op);
140 }
141 
func_or(volatile T * v,T op)142 template<typename T> T func_or(volatile T *v, T op) {
143   return __sync_fetch_and_or(v, op);
144 }
145 
func_xor(volatile T * v,T op)146 template<typename T> T func_xor(volatile T *v, T op) {
147   return __sync_fetch_and_xor(v, op);
148 }
149 
func_nand(volatile T * v,T op)150 template<typename T> T func_nand(volatile T *v, T op) {
151   // clang does not support __sync_fetch_and_nand.
152   T cmp = *v;
153   for (;;) {
154     T newv = ~(cmp & op);
155     T cur = __sync_val_compare_and_swap(v, cmp, newv);
156     if (cmp == cur)
157       return cmp;
158     cmp = cur;
159   }
160 }
161 
func_cas(volatile T * v,T cmp,T xch)162 template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
163   return __sync_val_compare_and_swap(v, cmp, xch);
164 }
165 
166 // clang does not support 128-bit atomic ops.
167 // Atomic ops are executed under tsan internal mutex,
168 // here we assume that the atomic variables are not accessed
169 // from non-instrumented code.
170 #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
func_xchg(volatile a128 * v,a128 op)171 a128 func_xchg(volatile a128 *v, a128 op) {
172   SpinMutexLock lock(&mutex128);
173   a128 cmp = *v;
174   *v = op;
175   return cmp;
176 }
177 
func_add(volatile a128 * v,a128 op)178 a128 func_add(volatile a128 *v, a128 op) {
179   SpinMutexLock lock(&mutex128);
180   a128 cmp = *v;
181   *v = cmp + op;
182   return cmp;
183 }
184 
func_sub(volatile a128 * v,a128 op)185 a128 func_sub(volatile a128 *v, a128 op) {
186   SpinMutexLock lock(&mutex128);
187   a128 cmp = *v;
188   *v = cmp - op;
189   return cmp;
190 }
191 
func_and(volatile a128 * v,a128 op)192 a128 func_and(volatile a128 *v, a128 op) {
193   SpinMutexLock lock(&mutex128);
194   a128 cmp = *v;
195   *v = cmp & op;
196   return cmp;
197 }
198 
func_or(volatile a128 * v,a128 op)199 a128 func_or(volatile a128 *v, a128 op) {
200   SpinMutexLock lock(&mutex128);
201   a128 cmp = *v;
202   *v = cmp | op;
203   return cmp;
204 }
205 
func_xor(volatile a128 * v,a128 op)206 a128 func_xor(volatile a128 *v, a128 op) {
207   SpinMutexLock lock(&mutex128);
208   a128 cmp = *v;
209   *v = cmp ^ op;
210   return cmp;
211 }
212 
func_nand(volatile a128 * v,a128 op)213 a128 func_nand(volatile a128 *v, a128 op) {
214   SpinMutexLock lock(&mutex128);
215   a128 cmp = *v;
216   *v = ~(cmp & op);
217   return cmp;
218 }
219 
func_cas(volatile a128 * v,a128 cmp,a128 xch)220 a128 func_cas(volatile a128 *v, a128 cmp, a128 xch) {
221   SpinMutexLock lock(&mutex128);
222   a128 cur = *v;
223   if (cur == cmp)
224     *v = xch;
225   return cur;
226 }
227 #endif
228 
229 template<typename T>
SizeLog()230 static int SizeLog() {
231   if (sizeof(T) <= 1)
232     return kSizeLog1;
233   else if (sizeof(T) <= 2)
234     return kSizeLog2;
235   else if (sizeof(T) <= 4)
236     return kSizeLog4;
237   else
238     return kSizeLog8;
239   // For 16-byte atomics we also use 8-byte memory access,
240   // this leads to false negatives only in very obscure cases.
241 }
242 
to_atomic(const volatile a8 * a)243 static atomic_uint8_t *to_atomic(const volatile a8 *a) {
244   return (atomic_uint8_t*)a;
245 }
246 
to_atomic(const volatile a16 * a)247 static atomic_uint16_t *to_atomic(const volatile a16 *a) {
248   return (atomic_uint16_t*)a;
249 }
250 
to_atomic(const volatile a32 * a)251 static atomic_uint32_t *to_atomic(const volatile a32 *a) {
252   return (atomic_uint32_t*)a;
253 }
254 
to_atomic(const volatile a64 * a)255 static atomic_uint64_t *to_atomic(const volatile a64 *a) {
256   return (atomic_uint64_t*)a;
257 }
258 
to_mo(morder mo)259 static memory_order to_mo(morder mo) {
260   switch (mo) {
261   case mo_relaxed: return memory_order_relaxed;
262   case mo_consume: return memory_order_consume;
263   case mo_acquire: return memory_order_acquire;
264   case mo_release: return memory_order_release;
265   case mo_acq_rel: return memory_order_acq_rel;
266   case mo_seq_cst: return memory_order_seq_cst;
267   }
268   CHECK(0);
269   return memory_order_seq_cst;
270 }
271 
272 template<typename T>
NoTsanAtomicLoad(const volatile T * a,morder mo)273 static T NoTsanAtomicLoad(const volatile T *a, morder mo) {
274   return atomic_load(to_atomic(a), to_mo(mo));
275 }
276 
277 #if __TSAN_HAS_INT128
NoTsanAtomicLoad(const volatile a128 * a,morder mo)278 static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
279   SpinMutexLock lock(&mutex128);
280   return *a;
281 }
282 #endif
283 
284 template<typename T>
AtomicLoad(ThreadState * thr,uptr pc,const volatile T * a,morder mo)285 static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a,
286     morder mo) {
287   CHECK(IsLoadOrder(mo));
288   // This fast-path is critical for performance.
289   // Assume the access is atomic.
290   if (!IsAcquireOrder(mo)) {
291     MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
292     return NoTsanAtomicLoad(a, mo);
293   }
294   SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, false);
295   AcquireImpl(thr, pc, &s->clock);
296   T v = NoTsanAtomicLoad(a, mo);
297   s->mtx.ReadUnlock();
298   MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
299   return v;
300 }
301 
302 template<typename T>
NoTsanAtomicStore(volatile T * a,T v,morder mo)303 static void NoTsanAtomicStore(volatile T *a, T v, morder mo) {
304   atomic_store(to_atomic(a), v, to_mo(mo));
305 }
306 
307 #if __TSAN_HAS_INT128
NoTsanAtomicStore(volatile a128 * a,a128 v,morder mo)308 static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
309   SpinMutexLock lock(&mutex128);
310   *a = v;
311 }
312 #endif
313 
314 template<typename T>
AtomicStore(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)315 static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
316     morder mo) {
317   CHECK(IsStoreOrder(mo));
318   MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
319   // This fast-path is critical for performance.
320   // Assume the access is atomic.
321   // Strictly saying even relaxed store cuts off release sequence,
322   // so must reset the clock.
323   if (!IsReleaseOrder(mo)) {
324     NoTsanAtomicStore(a, v, mo);
325     return;
326   }
327   __sync_synchronize();
328   SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
329   thr->fast_state.IncrementEpoch();
330   // Can't increment epoch w/o writing to the trace as well.
331   TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
332   ReleaseImpl(thr, pc, &s->clock);
333   NoTsanAtomicStore(a, v, mo);
334   s->mtx.Unlock();
335 }
336 
337 template<typename T, T (*F)(volatile T *v, T op)>
AtomicRMW(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)338 static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
339   MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
340   SyncVar *s = 0;
341   if (mo != mo_relaxed) {
342     s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
343     thr->fast_state.IncrementEpoch();
344     // Can't increment epoch w/o writing to the trace as well.
345     TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
346     if (IsAcqRelOrder(mo))
347       AcquireReleaseImpl(thr, pc, &s->clock);
348     else if (IsReleaseOrder(mo))
349       ReleaseImpl(thr, pc, &s->clock);
350     else if (IsAcquireOrder(mo))
351       AcquireImpl(thr, pc, &s->clock);
352   }
353   v = F(a, v);
354   if (s)
355     s->mtx.Unlock();
356   return v;
357 }
358 
359 template<typename T>
NoTsanAtomicExchange(volatile T * a,T v,morder mo)360 static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) {
361   return func_xchg(a, v);
362 }
363 
364 template<typename T>
NoTsanAtomicFetchAdd(volatile T * a,T v,morder mo)365 static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) {
366   return func_add(a, v);
367 }
368 
369 template<typename T>
NoTsanAtomicFetchSub(volatile T * a,T v,morder mo)370 static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) {
371   return func_sub(a, v);
372 }
373 
374 template<typename T>
NoTsanAtomicFetchAnd(volatile T * a,T v,morder mo)375 static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) {
376   return func_and(a, v);
377 }
378 
379 template<typename T>
NoTsanAtomicFetchOr(volatile T * a,T v,morder mo)380 static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) {
381   return func_or(a, v);
382 }
383 
384 template<typename T>
NoTsanAtomicFetchXor(volatile T * a,T v,morder mo)385 static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) {
386   return func_xor(a, v);
387 }
388 
389 template<typename T>
NoTsanAtomicFetchNand(volatile T * a,T v,morder mo)390 static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) {
391   return func_nand(a, v);
392 }
393 
394 template<typename T>
AtomicExchange(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)395 static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v,
396     morder mo) {
397   return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);
398 }
399 
400 template<typename T>
AtomicFetchAdd(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)401 static T AtomicFetchAdd(ThreadState *thr, uptr pc, volatile T *a, T v,
402     morder mo) {
403   return AtomicRMW<T, func_add>(thr, pc, a, v, mo);
404 }
405 
406 template<typename T>
AtomicFetchSub(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)407 static T AtomicFetchSub(ThreadState *thr, uptr pc, volatile T *a, T v,
408     morder mo) {
409   return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
410 }
411 
412 template<typename T>
AtomicFetchAnd(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)413 static T AtomicFetchAnd(ThreadState *thr, uptr pc, volatile T *a, T v,
414     morder mo) {
415   return AtomicRMW<T, func_and>(thr, pc, a, v, mo);
416 }
417 
418 template<typename T>
AtomicFetchOr(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)419 static T AtomicFetchOr(ThreadState *thr, uptr pc, volatile T *a, T v,
420     morder mo) {
421   return AtomicRMW<T, func_or>(thr, pc, a, v, mo);
422 }
423 
424 template<typename T>
AtomicFetchXor(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)425 static T AtomicFetchXor(ThreadState *thr, uptr pc, volatile T *a, T v,
426     morder mo) {
427   return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
428 }
429 
430 template<typename T>
AtomicFetchNand(ThreadState * thr,uptr pc,volatile T * a,T v,morder mo)431 static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v,
432     morder mo) {
433   return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
434 }
435 
436 template<typename T>
NoTsanAtomicCAS(volatile T * a,T * c,T v,morder mo,morder fmo)437 static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) {
438   return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));
439 }
440 
441 #if __TSAN_HAS_INT128
NoTsanAtomicCAS(volatile a128 * a,a128 * c,a128 v,morder mo,morder fmo)442 static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v,
443     morder mo, morder fmo) {
444   a128 old = *c;
445   a128 cur = func_cas(a, old, v);
446   if (cur == old)
447     return true;
448   *c = cur;
449   return false;
450 }
451 #endif
452 
453 template<typename T>
NoTsanAtomicCAS(volatile T * a,T c,T v,morder mo,morder fmo)454 static bool NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
455   return NoTsanAtomicCAS(a, &c, v, mo, fmo);
456 }
457 
458 template<typename T>
AtomicCAS(ThreadState * thr,uptr pc,volatile T * a,T * c,T v,morder mo,morder fmo)459 static bool AtomicCAS(ThreadState *thr, uptr pc,
460     volatile T *a, T *c, T v, morder mo, morder fmo) {
461   (void)fmo;  // Unused because llvm does not pass it yet.
462   MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
463   SyncVar *s = 0;
464   bool write_lock = mo != mo_acquire && mo != mo_consume;
465   if (mo != mo_relaxed) {
466     s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock);
467     thr->fast_state.IncrementEpoch();
468     // Can't increment epoch w/o writing to the trace as well.
469     TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
470     if (IsAcqRelOrder(mo))
471       AcquireReleaseImpl(thr, pc, &s->clock);
472     else if (IsReleaseOrder(mo))
473       ReleaseImpl(thr, pc, &s->clock);
474     else if (IsAcquireOrder(mo))
475       AcquireImpl(thr, pc, &s->clock);
476   }
477   T cc = *c;
478   T pr = func_cas(a, cc, v);
479   if (s) {
480     if (write_lock)
481       s->mtx.Unlock();
482     else
483       s->mtx.ReadUnlock();
484   }
485   if (pr == cc)
486     return true;
487   *c = pr;
488   return false;
489 }
490 
491 template<typename T>
AtomicCAS(ThreadState * thr,uptr pc,volatile T * a,T c,T v,morder mo,morder fmo)492 static T AtomicCAS(ThreadState *thr, uptr pc,
493     volatile T *a, T c, T v, morder mo, morder fmo) {
494   AtomicCAS(thr, pc, a, &c, v, mo, fmo);
495   return c;
496 }
497 
NoTsanAtomicFence(morder mo)498 static void NoTsanAtomicFence(morder mo) {
499   __sync_synchronize();
500 }
501 
AtomicFence(ThreadState * thr,uptr pc,morder mo)502 static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
503   // FIXME(dvyukov): not implemented.
504   __sync_synchronize();
505 }
506 
507 extern "C" {
508 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_load(const volatile a8 * a,morder mo)509 a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
510   SCOPED_ATOMIC(Load, a, mo);
511 }
512 
513 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_load(const volatile a16 * a,morder mo)514 a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
515   SCOPED_ATOMIC(Load, a, mo);
516 }
517 
518 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_load(const volatile a32 * a,morder mo)519 a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
520   SCOPED_ATOMIC(Load, a, mo);
521 }
522 
523 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_load(const volatile a64 * a,morder mo)524 a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
525   SCOPED_ATOMIC(Load, a, mo);
526 }
527 
528 #if __TSAN_HAS_INT128
529 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_load(const volatile a128 * a,morder mo)530 a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
531   SCOPED_ATOMIC(Load, a, mo);
532 }
533 #endif
534 
535 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_store(volatile a8 * a,a8 v,morder mo)536 void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
537   SCOPED_ATOMIC(Store, a, v, mo);
538 }
539 
540 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_store(volatile a16 * a,a16 v,morder mo)541 void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
542   SCOPED_ATOMIC(Store, a, v, mo);
543 }
544 
545 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_store(volatile a32 * a,a32 v,morder mo)546 void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
547   SCOPED_ATOMIC(Store, a, v, mo);
548 }
549 
550 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_store(volatile a64 * a,a64 v,morder mo)551 void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
552   SCOPED_ATOMIC(Store, a, v, mo);
553 }
554 
555 #if __TSAN_HAS_INT128
556 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_store(volatile a128 * a,a128 v,morder mo)557 void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
558   SCOPED_ATOMIC(Store, a, v, mo);
559 }
560 #endif
561 
562 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_exchange(volatile a8 * a,a8 v,morder mo)563 a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
564   SCOPED_ATOMIC(Exchange, a, v, mo);
565 }
566 
567 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_exchange(volatile a16 * a,a16 v,morder mo)568 a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
569   SCOPED_ATOMIC(Exchange, a, v, mo);
570 }
571 
572 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_exchange(volatile a32 * a,a32 v,morder mo)573 a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
574   SCOPED_ATOMIC(Exchange, a, v, mo);
575 }
576 
577 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_exchange(volatile a64 * a,a64 v,morder mo)578 a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
579   SCOPED_ATOMIC(Exchange, a, v, mo);
580 }
581 
582 #if __TSAN_HAS_INT128
583 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_exchange(volatile a128 * a,a128 v,morder mo)584 a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
585   SCOPED_ATOMIC(Exchange, a, v, mo);
586 }
587 #endif
588 
589 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_fetch_add(volatile a8 * a,a8 v,morder mo)590 a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
591   SCOPED_ATOMIC(FetchAdd, a, v, mo);
592 }
593 
594 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_fetch_add(volatile a16 * a,a16 v,morder mo)595 a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
596   SCOPED_ATOMIC(FetchAdd, a, v, mo);
597 }
598 
599 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_fetch_add(volatile a32 * a,a32 v,morder mo)600 a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
601   SCOPED_ATOMIC(FetchAdd, a, v, mo);
602 }
603 
604 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_fetch_add(volatile a64 * a,a64 v,morder mo)605 a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
606   SCOPED_ATOMIC(FetchAdd, a, v, mo);
607 }
608 
609 #if __TSAN_HAS_INT128
610 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_fetch_add(volatile a128 * a,a128 v,morder mo)611 a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
612   SCOPED_ATOMIC(FetchAdd, a, v, mo);
613 }
614 #endif
615 
616 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_fetch_sub(volatile a8 * a,a8 v,morder mo)617 a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
618   SCOPED_ATOMIC(FetchSub, a, v, mo);
619 }
620 
621 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_fetch_sub(volatile a16 * a,a16 v,morder mo)622 a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
623   SCOPED_ATOMIC(FetchSub, a, v, mo);
624 }
625 
626 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_fetch_sub(volatile a32 * a,a32 v,morder mo)627 a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
628   SCOPED_ATOMIC(FetchSub, a, v, mo);
629 }
630 
631 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_fetch_sub(volatile a64 * a,a64 v,morder mo)632 a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
633   SCOPED_ATOMIC(FetchSub, a, v, mo);
634 }
635 
636 #if __TSAN_HAS_INT128
637 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_fetch_sub(volatile a128 * a,a128 v,morder mo)638 a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
639   SCOPED_ATOMIC(FetchSub, a, v, mo);
640 }
641 #endif
642 
643 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_fetch_and(volatile a8 * a,a8 v,morder mo)644 a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
645   SCOPED_ATOMIC(FetchAnd, a, v, mo);
646 }
647 
648 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_fetch_and(volatile a16 * a,a16 v,morder mo)649 a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
650   SCOPED_ATOMIC(FetchAnd, a, v, mo);
651 }
652 
653 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_fetch_and(volatile a32 * a,a32 v,morder mo)654 a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
655   SCOPED_ATOMIC(FetchAnd, a, v, mo);
656 }
657 
658 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_fetch_and(volatile a64 * a,a64 v,morder mo)659 a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
660   SCOPED_ATOMIC(FetchAnd, a, v, mo);
661 }
662 
663 #if __TSAN_HAS_INT128
664 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_fetch_and(volatile a128 * a,a128 v,morder mo)665 a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
666   SCOPED_ATOMIC(FetchAnd, a, v, mo);
667 }
668 #endif
669 
670 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_fetch_or(volatile a8 * a,a8 v,morder mo)671 a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
672   SCOPED_ATOMIC(FetchOr, a, v, mo);
673 }
674 
675 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_fetch_or(volatile a16 * a,a16 v,morder mo)676 a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
677   SCOPED_ATOMIC(FetchOr, a, v, mo);
678 }
679 
680 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_fetch_or(volatile a32 * a,a32 v,morder mo)681 a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
682   SCOPED_ATOMIC(FetchOr, a, v, mo);
683 }
684 
685 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_fetch_or(volatile a64 * a,a64 v,morder mo)686 a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
687   SCOPED_ATOMIC(FetchOr, a, v, mo);
688 }
689 
690 #if __TSAN_HAS_INT128
691 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_fetch_or(volatile a128 * a,a128 v,morder mo)692 a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
693   SCOPED_ATOMIC(FetchOr, a, v, mo);
694 }
695 #endif
696 
697 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_fetch_xor(volatile a8 * a,a8 v,morder mo)698 a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
699   SCOPED_ATOMIC(FetchXor, a, v, mo);
700 }
701 
702 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_fetch_xor(volatile a16 * a,a16 v,morder mo)703 a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
704   SCOPED_ATOMIC(FetchXor, a, v, mo);
705 }
706 
707 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_fetch_xor(volatile a32 * a,a32 v,morder mo)708 a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
709   SCOPED_ATOMIC(FetchXor, a, v, mo);
710 }
711 
712 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_fetch_xor(volatile a64 * a,a64 v,morder mo)713 a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
714   SCOPED_ATOMIC(FetchXor, a, v, mo);
715 }
716 
717 #if __TSAN_HAS_INT128
718 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_fetch_xor(volatile a128 * a,a128 v,morder mo)719 a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
720   SCOPED_ATOMIC(FetchXor, a, v, mo);
721 }
722 #endif
723 
724 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_fetch_nand(volatile a8 * a,a8 v,morder mo)725 a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
726   SCOPED_ATOMIC(FetchNand, a, v, mo);
727 }
728 
729 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_fetch_nand(volatile a16 * a,a16 v,morder mo)730 a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
731   SCOPED_ATOMIC(FetchNand, a, v, mo);
732 }
733 
734 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_fetch_nand(volatile a32 * a,a32 v,morder mo)735 a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
736   SCOPED_ATOMIC(FetchNand, a, v, mo);
737 }
738 
739 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_fetch_nand(volatile a64 * a,a64 v,morder mo)740 a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
741   SCOPED_ATOMIC(FetchNand, a, v, mo);
742 }
743 
744 #if __TSAN_HAS_INT128
745 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_fetch_nand(volatile a128 * a,a128 v,morder mo)746 a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
747   SCOPED_ATOMIC(FetchNand, a, v, mo);
748 }
749 #endif
750 
751 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_compare_exchange_strong(volatile a8 * a,a8 * c,a8 v,morder mo,morder fmo)752 int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
753     morder mo, morder fmo) {
754   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
755 }
756 
757 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_compare_exchange_strong(volatile a16 * a,a16 * c,a16 v,morder mo,morder fmo)758 int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
759     morder mo, morder fmo) {
760   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
761 }
762 
763 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_compare_exchange_strong(volatile a32 * a,a32 * c,a32 v,morder mo,morder fmo)764 int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
765     morder mo, morder fmo) {
766   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
767 }
768 
769 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_compare_exchange_strong(volatile a64 * a,a64 * c,a64 v,morder mo,morder fmo)770 int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
771     morder mo, morder fmo) {
772   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
773 }
774 
775 #if __TSAN_HAS_INT128
776 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_compare_exchange_strong(volatile a128 * a,a128 * c,a128 v,morder mo,morder fmo)777 int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
778     morder mo, morder fmo) {
779   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
780 }
781 #endif
782 
783 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_compare_exchange_weak(volatile a8 * a,a8 * c,a8 v,morder mo,morder fmo)784 int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
785     morder mo, morder fmo) {
786   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
787 }
788 
789 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_compare_exchange_weak(volatile a16 * a,a16 * c,a16 v,morder mo,morder fmo)790 int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
791     morder mo, morder fmo) {
792   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
793 }
794 
795 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_compare_exchange_weak(volatile a32 * a,a32 * c,a32 v,morder mo,morder fmo)796 int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
797     morder mo, morder fmo) {
798   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
799 }
800 
801 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_compare_exchange_weak(volatile a64 * a,a64 * c,a64 v,morder mo,morder fmo)802 int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
803     morder mo, morder fmo) {
804   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
805 }
806 
807 #if __TSAN_HAS_INT128
808 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_compare_exchange_weak(volatile a128 * a,a128 * c,a128 v,morder mo,morder fmo)809 int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
810     morder mo, morder fmo) {
811   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
812 }
813 #endif
814 
815 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic8_compare_exchange_val(volatile a8 * a,a8 c,a8 v,morder mo,morder fmo)816 a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
817     morder mo, morder fmo) {
818   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
819 }
820 
821 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic16_compare_exchange_val(volatile a16 * a,a16 c,a16 v,morder mo,morder fmo)822 a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
823     morder mo, morder fmo) {
824   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
825 }
826 
827 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic32_compare_exchange_val(volatile a32 * a,a32 c,a32 v,morder mo,morder fmo)828 a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
829     morder mo, morder fmo) {
830   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
831 }
832 
833 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic64_compare_exchange_val(volatile a64 * a,a64 c,a64 v,morder mo,morder fmo)834 a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
835     morder mo, morder fmo) {
836   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
837 }
838 
839 #if __TSAN_HAS_INT128
840 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic128_compare_exchange_val(volatile a128 * a,a128 c,a128 v,morder mo,morder fmo)841 a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
842     morder mo, morder fmo) {
843   SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
844 }
845 #endif
846 
847 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic_thread_fence(morder mo)848 void __tsan_atomic_thread_fence(morder mo) {
849   char* a = 0;
850   SCOPED_ATOMIC(Fence, mo);
851 }
852 
853 SANITIZER_INTERFACE_ATTRIBUTE
__tsan_atomic_signal_fence(morder mo)854 void __tsan_atomic_signal_fence(morder mo) {
855 }
856 }  // extern "C"
857