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