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