• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BeforeInitThread(void * param)82 static void *BeforeInitThread(void *param) {
83   (void)param;
84   return 0;
85 }
86 
AtExit()87 static void AtExit() {
88 }
89 
TestMutexBeforeInit()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 {
OnReport(const ReportDesc * rep,bool suppressed)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 
allocate_addr(int size,int offset_from_aligned=0)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 
MemLoc(int offset_from_aligned)130 MemLoc::MemLoc(int offset_from_aligned)
131   : loc_(allocate_addr(16, offset_from_aligned)) {
132 }
133 
~MemLoc()134 MemLoc::~MemLoc() {
135 }
136 
Mutex(Type type)137 Mutex::Mutex(Type type)
138   : alive_()
139   , type_(type) {
140 }
141 
~Mutex()142 Mutex::~Mutex() {
143   CHECK(!alive_);
144 }
145 
Init()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 
StaticInit()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 
Destroy()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 
Lock()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 
TryLock()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 
Unlock()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 
ReadLock()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 
TryReadLock()225 bool Mutex::TryReadLock() {
226   CHECK(alive_);
227   CHECK(type_ == RW);
228   return __interceptor_pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) ==  0;
229 }
230 
ReadUnlock()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 
EventEvent264   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 
ExpectReportEvent274   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 
HandleEvent(Event * ev)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 
ScopedThreadCallback(void * arg)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 
send(Event * e)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 
ScopedThread(bool detached,bool main)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 
~ScopedThread()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 
Detach()433 void ScopedThread::Detach() {
434   CHECK(!impl_->main);
435   CHECK(!impl_->detached);
436   impl_->detached = true;
437   __interceptor_pthread_detach(impl_->thread);
438 }
439 
Access(void * addr,bool is_write,int size,bool expect_race)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 
VptrUpdate(const MemLoc & vptr,const MemLoc & new_val,bool expect_race)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 
Call(void (* pc)())457 void ScopedThread::Call(void(*pc)()) {
458   Event event(Event::CALL, (void*)((uintptr_t)pc));
459   impl_->send(&event);
460 }
461 
Return()462 void ScopedThread::Return() {
463   Event event(Event::RETURN);
464   impl_->send(&event);
465 }
466 
Create(const Mutex & m)467 void ScopedThread::Create(const Mutex &m) {
468   Event event(Event::MUTEX_CREATE, &m);
469   impl_->send(&event);
470 }
471 
Destroy(const Mutex & m)472 void ScopedThread::Destroy(const Mutex &m) {
473   Event event(Event::MUTEX_DESTROY, &m);
474   impl_->send(&event);
475 }
476 
Lock(const Mutex & m)477 void ScopedThread::Lock(const Mutex &m) {
478   Event event(Event::MUTEX_LOCK, &m);
479   impl_->send(&event);
480 }
481 
TryLock(const Mutex & m)482 bool ScopedThread::TryLock(const Mutex &m) {
483   Event event(Event::MUTEX_TRYLOCK, &m);
484   impl_->send(&event);
485   return event.res;
486 }
487 
Unlock(const Mutex & m)488 void ScopedThread::Unlock(const Mutex &m) {
489   Event event(Event::MUTEX_UNLOCK, &m);
490   impl_->send(&event);
491 }
492 
ReadLock(const Mutex & m)493 void ScopedThread::ReadLock(const Mutex &m) {
494   Event event(Event::MUTEX_READLOCK, &m);
495   impl_->send(&event);
496 }
497 
TryReadLock(const Mutex & m)498 bool ScopedThread::TryReadLock(const Mutex &m) {
499   Event event(Event::MUTEX_TRYREADLOCK, &m);
500   impl_->send(&event);
501   return event.res;
502 }
503 
ReadUnlock(const Mutex & m)504 void ScopedThread::ReadUnlock(const Mutex &m) {
505   Event event(Event::MUTEX_READUNLOCK, &m);
506   impl_->send(&event);
507 }
508 
Memcpy(void * dst,const void * src,int size,bool expect_race)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 
Memset(void * dst,int val,int size,bool expect_race)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