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