| 357 | [[clang::optnone]] |
| 358 | #elif defined(__GNUC__) |
| 359 | __attribute__((optimize("O0"))) |
| 360 | #endif |
| 361 | void Thread::SuperviseThread(const char* name, const string& category, |
| 362 | const Thread::ThreadFunctor& functor, const ThreadDebugInfo* parent_thread_info, |
| 363 | Promise<int64_t>* thread_started) { |
| 364 | int64_t system_tid = syscall(SYS_gettid); |
| 365 | if (system_tid == -1) { |
| 366 | string error_msg = GetStrErrMsg(); |
| 367 | LOG_EVERY_N(INFO, 100) << "Could not determine thread ID: " << error_msg; |
| 368 | } |
| 369 | // Store the final thread name in thread-local storage so the name pointer remains |
| 370 | // valid for pstack/gdb throughout the thread's lifetime, even if the Thread object |
| 371 | // that originally held the name gets destroyed (e.g., after Join() or Detach()). |
| 372 | thread_local string tls_name; |
| 373 | tls_name = (name == nullptr || name[0] == '\0') |
| 374 | ? Substitute("thread-$0", system_tid) |
| 375 | : string(name); |
| 376 | // Keep const char* parameter pointing at thread-local storage for pstack visibility. |
| 377 | name = tls_name.c_str(); |
| 378 | |
| 379 | // Make a copy, since we want to refer to these variables after the unsafe point below. |
| 380 | string category_copy = category.empty() ? "no-category" : category; |
| 381 | shared_ptr<ThreadMgr> thread_mgr_ref = thread_manager; |
| 382 | |
| 383 | // Use boost's get_id rather than the system thread ID as the unique key for this thread |
| 384 | // since the latter is more prone to being recycled. |
| 385 | thread_mgr_ref->AddThread(this_thread::get_id(), tls_name, category_copy, system_tid); |
| 386 | |
| 387 | ThreadDebugInfo thread_debug_info; |
| 388 | thread_debug_info.SetThreadName(tls_name); |
| 389 | thread_debug_info.SetParentInfo(parent_thread_info); |
| 390 | |
| 391 | thread_started->Set(system_tid); |
| 392 | |
| 393 | // Any reference to any parameter not copied in by value may no longer be valid after |
| 394 | // this point, since the caller that is waiting on *tid != 0 may wake, take the lock and |
| 395 | // destroy the enclosing Thread object. |
| 396 | |
| 397 | functor(); |
| 398 | thread_mgr_ref->RemoveThread(this_thread::get_id(), category_copy); |
| 399 | } |
| 400 | |
| 401 | void ThreadGroup::AddThread(unique_ptr<Thread>&& thread) { |
| 402 | threads_.emplace_back(move(thread)); |
nothing calls this directly
no test coverage detected