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