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