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