xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/tsan/tests/rtl/tsan_posix.cc (revision a7c257b03e4462df2b1020128fb82716512d7856)
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;
thread_keythread_key24   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 
thread_secific_dtor(void * v)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 
dtors_thread(void * p)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 
TEST(Posix,ThreadSpecificDtors)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 
local_thread(void * p)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 
TEST(Posix,ThreadLocalAccesses)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 
cond_thread(void * p)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 
TEST(Posix,CondBasic)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