1 //===-- tsan_interface_ann.cc ---------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
11 #include "sanitizer_common/sanitizer_libc.h"
12 #include "sanitizer_common/sanitizer_internal_defs.h"
13 #include "sanitizer_common/sanitizer_placement_new.h"
14 #include "sanitizer_common/sanitizer_stacktrace.h"
15 #include "tsan_interface_ann.h"
16 #include "tsan_mutex.h"
17 #include "tsan_report.h"
18 #include "tsan_rtl.h"
19 #include "tsan_mman.h"
20 #include "tsan_flags.h"
21 #include "tsan_platform.h"
22 #include "tsan_vector.h"
23 
24 #define CALLERPC ((uptr)__builtin_return_address(0))
25 
26 using namespace __tsan;  // NOLINT
27 
28 namespace __tsan {
29 
30 class ScopedAnnotation {
31  public:
ScopedAnnotation(ThreadState * thr,const char * aname,uptr pc)32   ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)
33       : thr_(thr) {
34     FuncEntry(thr_, pc);
35     DPrintf("#%d: annotation %s()\n", thr_->tid, aname);
36   }
37 
~ScopedAnnotation()38   ~ScopedAnnotation() {
39     FuncExit(thr_);
40     CheckNoLocks(thr_);
41   }
42  private:
43   ThreadState *const thr_;
44 };
45 
46 #define SCOPED_ANNOTATION_RET(typ, ret) \
47     if (!flags()->enable_annotations) \
48       return ret; \
49     ThreadState *thr = cur_thread(); \
50     const uptr caller_pc = (uptr)__builtin_return_address(0); \
51     StatInc(thr, StatAnnotation); \
52     StatInc(thr, Stat##typ); \
53     ScopedAnnotation sa(thr, __func__, caller_pc); \
54     const uptr pc = StackTrace::GetCurrentPc(); \
55     (void)pc; \
56 /**/
57 
58 #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
59 
60 static const int kMaxDescLen = 128;
61 
62 struct ExpectRace {
63   ExpectRace *next;
64   ExpectRace *prev;
65   atomic_uintptr_t hitcount;
66   atomic_uintptr_t addcount;
67   uptr addr;
68   uptr size;
69   char *file;
70   int line;
71   char desc[kMaxDescLen];
72 };
73 
74 struct DynamicAnnContext {
75   Mutex mtx;
76   ExpectRace expect;
77   ExpectRace benign;
78 
DynamicAnnContext__tsan::DynamicAnnContext79   DynamicAnnContext()
80     : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
81   }
82 };
83 
84 static DynamicAnnContext *dyn_ann_ctx;
85 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
86 
AddExpectRace(ExpectRace * list,char * f,int l,uptr addr,uptr size,char * desc)87 static void AddExpectRace(ExpectRace *list,
88     char *f, int l, uptr addr, uptr size, char *desc) {
89   ExpectRace *race = list->next;
90   for (; race != list; race = race->next) {
91     if (race->addr == addr && race->size == size) {
92       atomic_store_relaxed(&race->addcount,
93           atomic_load_relaxed(&race->addcount) + 1);
94       return;
95     }
96   }
97   race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
98   race->addr = addr;
99   race->size = size;
100   race->file = f;
101   race->line = l;
102   race->desc[0] = 0;
103   atomic_store_relaxed(&race->hitcount, 0);
104   atomic_store_relaxed(&race->addcount, 1);
105   if (desc) {
106     int i = 0;
107     for (; i < kMaxDescLen - 1 && desc[i]; i++)
108       race->desc[i] = desc[i];
109     race->desc[i] = 0;
110   }
111   race->prev = list;
112   race->next = list->next;
113   race->next->prev = race;
114   list->next = race;
115 }
116 
FindRace(ExpectRace * list,uptr addr,uptr size)117 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
118   for (ExpectRace *race = list->next; race != list; race = race->next) {
119     uptr maxbegin = max(race->addr, addr);
120     uptr minend = min(race->addr + race->size, addr + size);
121     if (maxbegin < minend)
122       return race;
123   }
124   return 0;
125 }
126 
CheckContains(ExpectRace * list,uptr addr,uptr size)127 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
128   ExpectRace *race = FindRace(list, addr, size);
129   if (race == 0)
130     return false;
131   DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
132       race->desc, race->addr, (int)race->size, race->file, race->line);
133   atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
134   return true;
135 }
136 
InitList(ExpectRace * list)137 static void InitList(ExpectRace *list) {
138   list->next = list;
139   list->prev = list;
140 }
141 
InitializeDynamicAnnotations()142 void InitializeDynamicAnnotations() {
143   dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
144   InitList(&dyn_ann_ctx->expect);
145   InitList(&dyn_ann_ctx->benign);
146 }
147 
IsExpectedReport(uptr addr,uptr size)148 bool IsExpectedReport(uptr addr, uptr size) {
149   ReadLock lock(&dyn_ann_ctx->mtx);
150   if (CheckContains(&dyn_ann_ctx->expect, addr, size))
151     return true;
152   if (CheckContains(&dyn_ann_ctx->benign, addr, size))
153     return true;
154   return false;
155 }
156 
CollectMatchedBenignRaces(Vector<ExpectRace> * matched,int * unique_count,int * hit_count,atomic_uintptr_t ExpectRace::* counter)157 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
158     int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) {
159   ExpectRace *list = &dyn_ann_ctx->benign;
160   for (ExpectRace *race = list->next; race != list; race = race->next) {
161     (*unique_count)++;
162     const uptr cnt = atomic_load_relaxed(&(race->*counter));
163     if (cnt == 0)
164       continue;
165     *hit_count += cnt;
166     uptr i = 0;
167     for (; i < matched->Size(); i++) {
168       ExpectRace *race0 = &(*matched)[i];
169       if (race->line == race0->line
170           && internal_strcmp(race->file, race0->file) == 0
171           && internal_strcmp(race->desc, race0->desc) == 0) {
172         atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed);
173         break;
174       }
175     }
176     if (i == matched->Size())
177       matched->PushBack(*race);
178   }
179 }
180 
PrintMatchedBenignRaces()181 void PrintMatchedBenignRaces() {
182   Lock lock(&dyn_ann_ctx->mtx);
183   int unique_count = 0;
184   int hit_count = 0;
185   int add_count = 0;
186   Vector<ExpectRace> hit_matched(MBlockScopedBuf);
187   CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
188       &ExpectRace::hitcount);
189   Vector<ExpectRace> add_matched(MBlockScopedBuf);
190   CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
191       &ExpectRace::addcount);
192   if (hit_matched.Size()) {
193     Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
194         hit_count, (int)internal_getpid());
195     for (uptr i = 0; i < hit_matched.Size(); i++) {
196       Printf("%d %s:%d %s\n",
197           atomic_load_relaxed(&hit_matched[i].hitcount),
198           hit_matched[i].file, hit_matched[i].line, hit_matched[i].desc);
199     }
200   }
201   if (hit_matched.Size()) {
202     Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
203            " (pid=%d):\n",
204         add_count, unique_count, (int)internal_getpid());
205     for (uptr i = 0; i < add_matched.Size(); i++) {
206       Printf("%d %s:%d %s\n",
207           atomic_load_relaxed(&add_matched[i].addcount),
208           add_matched[i].file, add_matched[i].line, add_matched[i].desc);
209     }
210   }
211 }
212 
ReportMissedExpectedRace(ExpectRace * race)213 static void ReportMissedExpectedRace(ExpectRace *race) {
214   Printf("==================\n");
215   Printf("WARNING: ThreadSanitizer: missed expected data race\n");
216   Printf("  %s addr=%zx %s:%d\n",
217       race->desc, race->addr, race->file, race->line);
218   Printf("==================\n");
219 }
220 }  // namespace __tsan
221 
222 using namespace __tsan;  // NOLINT
223 
224 extern "C" {
AnnotateHappensBefore(char * f,int l,uptr addr)225 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
226   SCOPED_ANNOTATION(AnnotateHappensBefore);
227   Release(thr, pc, addr);
228 }
229 
AnnotateHappensAfter(char * f,int l,uptr addr)230 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
231   SCOPED_ANNOTATION(AnnotateHappensAfter);
232   Acquire(thr, pc, addr);
233 }
234 
AnnotateCondVarSignal(char * f,int l,uptr cv)235 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
236   SCOPED_ANNOTATION(AnnotateCondVarSignal);
237 }
238 
AnnotateCondVarSignalAll(char * f,int l,uptr cv)239 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
240   SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
241 }
242 
AnnotateMutexIsNotPHB(char * f,int l,uptr mu)243 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
244   SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
245 }
246 
AnnotateCondVarWait(char * f,int l,uptr cv,uptr lock)247 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
248                                              uptr lock) {
249   SCOPED_ANNOTATION(AnnotateCondVarWait);
250 }
251 
AnnotateRWLockCreate(char * f,int l,uptr m)252 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
253   SCOPED_ANNOTATION(AnnotateRWLockCreate);
254   MutexCreate(thr, pc, m, MutexFlagWriteReentrant);
255 }
256 
AnnotateRWLockCreateStatic(char * f,int l,uptr m)257 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
258   SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
259   MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
260 }
261 
AnnotateRWLockDestroy(char * f,int l,uptr m)262 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
263   SCOPED_ANNOTATION(AnnotateRWLockDestroy);
264   MutexDestroy(thr, pc, m);
265 }
266 
AnnotateRWLockAcquired(char * f,int l,uptr m,uptr is_w)267 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
268                                                 uptr is_w) {
269   SCOPED_ANNOTATION(AnnotateRWLockAcquired);
270   if (is_w)
271     MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
272   else
273     MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
274 }
275 
AnnotateRWLockReleased(char * f,int l,uptr m,uptr is_w)276 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
277                                                 uptr is_w) {
278   SCOPED_ANNOTATION(AnnotateRWLockReleased);
279   if (is_w)
280     MutexUnlock(thr, pc, m);
281   else
282     MutexReadUnlock(thr, pc, m);
283 }
284 
AnnotateTraceMemory(char * f,int l,uptr mem)285 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
286   SCOPED_ANNOTATION(AnnotateTraceMemory);
287 }
288 
AnnotateFlushState(char * f,int l)289 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
290   SCOPED_ANNOTATION(AnnotateFlushState);
291 }
292 
AnnotateNewMemory(char * f,int l,uptr mem,uptr size)293 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
294                                            uptr size) {
295   SCOPED_ANNOTATION(AnnotateNewMemory);
296 }
297 
AnnotateNoOp(char * f,int l,uptr mem)298 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
299   SCOPED_ANNOTATION(AnnotateNoOp);
300 }
301 
AnnotateFlushExpectedRaces(char * f,int l)302 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
303   SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
304   Lock lock(&dyn_ann_ctx->mtx);
305   while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
306     ExpectRace *race = dyn_ann_ctx->expect.next;
307     if (atomic_load_relaxed(&race->hitcount) == 0) {
308       ctx->nmissed_expected++;
309       ReportMissedExpectedRace(race);
310     }
311     race->prev->next = race->next;
312     race->next->prev = race->prev;
313     internal_free(race);
314   }
315 }
316 
AnnotateEnableRaceDetection(char * f,int l,int enable)317 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
318     char *f, int l, int enable) {
319   SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
320   // FIXME: Reconsider this functionality later. It may be irrelevant.
321 }
322 
AnnotateMutexIsUsedAsCondVar(char * f,int l,uptr mu)323 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
324     char *f, int l, uptr mu) {
325   SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
326 }
327 
AnnotatePCQGet(char * f,int l,uptr pcq)328 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
329     char *f, int l, uptr pcq) {
330   SCOPED_ANNOTATION(AnnotatePCQGet);
331 }
332 
AnnotatePCQPut(char * f,int l,uptr pcq)333 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
334     char *f, int l, uptr pcq) {
335   SCOPED_ANNOTATION(AnnotatePCQPut);
336 }
337 
AnnotatePCQDestroy(char * f,int l,uptr pcq)338 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
339     char *f, int l, uptr pcq) {
340   SCOPED_ANNOTATION(AnnotatePCQDestroy);
341 }
342 
AnnotatePCQCreate(char * f,int l,uptr pcq)343 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
344     char *f, int l, uptr pcq) {
345   SCOPED_ANNOTATION(AnnotatePCQCreate);
346 }
347 
AnnotateExpectRace(char * f,int l,uptr mem,char * desc)348 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
349     char *f, int l, uptr mem, char *desc) {
350   SCOPED_ANNOTATION(AnnotateExpectRace);
351   Lock lock(&dyn_ann_ctx->mtx);
352   AddExpectRace(&dyn_ann_ctx->expect,
353                 f, l, mem, 1, desc);
354   DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
355 }
356 
BenignRaceImpl(char * f,int l,uptr mem,uptr size,char * desc)357 static void BenignRaceImpl(
358     char *f, int l, uptr mem, uptr size, char *desc) {
359   Lock lock(&dyn_ann_ctx->mtx);
360   AddExpectRace(&dyn_ann_ctx->benign,
361                 f, l, mem, size, desc);
362   DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
363 }
364 
365 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
AnnotateBenignRaceSized(char * f,int l,uptr mem,uptr size,char * desc)366 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
367     char *f, int l, uptr mem, uptr size, char *desc) {
368   SCOPED_ANNOTATION(AnnotateBenignRaceSized);
369   BenignRaceImpl(f, l, mem, size, desc);
370 }
371 
AnnotateBenignRace(char * f,int l,uptr mem,char * desc)372 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
373     char *f, int l, uptr mem, char *desc) {
374   SCOPED_ANNOTATION(AnnotateBenignRace);
375   BenignRaceImpl(f, l, mem, 1, desc);
376 }
377 
AnnotateIgnoreReadsBegin(char * f,int l)378 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
379   SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
380   ThreadIgnoreBegin(thr, pc);
381 }
382 
AnnotateIgnoreReadsEnd(char * f,int l)383 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
384   SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
385   ThreadIgnoreEnd(thr, pc);
386 }
387 
AnnotateIgnoreWritesBegin(char * f,int l)388 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
389   SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
390   ThreadIgnoreBegin(thr, pc);
391 }
392 
AnnotateIgnoreWritesEnd(char * f,int l)393 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
394   SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
395   ThreadIgnoreEnd(thr, pc);
396 }
397 
AnnotateIgnoreSyncBegin(char * f,int l)398 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
399   SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
400   ThreadIgnoreSyncBegin(thr, pc);
401 }
402 
AnnotateIgnoreSyncEnd(char * f,int l)403 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
404   SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
405   ThreadIgnoreSyncEnd(thr, pc);
406 }
407 
AnnotatePublishMemoryRange(char * f,int l,uptr addr,uptr size)408 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
409     char *f, int l, uptr addr, uptr size) {
410   SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
411 }
412 
AnnotateUnpublishMemoryRange(char * f,int l,uptr addr,uptr size)413 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
414     char *f, int l, uptr addr, uptr size) {
415   SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
416 }
417 
AnnotateThreadName(char * f,int l,char * name)418 void INTERFACE_ATTRIBUTE AnnotateThreadName(
419     char *f, int l, char *name) {
420   SCOPED_ANNOTATION(AnnotateThreadName);
421   ThreadSetName(thr, name);
422 }
423 
424 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
425 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
426 // atomic operations, which should be handled by ThreadSanitizer correctly.
WTFAnnotateHappensBefore(char * f,int l,uptr addr)427 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
428   SCOPED_ANNOTATION(AnnotateHappensBefore);
429 }
430 
WTFAnnotateHappensAfter(char * f,int l,uptr addr)431 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
432   SCOPED_ANNOTATION(AnnotateHappensAfter);
433 }
434 
WTFAnnotateBenignRaceSized(char * f,int l,uptr mem,uptr sz,char * desc)435 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
436     char *f, int l, uptr mem, uptr sz, char *desc) {
437   SCOPED_ANNOTATION(AnnotateBenignRaceSized);
438   BenignRaceImpl(f, l, mem, sz, desc);
439 }
440 
RunningOnValgrind()441 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
442   return flags()->running_on_valgrind;
443 }
444 
ValgrindSlowdown(void)445 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
446   return 10.0;
447 }
448 
ThreadSanitizerQuery(const char * query)449 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
450   if (internal_strcmp(query, "pure_happens_before") == 0)
451     return "1";
452   else
453     return "0";
454 }
455 
456 void INTERFACE_ATTRIBUTE
AnnotateMemoryIsInitialized(char * f,int l,uptr mem,uptr sz)457 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
458 void INTERFACE_ATTRIBUTE
AnnotateMemoryIsUninitialized(char * f,int l,uptr mem,uptr sz)459 AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}
460 
461 // Note: the parameter is called flagz, because flags is already taken
462 // by the global function that returns flags.
463 INTERFACE_ATTRIBUTE
__tsan_mutex_create(void * m,unsigned flagz)464 void __tsan_mutex_create(void *m, unsigned flagz) {
465   SCOPED_ANNOTATION(__tsan_mutex_create);
466   MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
467 }
468 
469 INTERFACE_ATTRIBUTE
__tsan_mutex_destroy(void * m,unsigned flagz)470 void __tsan_mutex_destroy(void *m, unsigned flagz) {
471   SCOPED_ANNOTATION(__tsan_mutex_destroy);
472   MutexDestroy(thr, pc, (uptr)m, flagz);
473 }
474 
475 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_lock(void * m,unsigned flagz)476 void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
477   SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
478   if (!(flagz & MutexFlagTryLock)) {
479     if (flagz & MutexFlagReadLock)
480       MutexPreReadLock(thr, pc, (uptr)m);
481     else
482       MutexPreLock(thr, pc, (uptr)m);
483   }
484   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
485   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
486 }
487 
488 INTERFACE_ATTRIBUTE
__tsan_mutex_post_lock(void * m,unsigned flagz,int rec)489 void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
490   SCOPED_ANNOTATION(__tsan_mutex_post_lock);
491   ThreadIgnoreSyncEnd(thr, pc);
492   ThreadIgnoreEnd(thr, pc);
493   if (!(flagz & MutexFlagTryLockFailed)) {
494     if (flagz & MutexFlagReadLock)
495       MutexPostReadLock(thr, pc, (uptr)m, flagz);
496     else
497       MutexPostLock(thr, pc, (uptr)m, flagz, rec);
498   }
499 }
500 
501 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_unlock(void * m,unsigned flagz)502 int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
503   SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
504   int ret = 0;
505   if (flagz & MutexFlagReadLock) {
506     CHECK(!(flagz & MutexFlagRecursiveUnlock));
507     MutexReadUnlock(thr, pc, (uptr)m);
508   } else {
509     ret = MutexUnlock(thr, pc, (uptr)m, flagz);
510   }
511   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
512   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
513   return ret;
514 }
515 
516 INTERFACE_ATTRIBUTE
__tsan_mutex_post_unlock(void * m,unsigned flagz)517 void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
518   SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
519   ThreadIgnoreSyncEnd(thr, pc);
520   ThreadIgnoreEnd(thr, pc);
521 }
522 
523 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_signal(void * addr,unsigned flagz)524 void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
525   SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
526   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
527   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
528 }
529 
530 INTERFACE_ATTRIBUTE
__tsan_mutex_post_signal(void * addr,unsigned flagz)531 void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
532   SCOPED_ANNOTATION(__tsan_mutex_post_signal);
533   ThreadIgnoreSyncEnd(thr, pc);
534   ThreadIgnoreEnd(thr, pc);
535 }
536 
537 INTERFACE_ATTRIBUTE
__tsan_mutex_pre_divert(void * addr,unsigned flagz)538 void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
539   SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
540   // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
541   ThreadIgnoreSyncEnd(thr, pc);
542   ThreadIgnoreEnd(thr, pc);
543 }
544 
545 INTERFACE_ATTRIBUTE
__tsan_mutex_post_divert(void * addr,unsigned flagz)546 void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
547   SCOPED_ANNOTATION(__tsan_mutex_post_divert);
548   ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
549   ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
550 }
551 }  // extern "C"
552