From 5b2e4e3c66b9ea1a8604d3899aba68a52b2e1f72 Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 15 Nov 2016 21:00:55 +0000 Subject: [PATCH] [tsan] Call pthread interceptors directly in TSan RTL unit tests On Darwin, we're running the TSan unit tests without interceptors. To make sure TSan observes all the pthread events (thread creating, thread join, condvar signal, etc.) in tsan_posix.cc, we should call the pthread interceptors directly, as we already do in tsan_test_util_posix.cc. This fixes some flaky failures on Darwin bots. Differential Revision: https://reviews.llvm.org/D26639 llvm-svn: 287026 --- compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc | 69 +++++++++---------- compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h | 77 ++++++++++++++++++++++ .../lib/tsan/tests/rtl/tsan_test_util_posix.cc | 47 +------------ 3 files changed, 114 insertions(+), 79 deletions(-) create mode 100644 compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h diff --git a/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc b/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc index e1a61b5..9c0e013 100644 --- a/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc +++ b/compiler-rt/lib/tsan/tests/rtl/tsan_posix.cc @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "tsan_interface.h" +#include "tsan_posix_util.h" #include "tsan_test_util.h" #include "gtest/gtest.h" #include @@ -30,10 +31,10 @@ struct thread_key { static void thread_secific_dtor(void *v) { thread_key *k = (thread_key *)v; - EXPECT_EQ(pthread_mutex_lock(k->mtx), 0); + EXPECT_EQ(__interceptor_pthread_mutex_lock(k->mtx), 0); (*k->cnt)++; __tsan_write4(&k->cnt); - EXPECT_EQ(pthread_mutex_unlock(k->mtx), 0); + EXPECT_EQ(__interceptor_pthread_mutex_unlock(k->mtx), 0); if (k->val == 42) { // Okay. } else if (k->val == 43 || k->val == 44) { @@ -55,22 +56,22 @@ TEST(Posix, ThreadSpecificDtors) { pthread_key_t key; EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0); pthread_mutex_t mtx; - EXPECT_EQ(pthread_mutex_init(&mtx, 0), 0); + EXPECT_EQ(__interceptor_pthread_mutex_init(&mtx, 0), 0); pthread_t th[3]; thread_key k1 = thread_key(key, &mtx, 42, &cnt); thread_key k2 = thread_key(key, &mtx, 43, &cnt); thread_key k3 = thread_key(key, &mtx, 44, &cnt); - EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, &k1), 0); - EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, &k2), 0); - EXPECT_EQ(pthread_join(th[0], 0), 0); - EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, &k3), 0); - EXPECT_EQ(pthread_join(th[1], 0), 0); - EXPECT_EQ(pthread_join(th[2], 0), 0); + EXPECT_EQ(__interceptor_pthread_create(&th[0], 0, dtors_thread, &k1), 0); + EXPECT_EQ(__interceptor_pthread_create(&th[1], 0, dtors_thread, &k2), 0); + EXPECT_EQ(__interceptor_pthread_join(th[0], 0), 0); + EXPECT_EQ(__interceptor_pthread_create(&th[2], 0, dtors_thread, &k3), 0); + EXPECT_EQ(__interceptor_pthread_join(th[1], 0), 0); + EXPECT_EQ(__interceptor_pthread_join(th[2], 0), 0); EXPECT_EQ(pthread_key_delete(key), 0); EXPECT_EQ(6, cnt); } -#ifndef __aarch64__ +#if !defined(__aarch64__) && !defined(__APPLE__) static __thread int local_var; static void *local_thread(void *p) { @@ -81,10 +82,10 @@ static void *local_thread(void *p) { const int kThreads = 4; pthread_t th[kThreads]; for (int i = 0; i < kThreads; i++) - EXPECT_EQ(pthread_create(&th[i], 0, local_thread, + EXPECT_EQ(__interceptor_pthread_create(&th[i], 0, local_thread, (void*)((long)p - 1)), 0); // NOLINT for (int i = 0; i < kThreads; i++) - EXPECT_EQ(pthread_join(th[i], 0), 0); + EXPECT_EQ(__interceptor_pthread_join(th[i], 0), 0); return 0; } #endif @@ -92,7 +93,9 @@ static void *local_thread(void *p) { TEST(Posix, ThreadLocalAccesses) { // The test is failing with high thread count for aarch64. // FIXME: track down the issue and re-enable the test. -#ifndef __aarch64__ +// On Darwin, we're running unit tests without interceptors and __thread is +// using malloc and free, which causes false data race reports. +#if !defined(__aarch64__) && !defined(__APPLE__) local_thread((void*)2); #endif } @@ -106,46 +109,46 @@ struct CondContext { static void *cond_thread(void *p) { CondContext &ctx = *static_cast(p); - EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); EXPECT_EQ(ctx.data, 0); ctx.data = 1; - EXPECT_EQ(pthread_cond_signal(&ctx.c), 0); - EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_cond_signal(&ctx.c), 0); + EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); while (ctx.data != 2) - EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0); - EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); ctx.data = 3; EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); - EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); return 0; } TEST(Posix, CondBasic) { CondContext ctx; - EXPECT_EQ(pthread_mutex_init(&ctx.m, 0), 0); - EXPECT_EQ(pthread_cond_init(&ctx.c, 0), 0); + EXPECT_EQ(__interceptor_pthread_mutex_init(&ctx.m, 0), 0); + EXPECT_EQ(__interceptor_pthread_cond_init(&ctx.c, 0), 0); ctx.data = 0; pthread_t th; - EXPECT_EQ(pthread_create(&th, 0, cond_thread, &ctx), 0); + EXPECT_EQ(__interceptor_pthread_create(&th, 0, cond_thread, &ctx), 0); - EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); while (ctx.data != 1) - EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); ctx.data = 2; - EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); - EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); while (ctx.data != 3) - EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0); - EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - EXPECT_EQ(pthread_join(th, 0), 0); - EXPECT_EQ(pthread_cond_destroy(&ctx.c), 0); - EXPECT_EQ(pthread_mutex_destroy(&ctx.m), 0); + EXPECT_EQ(__interceptor_pthread_join(th, 0), 0); + EXPECT_EQ(__interceptor_pthread_cond_destroy(&ctx.c), 0); + EXPECT_EQ(__interceptor_pthread_mutex_destroy(&ctx.m), 0); } diff --git a/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h b/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h new file mode 100644 index 0000000..340693e --- /dev/null +++ b/compiler-rt/lib/tsan/tests/rtl/tsan_posix_util.h @@ -0,0 +1,77 @@ +//===-- tsan_posix_util.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Test POSIX utils. +//===----------------------------------------------------------------------===// +#ifndef TSAN_POSIX_UTIL_H +#define TSAN_POSIX_UTIL_H + +#include + +#ifdef __APPLE__ +#define __interceptor_memcpy wrap_memcpy +#define __interceptor_memset wrap_memset +#define __interceptor_pthread_create wrap_pthread_create +#define __interceptor_pthread_join wrap_pthread_join +#define __interceptor_pthread_detach wrap_pthread_detach +#define __interceptor_pthread_mutex_init wrap_pthread_mutex_init +#define __interceptor_pthread_mutex_lock wrap_pthread_mutex_lock +#define __interceptor_pthread_mutex_unlock wrap_pthread_mutex_unlock +#define __interceptor_pthread_mutex_destroy wrap_pthread_mutex_destroy +#define __interceptor_pthread_mutex_trylock wrap_pthread_mutex_trylock +#define __interceptor_pthread_rwlock_init wrap_pthread_rwlock_init +#define __interceptor_pthread_rwlock_destroy wrap_pthread_rwlock_destroy +#define __interceptor_pthread_rwlock_trywrlock wrap_pthread_rwlock_trywrlock +#define __interceptor_pthread_rwlock_wrlock wrap_pthread_rwlock_wrlock +#define __interceptor_pthread_rwlock_unlock wrap_pthread_rwlock_unlock +#define __interceptor_pthread_rwlock_rdlock wrap_pthread_rwlock_rdlock +#define __interceptor_pthread_rwlock_tryrdlock wrap_pthread_rwlock_tryrdlock +#define __interceptor_pthread_cond_init wrap_pthread_cond_init +#define __interceptor_pthread_cond_signal wrap_pthread_cond_signal +#define __interceptor_pthread_cond_broadcast wrap_pthread_cond_broadcast +#define __interceptor_pthread_cond_wait wrap_pthread_cond_wait +#define __interceptor_pthread_cond_destroy wrap_pthread_cond_destroy +#endif + +extern "C" void *__interceptor_memcpy(void *, const void *, uptr); +extern "C" void *__interceptor_memset(void *, int, uptr); +extern "C" int __interceptor_pthread_create(pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); +extern "C" int __interceptor_pthread_join(pthread_t thread, void **value_ptr); +extern "C" int __interceptor_pthread_detach(pthread_t thread); + +extern "C" int __interceptor_pthread_mutex_init( + pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +extern "C" int __interceptor_pthread_mutex_lock(pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_mutex_unlock(pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_mutex_destroy(pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_mutex_trylock(pthread_mutex_t *mutex); + +extern "C" int __interceptor_pthread_rwlock_init( + pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); +extern "C" int __interceptor_pthread_rwlock_destroy(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_unlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); +extern "C" int __interceptor_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); + +extern "C" int __interceptor_pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr); +extern "C" int __interceptor_pthread_cond_signal(pthread_cond_t *cond); +extern "C" int __interceptor_pthread_cond_broadcast(pthread_cond_t *cond); +extern "C" int __interceptor_pthread_cond_wait(pthread_cond_t *cond, + pthread_mutex_t *mutex); +extern "C" int __interceptor_pthread_cond_destroy(pthread_cond_t *cond); + +#endif // #ifndef TSAN_POSIX_UTIL_H diff --git a/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc b/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc index c8be088..01e3f7c 100644 --- a/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc +++ b/compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cc @@ -14,6 +14,7 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "tsan_interface.h" +#include "tsan_posix_util.h" #include "tsan_test_util.h" #include "tsan_report.h" @@ -33,52 +34,6 @@ static __thread bool expect_report; static __thread bool expect_report_reported; static __thread ReportType expect_report_type; -#ifdef __APPLE__ -#define __interceptor_memcpy wrap_memcpy -#define __interceptor_memset wrap_memset -#define __interceptor_pthread_create wrap_pthread_create -#define __interceptor_pthread_join wrap_pthread_join -#define __interceptor_pthread_detach wrap_pthread_detach -#define __interceptor_pthread_mutex_init wrap_pthread_mutex_init -#define __interceptor_pthread_mutex_lock wrap_pthread_mutex_lock -#define __interceptor_pthread_mutex_unlock wrap_pthread_mutex_unlock -#define __interceptor_pthread_mutex_destroy wrap_pthread_mutex_destroy -#define __interceptor_pthread_mutex_trylock wrap_pthread_mutex_trylock -#define __interceptor_pthread_rwlock_init wrap_pthread_rwlock_init -#define __interceptor_pthread_rwlock_destroy wrap_pthread_rwlock_destroy -#define __interceptor_pthread_rwlock_trywrlock wrap_pthread_rwlock_trywrlock -#define __interceptor_pthread_rwlock_wrlock wrap_pthread_rwlock_wrlock -#define __interceptor_pthread_rwlock_unlock wrap_pthread_rwlock_unlock -#define __interceptor_pthread_rwlock_rdlock wrap_pthread_rwlock_rdlock -#define __interceptor_pthread_rwlock_tryrdlock wrap_pthread_rwlock_tryrdlock -#endif - -extern "C" void *__interceptor_memcpy(void *, const void *, uptr); -extern "C" void *__interceptor_memset(void *, int, uptr); -extern "C" int __interceptor_pthread_create(pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), - void *arg); -extern "C" int __interceptor_pthread_join(pthread_t thread, void **value_ptr); -extern "C" int __interceptor_pthread_detach(pthread_t thread); - -extern "C" int __interceptor_pthread_mutex_init( - pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); -extern "C" int __interceptor_pthread_mutex_lock(pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_mutex_unlock(pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_mutex_destroy(pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_mutex_trylock(pthread_mutex_t *mutex); - -extern "C" int __interceptor_pthread_rwlock_init( - pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); -extern "C" int __interceptor_pthread_rwlock_destroy(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_unlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); - - static void *BeforeInitThread(void *param) { (void)param; return 0; -- 2.7.4