Home | History | Annotate | Download | only in rtl_tests
      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;
     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 
     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     delete k;
     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 
     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 
     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 *k[3];
     61   k[0] = new thread_key(key, &mtx, 42, &cnt);
     62   k[1] = new thread_key(key, &mtx, 43, &cnt);
     63   k[2] = new thread_key(key, &mtx, 44, &cnt);
     64   EXPECT_EQ(pthread_create(&th[0], 0, dtors_thread, k[0]), 0);
     65   EXPECT_EQ(pthread_create(&th[1], 0, dtors_thread, k[1]), 0);
     66   EXPECT_EQ(pthread_join(th[0], 0), 0);
     67   EXPECT_EQ(pthread_create(&th[2], 0, dtors_thread, k[2]), 0);
     68   EXPECT_EQ(pthread_join(th[1], 0), 0);
     69   EXPECT_EQ(pthread_join(th[2], 0), 0);
     70   EXPECT_EQ(pthread_key_delete(key), 0);
     71   EXPECT_EQ(6, cnt);
     72 }
     73 
     74 static __thread int local_var;
     75 
     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 
     91 TEST(Posix, ThreadLocalAccesses) {
     92   local_thread((void*)2);
     93 }
     94 
     95 struct CondContext {
     96   pthread_mutex_t m;
     97   pthread_cond_t c;
     98   int data;
     99 };
    100 
    101 static void *cond_thread(void *p) {
    102   CondContext &ctx = *static_cast<CondContext*>(p);
    103 
    104   EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
    105   EXPECT_EQ(ctx.data, 0);
    106   ctx.data = 1;
    107   EXPECT_EQ(pthread_cond_signal(&ctx.c), 0);
    108   EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
    109 
    110   EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
    111   while (ctx.data != 2)
    112     EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
    113   EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
    114 
    115   EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
    116   ctx.data = 3;
    117   EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);
    118   EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
    119 
    120   return 0;
    121 }
    122 
    123 TEST(Posix, CondBasic) {
    124   CondContext ctx;
    125   EXPECT_EQ(pthread_mutex_init(&ctx.m, 0), 0);
    126   EXPECT_EQ(pthread_cond_init(&ctx.c, 0), 0);
    127   ctx.data = 0;
    128   pthread_t th;
    129   EXPECT_EQ(pthread_create(&th, 0, cond_thread, &ctx), 0);
    130 
    131   EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
    132   while (ctx.data != 1)
    133     EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
    134   ctx.data = 2;
    135   EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
    136   EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0);
    137 
    138   EXPECT_EQ(pthread_mutex_lock(&ctx.m), 0);
    139   while (ctx.data != 3)
    140     EXPECT_EQ(pthread_cond_wait(&ctx.c, &ctx.m), 0);
    141   EXPECT_EQ(pthread_mutex_unlock(&ctx.m), 0);
    142 
    143   EXPECT_EQ(pthread_join(th, 0), 0);
    144   EXPECT_EQ(pthread_cond_destroy(&ctx.c), 0);
    145   EXPECT_EQ(pthread_mutex_destroy(&ctx.m), 0);
    146 }
    147