• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 struct thread_key {
19   pthread_key_t key;
20   pthread_mutex_t *mtx;
21   int val;
22   int *cnt;
thread_keythread_key23   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 
thread_secific_dtor(void * v)31 static 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 
dtors_thread(void * p)47 static 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 
TEST(Posix,ThreadSpecificDtors)53 TEST(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__
74 static __thread int local_var;
75 
local_thread(void * p)76 static 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 
TEST(Posix,ThreadLocalAccesses)92 TEST(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 
100 struct CondContext {
101   pthread_mutex_t m;
102   pthread_cond_t c;
103   int data;
104 };
105 
cond_thread(void * p)106 static 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 
TEST(Posix,CondBasic)128 TEST(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