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