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