1 //===-- tsan_posix.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 #include "tsan_interface.h" 14 #include "tsan_posix_util.h" 15 #include "tsan_test_util.h" 16 #include "gtest/gtest.h" 17 #include <pthread.h> 18 19 struct thread_key { 20 pthread_key_t key; 21 pthread_mutex_t *mtx; 22 int val; 23 int *cnt; 24 thread_key(pthread_key_t key, pthread_mutex_t *mtx, int val, int *cnt) 25 : key(key) 26 , mtx(mtx) 27 , val(val) 28 , cnt(cnt) { 29 } 30 }; 31 32 static void thread_secific_dtor(void *v) { 33 thread_key *k = (thread_key *)v; 34 EXPECT_EQ(__interceptor_pthread_mutex_lock(k->mtx), 0); 35 (*k->cnt)++; 36 __tsan_write4(&k->cnt); 37 EXPECT_EQ(__interceptor_pthread_mutex_unlock(k->mtx), 0); 38 if (k->val == 42) { 39 // Okay. 40 } else if (k->val == 43 || k->val == 44) { 41 k->val--; 42 EXPECT_EQ(pthread_setspecific(k->key, k), 0); 43 } else { 44 ASSERT_TRUE(false); 45 } 46 } 47 48 static void *dtors_thread(void *p) { 49 thread_key *k = (thread_key *)p; 50 EXPECT_EQ(pthread_setspecific(k->key, k), 0); 51 return 0; 52 } 53 54 TEST(Posix, ThreadSpecificDtors) { 55 int cnt = 0; 56 pthread_key_t key; 57 EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0); 58 pthread_mutex_t mtx; 59 EXPECT_EQ(__interceptor_pthread_mutex_init(&mtx, 0), 0); 60 pthread_t th[3]; 61 thread_key k1 = thread_key(key, &mtx, 42, &cnt); 62 thread_key k2 = thread_key(key, &mtx, 43, &cnt); 63 thread_key k3 = thread_key(key, &mtx, 44, &cnt); 64 EXPECT_EQ(__interceptor_pthread_create(&th[0], 0, dtors_thread, &k1), 0); 65 EXPECT_EQ(__interceptor_pthread_create(&th[1], 0, dtors_thread, &k2), 0); 66 EXPECT_EQ(__interceptor_pthread_join(th[0], 0), 0); 67 EXPECT_EQ(__interceptor_pthread_create(&th[2], 0, dtors_thread, &k3), 0); 68 EXPECT_EQ(__interceptor_pthread_join(th[1], 0), 0); 69 EXPECT_EQ(__interceptor_pthread_join(th[2], 0), 0); 70 EXPECT_EQ(pthread_key_delete(key), 0); 71 EXPECT_EQ(6, cnt); 72 } 73 74 #if !defined(__aarch64__) && !defined(__APPLE__) 75 static __thread int local_var; 76 77 static void *local_thread(void *p) { 78 __tsan_write1(&local_var); 79 __tsan_write1(&p); 80 if (p == 0) 81 return 0; 82 const int kThreads = 4; 83 pthread_t th[kThreads]; 84 for (int i = 0; i < kThreads; i++) 85 EXPECT_EQ(__interceptor_pthread_create(&th[i], 0, local_thread, 86 (void*)((long)p - 1)), 0); // NOLINT 87 for (int i = 0; i < kThreads; i++) 88 EXPECT_EQ(__interceptor_pthread_join(th[i], 0), 0); 89 return 0; 90 } 91 #endif 92 93 TEST(Posix, ThreadLocalAccesses) { 94 // The test is failing with high thread count for aarch64. 95 // FIXME: track down the issue and re-enable the test. 96 // On Darwin, we're running unit tests without interceptors and __thread is 97 // using malloc and free, which causes false data race reports. On rare 98 // occasions on powerpc64le this test also fails. 99 #if !defined(__aarch64__) && !defined(__APPLE__) && !defined(powerpc64le) 100 local_thread((void*)2); 101 #endif 102 } 103 104 struct CondContext { 105 pthread_mutex_t m; 106 pthread_cond_t c; 107 int data; 108 }; 109 110 static void *cond_thread(void *p) { 111 CondContext &ctx = *static_cast<CondContext*>(p); 112 113 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); 114 EXPECT_EQ(ctx.data, 0); 115 ctx.data = 1; 116 EXPECT_EQ(__interceptor_pthread_cond_signal(&ctx.c), 0); 117 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); 118 119 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); 120 while (ctx.data != 2) 121 EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); 122 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); 123 124 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); 125 ctx.data = 3; 126 EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); 127 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); 128 129 return 0; 130 } 131 132 TEST(Posix, CondBasic) { 133 CondContext ctx; 134 EXPECT_EQ(__interceptor_pthread_mutex_init(&ctx.m, 0), 0); 135 EXPECT_EQ(__interceptor_pthread_cond_init(&ctx.c, 0), 0); 136 ctx.data = 0; 137 pthread_t th; 138 EXPECT_EQ(__interceptor_pthread_create(&th, 0, cond_thread, &ctx), 0); 139 140 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); 141 while (ctx.data != 1) 142 EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); 143 ctx.data = 2; 144 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); 145 EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); 146 147 EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); 148 while (ctx.data != 3) 149 EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); 150 EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); 151 152 EXPECT_EQ(__interceptor_pthread_join(th, 0), 0); 153 EXPECT_EQ(__interceptor_pthread_cond_destroy(&ctx.c), 0); 154 EXPECT_EQ(__interceptor_pthread_mutex_destroy(&ctx.m), 0); 155 } 156