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