Home | History | Annotate | Line # | Download | only in rtl
      1 //===-- tsan_test_util_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 // Test utils, Linux, FreeBSD, NetBSD and Darwin implementation.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "sanitizer_common/sanitizer_atomic.h"
     16 #include "tsan_interface.h"
     17 #include "tsan_posix_util.h"
     18 #include "tsan_test_util.h"
     19 #include "tsan_report.h"
     20 
     21 #include "gtest/gtest.h"
     22 
     23 #include <assert.h>
     24 #include <pthread.h>
     25 #include <stdio.h>
     26 #include <stdint.h>
     27 #include <string.h>
     28 #include <unistd.h>
     29 #include <errno.h>
     30 
     31 using namespace __tsan;  // NOLINT
     32 
     33 static __thread bool expect_report;
     34 static __thread bool expect_report_reported;
     35 static __thread ReportType expect_report_type;
     36 
     37 static void *BeforeInitThread(void *param) {
     38   (void)param;
     39   return 0;
     40 }
     41 
     42 static void AtExit() {
     43 }
     44 
     45 void TestMutexBeforeInit() {
     46   // Mutexes must be usable before __tsan_init();
     47   pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
     48   __interceptor_pthread_mutex_lock(&mtx);
     49   __interceptor_pthread_mutex_unlock(&mtx);
     50   __interceptor_pthread_mutex_destroy(&mtx);
     51   pthread_t thr;
     52   __interceptor_pthread_create(&thr, 0, BeforeInitThread, 0);
     53   __interceptor_pthread_join(thr, 0);
     54   atexit(AtExit);
     55 }
     56 
     57 namespace __tsan {
     58 bool OnReport(const ReportDesc *rep, bool suppressed) {
     59   if (expect_report) {
     60     if (rep->typ != expect_report_type) {
     61       printf("Expected report of type %d, got type %d\n",
     62              (int)expect_report_type, (int)rep->typ);
     63       EXPECT_TRUE(false) << "Wrong report type";
     64       return false;
     65     }
     66   } else {
     67     EXPECT_TRUE(false) << "Unexpected report";
     68     return false;
     69   }
     70   expect_report_reported = true;
     71   return true;
     72 }
     73 }  // namespace __tsan
     74 
     75 static void* allocate_addr(int size, int offset_from_aligned = 0) {
     76   static uintptr_t foo;
     77   static atomic_uintptr_t uniq = {(uintptr_t)&foo};  // Some real address.
     78   const int kAlign = 16;
     79   CHECK(offset_from_aligned < kAlign);
     80   size = (size + 2 * kAlign) & ~(kAlign - 1);
     81   uintptr_t addr = atomic_fetch_add(&uniq, size, memory_order_relaxed);
     82   return (void*)(addr + offset_from_aligned);
     83 }
     84 
     85 MemLoc::MemLoc(int offset_from_aligned)
     86   : loc_(allocate_addr(16, offset_from_aligned)) {
     87 }
     88 
     89 MemLoc::~MemLoc() {
     90 }
     91 
     92 Mutex::Mutex(Type type)
     93   : alive_()
     94   , type_(type) {
     95 }
     96 
     97 Mutex::~Mutex() {
     98   CHECK(!alive_);
     99 }
    100 
    101 void Mutex::Init() {
    102   CHECK(!alive_);
    103   alive_ = true;
    104   if (type_ == Normal)
    105     CHECK_EQ(__interceptor_pthread_mutex_init((pthread_mutex_t*)mtx_, 0), 0);
    106 #ifndef __APPLE__
    107   else if (type_ == Spin)
    108     CHECK_EQ(pthread_spin_init((pthread_spinlock_t*)mtx_, 0), 0);
    109 #endif
    110   else if (type_ == RW)
    111     CHECK_EQ(__interceptor_pthread_rwlock_init((pthread_rwlock_t*)mtx_, 0), 0);
    112   else
    113     CHECK(0);
    114 }
    115 
    116 void Mutex::StaticInit() {
    117   CHECK(!alive_);
    118   CHECK(type_ == Normal);
    119   alive_ = true;
    120   pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER;
    121   memcpy(mtx_, &tmp, sizeof(tmp));
    122 }
    123 
    124 void Mutex::Destroy() {
    125   CHECK(alive_);
    126   alive_ = false;
    127   if (type_ == Normal)
    128     CHECK_EQ(__interceptor_pthread_mutex_destroy((pthread_mutex_t*)mtx_), 0);
    129 #ifndef __APPLE__
    130   else if (type_ == Spin)
    131     CHECK_EQ(pthread_spin_destroy((pthread_spinlock_t*)mtx_), 0);
    132 #endif
    133   else if (type_ == RW)
    134     CHECK_EQ(__interceptor_pthread_rwlock_destroy((pthread_rwlock_t*)mtx_), 0);
    135 }
    136 
    137 void Mutex::Lock() {
    138   CHECK(alive_);
    139   if (type_ == Normal)
    140     CHECK_EQ(__interceptor_pthread_mutex_lock((pthread_mutex_t*)mtx_), 0);
    141 #ifndef __APPLE__
    142   else if (type_ == Spin)
    143     CHECK_EQ(pthread_spin_lock((pthread_spinlock_t*)mtx_), 0);
    144 #endif
    145   else if (type_ == RW)
    146     CHECK_EQ(__interceptor_pthread_rwlock_wrlock((pthread_rwlock_t*)mtx_), 0);
    147 }
    148 
    149 bool Mutex::TryLock() {
    150   CHECK(alive_);
    151   if (type_ == Normal)
    152     return __interceptor_pthread_mutex_trylock((pthread_mutex_t*)mtx_) == 0;
    153 #ifndef __APPLE__
    154   else if (type_ == Spin)
    155     return pthread_spin_trylock((pthread_spinlock_t*)mtx_) == 0;
    156 #endif
    157   else if (type_ == RW)
    158     return __interceptor_pthread_rwlock_trywrlock((pthread_rwlock_t*)mtx_) == 0;
    159   return false;
    160 }
    161 
    162 void Mutex::Unlock() {
    163   CHECK(alive_);
    164   if (type_ == Normal)
    165     CHECK_EQ(__interceptor_pthread_mutex_unlock((pthread_mutex_t*)mtx_), 0);
    166 #ifndef __APPLE__
    167   else if (type_ == Spin)
    168     CHECK_EQ(pthread_spin_unlock((pthread_spinlock_t*)mtx_), 0);
    169 #endif
    170   else if (type_ == RW)
    171     CHECK_EQ(__interceptor_pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0);
    172 }
    173 
    174 void Mutex::ReadLock() {
    175   CHECK(alive_);
    176   CHECK(type_ == RW);
    177   CHECK_EQ(__interceptor_pthread_rwlock_rdlock((pthread_rwlock_t*)mtx_), 0);
    178 }
    179 
    180 bool Mutex::TryReadLock() {
    181   CHECK(alive_);
    182   CHECK(type_ == RW);
    183   return __interceptor_pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) ==  0;
    184 }
    185 
    186 void Mutex::ReadUnlock() {
    187   CHECK(alive_);
    188   CHECK(type_ == RW);
    189   CHECK_EQ(__interceptor_pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0);
    190 }
    191 
    192 struct Event {
    193   enum Type {
    194     SHUTDOWN,
    195     READ,
    196     WRITE,
    197     VPTR_UPDATE,
    198     CALL,
    199     RETURN,
    200     MUTEX_CREATE,
    201     MUTEX_DESTROY,
    202     MUTEX_LOCK,
    203     MUTEX_TRYLOCK,
    204     MUTEX_UNLOCK,
    205     MUTEX_READLOCK,
    206     MUTEX_TRYREADLOCK,
    207     MUTEX_READUNLOCK,
    208     MEMCPY,
    209     MEMSET
    210   };
    211   Type type;
    212   void *ptr;
    213   uptr arg;
    214   uptr arg2;
    215   bool res;
    216   bool expect_report;
    217   ReportType report_type;
    218 
    219   Event(Type type, const void *ptr = 0, uptr arg = 0, uptr arg2 = 0)
    220     : type(type)
    221     , ptr(const_cast<void*>(ptr))
    222     , arg(arg)
    223     , arg2(arg2)
    224     , res()
    225     , expect_report()
    226     , report_type() {
    227   }
    228 
    229   void ExpectReport(ReportType type) {
    230     expect_report = true;
    231     report_type = type;
    232   }
    233 };
    234 
    235 struct ScopedThread::Impl {
    236   pthread_t thread;
    237   bool main;
    238   bool detached;
    239   atomic_uintptr_t event;  // Event*
    240 
    241   static void *ScopedThreadCallback(void *arg);
    242   void send(Event *ev);
    243   void HandleEvent(Event *ev);
    244 };
    245 
    246 void ScopedThread::Impl::HandleEvent(Event *ev) {
    247   CHECK_EQ(expect_report, false);
    248   expect_report = ev->expect_report;
    249   expect_report_reported = false;
    250   expect_report_type = ev->report_type;
    251   switch (ev->type) {
    252   case Event::READ:
    253   case Event::WRITE: {
    254     void (*tsan_mop)(void *addr) = 0;
    255     if (ev->type == Event::READ) {
    256       switch (ev->arg /*size*/) {
    257         case 1: tsan_mop = __tsan_read1; break;
    258         case 2: tsan_mop = __tsan_read2; break;
    259         case 4: tsan_mop = __tsan_read4; break;
    260         case 8: tsan_mop = __tsan_read8; break;
    261         case 16: tsan_mop = __tsan_read16; break;
    262       }
    263     } else {
    264       switch (ev->arg /*size*/) {
    265         case 1: tsan_mop = __tsan_write1; break;
    266         case 2: tsan_mop = __tsan_write2; break;
    267         case 4: tsan_mop = __tsan_write4; break;
    268         case 8: tsan_mop = __tsan_write8; break;
    269         case 16: tsan_mop = __tsan_write16; break;
    270       }
    271     }
    272     CHECK_NE(tsan_mop, 0);
    273 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
    274     const int ErrCode = ESOCKTNOSUPPORT;
    275 #else
    276     const int ErrCode = ECHRNG;
    277 #endif
    278     errno = ErrCode;
    279     tsan_mop(ev->ptr);
    280     CHECK_EQ(ErrCode, errno);  // In no case must errno be changed.
    281     break;
    282   }
    283   case Event::VPTR_UPDATE:
    284     __tsan_vptr_update((void**)ev->ptr, (void*)ev->arg);
    285     break;
    286   case Event::CALL:
    287     __tsan_func_entry((void*)((uptr)ev->ptr));
    288     break;
    289   case Event::RETURN:
    290     __tsan_func_exit();
    291     break;
    292   case Event::MUTEX_CREATE:
    293     static_cast<Mutex*>(ev->ptr)->Init();
    294     break;
    295   case Event::MUTEX_DESTROY:
    296     static_cast<Mutex*>(ev->ptr)->Destroy();
    297     break;
    298   case Event::MUTEX_LOCK:
    299     static_cast<Mutex*>(ev->ptr)->Lock();
    300     break;
    301   case Event::MUTEX_TRYLOCK:
    302     ev->res = static_cast<Mutex*>(ev->ptr)->TryLock();
    303     break;
    304   case Event::MUTEX_UNLOCK:
    305     static_cast<Mutex*>(ev->ptr)->Unlock();
    306     break;
    307   case Event::MUTEX_READLOCK:
    308     static_cast<Mutex*>(ev->ptr)->ReadLock();
    309     break;
    310   case Event::MUTEX_TRYREADLOCK:
    311     ev->res = static_cast<Mutex*>(ev->ptr)->TryReadLock();
    312     break;
    313   case Event::MUTEX_READUNLOCK:
    314     static_cast<Mutex*>(ev->ptr)->ReadUnlock();
    315     break;
    316   case Event::MEMCPY:
    317     __interceptor_memcpy(ev->ptr, (void*)ev->arg, ev->arg2);
    318     break;
    319   case Event::MEMSET:
    320     __interceptor_memset(ev->ptr, ev->arg, ev->arg2);
    321     break;
    322   default: CHECK(0);
    323   }
    324   if (expect_report && !expect_report_reported) {
    325     printf("Missed expected report of type %d\n", (int)ev->report_type);
    326     EXPECT_TRUE(false) << "Missed expected race";
    327   }
    328   expect_report = false;
    329 }
    330 
    331 void *ScopedThread::Impl::ScopedThreadCallback(void *arg) {
    332   __tsan_func_entry(__builtin_return_address(0));
    333   Impl *impl = (Impl*)arg;
    334   for (;;) {
    335     Event* ev = (Event*)atomic_load(&impl->event, memory_order_acquire);
    336     if (ev == 0) {
    337       sched_yield();
    338       continue;
    339     }
    340     if (ev->type == Event::SHUTDOWN) {
    341       atomic_store(&impl->event, 0, memory_order_release);
    342       break;
    343     }
    344     impl->HandleEvent(ev);
    345     atomic_store(&impl->event, 0, memory_order_release);
    346   }
    347   __tsan_func_exit();
    348   return 0;
    349 }
    350 
    351 void ScopedThread::Impl::send(Event *e) {
    352   if (main) {
    353     HandleEvent(e);
    354   } else {
    355     CHECK_EQ(atomic_load(&event, memory_order_relaxed), 0);
    356     atomic_store(&event, (uintptr_t)e, memory_order_release);
    357     while (atomic_load(&event, memory_order_acquire) != 0)
    358       sched_yield();
    359   }
    360 }
    361 
    362 ScopedThread::ScopedThread(bool detached, bool main) {
    363   impl_ = new Impl;
    364   impl_->main = main;
    365   impl_->detached = detached;
    366   atomic_store(&impl_->event, 0, memory_order_relaxed);
    367   if (!main) {
    368     pthread_attr_t attr;
    369     pthread_attr_init(&attr);
    370     pthread_attr_setdetachstate(
    371         &attr, detached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE);
    372     pthread_attr_setstacksize(&attr, 64*1024);
    373     __interceptor_pthread_create(&impl_->thread, &attr,
    374         ScopedThread::Impl::ScopedThreadCallback, impl_);
    375   }
    376 }
    377 
    378 ScopedThread::~ScopedThread() {
    379   if (!impl_->main) {
    380     Event event(Event::SHUTDOWN);
    381     impl_->send(&event);
    382     if (!impl_->detached)
    383       __interceptor_pthread_join(impl_->thread, 0);
    384   }
    385   delete impl_;
    386 }
    387 
    388 void ScopedThread::Detach() {
    389   CHECK(!impl_->main);
    390   CHECK(!impl_->detached);
    391   impl_->detached = true;
    392   __interceptor_pthread_detach(impl_->thread);
    393 }
    394 
    395 void ScopedThread::Access(void *addr, bool is_write,
    396                           int size, bool expect_race) {
    397   Event event(is_write ? Event::WRITE : Event::READ, addr, size);
    398   if (expect_race)
    399     event.ExpectReport(ReportTypeRace);
    400   impl_->send(&event);
    401 }
    402 
    403 void ScopedThread::VptrUpdate(const MemLoc &vptr,
    404                               const MemLoc &new_val,
    405                               bool expect_race) {
    406   Event event(Event::VPTR_UPDATE, vptr.loc(), (uptr)new_val.loc());
    407   if (expect_race)
    408     event.ExpectReport(ReportTypeRace);
    409   impl_->send(&event);
    410 }
    411 
    412 void ScopedThread::Call(void(*pc)()) {
    413   Event event(Event::CALL, (void*)((uintptr_t)pc));
    414   impl_->send(&event);
    415 }
    416 
    417 void ScopedThread::Return() {
    418   Event event(Event::RETURN);
    419   impl_->send(&event);
    420 }
    421 
    422 void ScopedThread::Create(const Mutex &m) {
    423   Event event(Event::MUTEX_CREATE, &m);
    424   impl_->send(&event);
    425 }
    426 
    427 void ScopedThread::Destroy(const Mutex &m) {
    428   Event event(Event::MUTEX_DESTROY, &m);
    429   impl_->send(&event);
    430 }
    431 
    432 void ScopedThread::Lock(const Mutex &m) {
    433   Event event(Event::MUTEX_LOCK, &m);
    434   impl_->send(&event);
    435 }
    436 
    437 bool ScopedThread::TryLock(const Mutex &m) {
    438   Event event(Event::MUTEX_TRYLOCK, &m);
    439   impl_->send(&event);
    440   return event.res;
    441 }
    442 
    443 void ScopedThread::Unlock(const Mutex &m) {
    444   Event event(Event::MUTEX_UNLOCK, &m);
    445   impl_->send(&event);
    446 }
    447 
    448 void ScopedThread::ReadLock(const Mutex &m) {
    449   Event event(Event::MUTEX_READLOCK, &m);
    450   impl_->send(&event);
    451 }
    452 
    453 bool ScopedThread::TryReadLock(const Mutex &m) {
    454   Event event(Event::MUTEX_TRYREADLOCK, &m);
    455   impl_->send(&event);
    456   return event.res;
    457 }
    458 
    459 void ScopedThread::ReadUnlock(const Mutex &m) {
    460   Event event(Event::MUTEX_READUNLOCK, &m);
    461   impl_->send(&event);
    462 }
    463 
    464 void ScopedThread::Memcpy(void *dst, const void *src, int size,
    465                           bool expect_race) {
    466   Event event(Event::MEMCPY, dst, (uptr)src, size);
    467   if (expect_race)
    468     event.ExpectReport(ReportTypeRace);
    469   impl_->send(&event);
    470 }
    471 
    472 void ScopedThread::Memset(void *dst, int val, int size,
    473                           bool expect_race) {
    474   Event event(Event::MEMSET, dst, val, size);
    475   if (expect_race)
    476     event.ExpectReport(ReportTypeRace);
    477   impl_->send(&event);
    478 }
    479