Index: lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- lib/tsan/rtl/tsan_interceptors.cc +++ lib/tsan/rtl/tsan_interceptors.cc @@ -1101,49 +1101,47 @@ return REAL(pthread_cond_init)(cond, a); } +#define PTHREAD_COND_WAIT_BODY(call, c, m, t) \ + MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); \ + MutexUnlock(thr, pc, (uptr)m); \ + CondMutexUnlockCtx arg = {&si, thr, pc, m}; \ + int res = 0; \ + /* This ensures that we handle mutex lock even in case of pthread_cancel. */ \ + /* See test/tsan/cond_cancel.cc. */ \ + { \ + /* Enable signal delivery while the thread is blocked. */ \ + BlockingCall bc(thr); \ + res = call_pthread_cancel_with_cleanup( \ + call, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg); \ + } \ + if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m); \ + MutexLock(thr, pc, (uptr)m); \ + return res + INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) { void *cond = init_cond(c); SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m); - MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); - MutexUnlock(thr, pc, (uptr)m); - CondMutexUnlockCtx arg = {&si, thr, pc, m}; - int res = 0; - // This ensures that we handle mutex lock even in case of pthread_cancel. - // See test/tsan/cond_cancel.cc. - { - // Enable signal delivery while the thread is blocked. - BlockingCall bc(thr); - res = call_pthread_cancel_with_cleanup( - (int(*)(void *c, void *m, void *abstime))REAL(pthread_cond_wait), - cond, m, 0, (void(*)(void *arg))cond_mutex_unlock, &arg); - } - if (res == errno_EOWNERDEAD) - MutexRepair(thr, pc, (uptr)m); - MutexLock(thr, pc, (uptr)m); - return res; + PTHREAD_COND_WAIT_BODY( + (int (*)(void *c, void *m, void *abstime))REAL(pthread_cond_wait), cond, + m, 0); } INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) { void *cond = init_cond(c); SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime); - MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false); - MutexUnlock(thr, pc, (uptr)m); - CondMutexUnlockCtx arg = {&si, thr, pc, m}; - int res = 0; - // This ensures that we handle mutex lock even in case of pthread_cancel. - // See test/tsan/cond_cancel.cc. - { - BlockingCall bc(thr); - res = call_pthread_cancel_with_cleanup( - REAL(pthread_cond_timedwait), cond, m, abstime, - (void(*)(void *arg))cond_mutex_unlock, &arg); - } - if (res == errno_EOWNERDEAD) - MutexRepair(thr, pc, (uptr)m); - MutexLock(thr, pc, (uptr)m); - return res; + PTHREAD_COND_WAIT_BODY(REAL(pthread_cond_timedwait), cond, m, abstime); } +#if SANITIZER_MAC +INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m, + void *reltime) { + void *cond = init_cond(c); + SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime); + PTHREAD_COND_WAIT_BODY(REAL(pthread_cond_timedwait_relative_np), cond, m, + reltime); +} +#endif + INTERCEPTOR(int, pthread_cond_signal, void *c) { void *cond = init_cond(c); SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);