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