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