15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===-- tsan_posix.cc -----------------------------------------------------===//
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// License. See LICENSE.TXT for details.
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===//
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This file is a part of ThreadSanitizer (TSan), a race detector.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//===----------------------------------------------------------------------===//
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tsan_interface.h"
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tsan_test_util.h"
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "gtest/gtest.h"
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <pthread.h>
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct thread_key {
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  pthread_key_t key;
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  pthread_mutex_t *mtx;
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  int val;
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  int *cnt;
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  thread_key(pthread_key_t key, pthread_mutex_t *mtx, int val, int *cnt)
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : key(key)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , mtx(mtx)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , val(val)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , cnt(cnt) {
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void thread_secific_dtor(void *v) {
32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  thread_key *k = (thread_key *)v;
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  EXPECT_EQ(pthread_mutex_lock(k->mtx), 0);
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  (*k->cnt)++;
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  __tsan_write4(&k->cnt);
36e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)  EXPECT_EQ(pthread_mutex_unlock(k->mtx), 0);
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (k->val == 42) {
3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    delete k;
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  } else if (k->val == 43 || k->val == 44) {
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    k->val--;
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    EXPECT_EQ(pthread_setspecific(k->key, k), 0);
4206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)  } else {
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ASSERT_TRUE(false);
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  }
453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static void *dtors_thread(void *p) {
481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  thread_key *k = (thread_key *)p;
49d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)  EXPECT_EQ(pthread_setspecific(k->key, k), 0);
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  return 0;
51d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
52d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)TEST(Posix, ThreadSpecificDtors) {
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  int cnt = 0;
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  pthread_key_t key;
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0);
57a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)  pthread_mutex_t mtx;
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_mutex_init(&mtx, 0), 0);
5919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)  pthread_t th[3];
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  thread_key *k[3];
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  k[0] = new thread_key(key, &mtx, 42, &cnt);
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  k[1] = new thread_key(key, &mtx, 43, &cnt);
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  k[2] = new thread_key(key, &mtx, 44, &cnt);
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, k[0]), 0);
6553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, k[1]), 0);
6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_join(th[0], 0), 0);
6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)  EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, k[2]), 0);
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_join(th[1], 0), 0);
6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_join(th[2], 0), 0);
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(pthread_key_delete(key), 0);
7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  EXPECT_EQ(6, cnt);
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
7353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static __thread int local_var;
7553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static void *local_thread(void *p) {
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  __tsan_write1(&local_var);
78aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch  __tsan_write1(&p);
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)  if (p == 0)
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return 0;
815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)  const int kThreads = 4;
82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)  pthread_t th[kThreads];
8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  for (int i = 0; i < kThreads; i++)
8407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    EXPECT_EQ(pthread_create(&th[i], 0, local_thread,
8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)              (void*)((long)p - 1)), 0);  // NOLINT
8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  for (int i = 0; i < kThreads; i++)
87a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    EXPECT_EQ(pthread_join(th[i], 0), 0);
8851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)  return 0;
8951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
90a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)TEST(Posix, ThreadLocalAccesses) {
921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  local_thread((void*)2);
93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
951e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)struct CondContext {
961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  pthread_mutex_t m;
971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  pthread_cond_t c;
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)  int data;
991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)};
10007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
101bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)static void *cond_thread(void *p) {
102a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)  CondContext &ctx = *static_cast<CondContext*>(p);
103f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)  EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
105a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)  EXPECT_EQ(ctx.data, 0);
106a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)  ctx.data = 1;
10751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)  EXPECT_EQ(pthread_cond_signal(&ctx.c), 0);
1081e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
1091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
1101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
1111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  while (ctx.data != 2)
1121e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
1131e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)  EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
1141e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
115f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
116f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  ctx.data = 3;
117f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);
118a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch  EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
119f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
120f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  return 0;
121f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
122f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
123f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(Posix, CondBasic) {
124f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  CondContext ctx;
125f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_init(&ctx.m, 0), 0);
126f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_cond_init(&ctx.c, 0), 0);
127f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  ctx.data = 0;
128f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  pthread_t th;
129f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_create(&th, 0, cond_thread, &ctx), 0);
130f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
131f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
132f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  while (ctx.data != 1)
133f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
134f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  ctx.data = 2;
135f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
136f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);
137f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
138f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
139f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  while (ctx.data != 3)
140f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
141f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
142f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
143f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_join(th, 0), 0);
144f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_cond_destroy(&ctx.c), 0);
145f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu  EXPECT_EQ(pthread_mutex_destroy(&ctx.m), 0);
146f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
147f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu