1 1.1 mrg //===-- sanitizer_thread_registry.cpp -------------------------------------===// 2 1.1 mrg // 3 1.1 mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 mrg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 mrg // 7 1.1 mrg //===----------------------------------------------------------------------===// 8 1.1 mrg // 9 1.1 mrg // This file is shared between sanitizer tools. 10 1.1 mrg // 11 1.1 mrg // General thread bookkeeping functionality. 12 1.1 mrg //===----------------------------------------------------------------------===// 13 1.1 mrg 14 1.1 mrg #include "sanitizer_thread_registry.h" 15 1.1 mrg 16 1.4 mrg #include "sanitizer_placement_new.h" 17 1.4 mrg 18 1.1 mrg namespace __sanitizer { 19 1.1 mrg 20 1.1 mrg ThreadContextBase::ThreadContextBase(u32 tid) 21 1.1 mrg : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0), 22 1.1 mrg status(ThreadStatusInvalid), detached(false), 23 1.1 mrg thread_type(ThreadType::Regular), parent_tid(0), next(0) { 24 1.1 mrg name[0] = '\0'; 25 1.1 mrg atomic_store(&thread_destroyed, 0, memory_order_release); 26 1.1 mrg } 27 1.1 mrg 28 1.1 mrg ThreadContextBase::~ThreadContextBase() { 29 1.1 mrg // ThreadContextBase should never be deleted. 30 1.1 mrg CHECK(0); 31 1.1 mrg } 32 1.1 mrg 33 1.1 mrg void ThreadContextBase::SetName(const char *new_name) { 34 1.1 mrg name[0] = '\0'; 35 1.1 mrg if (new_name) { 36 1.1 mrg internal_strncpy(name, new_name, sizeof(name)); 37 1.1 mrg name[sizeof(name) - 1] = '\0'; 38 1.1 mrg } 39 1.1 mrg } 40 1.1 mrg 41 1.1 mrg void ThreadContextBase::SetDead() { 42 1.1 mrg CHECK(status == ThreadStatusRunning || 43 1.1 mrg status == ThreadStatusFinished); 44 1.1 mrg status = ThreadStatusDead; 45 1.1 mrg user_id = 0; 46 1.1 mrg OnDead(); 47 1.1 mrg } 48 1.1 mrg 49 1.1 mrg void ThreadContextBase::SetDestroyed() { 50 1.1 mrg atomic_store(&thread_destroyed, 1, memory_order_release); 51 1.1 mrg } 52 1.1 mrg 53 1.1 mrg bool ThreadContextBase::GetDestroyed() { 54 1.1 mrg return !!atomic_load(&thread_destroyed, memory_order_acquire); 55 1.1 mrg } 56 1.1 mrg 57 1.1 mrg void ThreadContextBase::SetJoined(void *arg) { 58 1.1 mrg // FIXME(dvyukov): print message and continue (it's user error). 59 1.1 mrg CHECK_EQ(false, detached); 60 1.1 mrg CHECK_EQ(ThreadStatusFinished, status); 61 1.1 mrg status = ThreadStatusDead; 62 1.1 mrg user_id = 0; 63 1.1 mrg OnJoined(arg); 64 1.1 mrg } 65 1.1 mrg 66 1.1 mrg void ThreadContextBase::SetFinished() { 67 1.1 mrg // ThreadRegistry::FinishThread calls here in ThreadStatusCreated state 68 1.1 mrg // for a thread that never actually started. In that case the thread 69 1.1 mrg // should go to ThreadStatusFinished regardless of whether it was created 70 1.1 mrg // as detached. 71 1.1 mrg if (!detached || status == ThreadStatusCreated) status = ThreadStatusFinished; 72 1.1 mrg OnFinished(); 73 1.1 mrg } 74 1.1 mrg 75 1.1 mrg void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type, 76 1.1 mrg void *arg) { 77 1.1 mrg status = ThreadStatusRunning; 78 1.1 mrg os_id = _os_id; 79 1.1 mrg thread_type = _thread_type; 80 1.1 mrg OnStarted(arg); 81 1.1 mrg } 82 1.1 mrg 83 1.1 mrg void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id, 84 1.1 mrg bool _detached, u32 _parent_tid, void *arg) { 85 1.1 mrg status = ThreadStatusCreated; 86 1.1 mrg user_id = _user_id; 87 1.1 mrg unique_id = _unique_id; 88 1.1 mrg detached = _detached; 89 1.1 mrg // Parent tid makes no sense for the main thread. 90 1.3 mrg if (tid != kMainTid) 91 1.1 mrg parent_tid = _parent_tid; 92 1.1 mrg OnCreated(arg); 93 1.1 mrg } 94 1.1 mrg 95 1.1 mrg void ThreadContextBase::Reset() { 96 1.1 mrg status = ThreadStatusInvalid; 97 1.1 mrg SetName(0); 98 1.1 mrg atomic_store(&thread_destroyed, 0, memory_order_release); 99 1.1 mrg OnReset(); 100 1.1 mrg } 101 1.1 mrg 102 1.1 mrg // ThreadRegistry implementation. 103 1.1 mrg 104 1.3 mrg ThreadRegistry::ThreadRegistry(ThreadContextFactory factory) 105 1.3 mrg : ThreadRegistry(factory, UINT32_MAX, UINT32_MAX, 0) {} 106 1.1 mrg 107 1.1 mrg ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads, 108 1.1 mrg u32 thread_quarantine_size, u32 max_reuse) 109 1.1 mrg : context_factory_(factory), 110 1.1 mrg max_threads_(max_threads), 111 1.1 mrg thread_quarantine_size_(thread_quarantine_size), 112 1.1 mrg max_reuse_(max_reuse), 113 1.4 mrg mtx_(MutexThreadRegistry), 114 1.1 mrg total_threads_(0), 115 1.1 mrg alive_threads_(0), 116 1.1 mrg max_alive_threads_(0), 117 1.1 mrg running_threads_(0) { 118 1.1 mrg dead_threads_.clear(); 119 1.1 mrg invalid_threads_.clear(); 120 1.1 mrg } 121 1.1 mrg 122 1.1 mrg void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running, 123 1.1 mrg uptr *alive) { 124 1.3 mrg ThreadRegistryLock l(this); 125 1.3 mrg if (total) 126 1.3 mrg *total = threads_.size(); 127 1.1 mrg if (running) *running = running_threads_; 128 1.1 mrg if (alive) *alive = alive_threads_; 129 1.1 mrg } 130 1.1 mrg 131 1.1 mrg uptr ThreadRegistry::GetMaxAliveThreads() { 132 1.3 mrg ThreadRegistryLock l(this); 133 1.1 mrg return max_alive_threads_; 134 1.1 mrg } 135 1.1 mrg 136 1.1 mrg u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, 137 1.1 mrg void *arg) { 138 1.3 mrg ThreadRegistryLock l(this); 139 1.3 mrg u32 tid = kInvalidTid; 140 1.1 mrg ThreadContextBase *tctx = QuarantinePop(); 141 1.1 mrg if (tctx) { 142 1.1 mrg tid = tctx->tid; 143 1.3 mrg } else if (threads_.size() < max_threads_) { 144 1.1 mrg // Allocate new thread context and tid. 145 1.3 mrg tid = threads_.size(); 146 1.1 mrg tctx = context_factory_(tid); 147 1.3 mrg threads_.push_back(tctx); 148 1.1 mrg } else { 149 1.1 mrg #if !SANITIZER_GO 150 1.1 mrg Report("%s: Thread limit (%u threads) exceeded. Dying.\n", 151 1.1 mrg SanitizerToolName, max_threads_); 152 1.1 mrg #else 153 1.1 mrg Printf("race: limit on %u simultaneously alive goroutines is exceeded," 154 1.1 mrg " dying\n", max_threads_); 155 1.1 mrg #endif 156 1.1 mrg Die(); 157 1.1 mrg } 158 1.1 mrg CHECK_NE(tctx, 0); 159 1.3 mrg CHECK_NE(tid, kInvalidTid); 160 1.1 mrg CHECK_LT(tid, max_threads_); 161 1.1 mrg CHECK_EQ(tctx->status, ThreadStatusInvalid); 162 1.1 mrg alive_threads_++; 163 1.1 mrg if (max_alive_threads_ < alive_threads_) { 164 1.1 mrg max_alive_threads_++; 165 1.1 mrg CHECK_EQ(alive_threads_, max_alive_threads_); 166 1.1 mrg } 167 1.4 mrg if (user_id) { 168 1.4 mrg // Ensure that user_id is unique. If it's not the case we are screwed. 169 1.4 mrg // Ignoring this situation may lead to very hard to debug false 170 1.4 mrg // positives later (e.g. if we join a wrong thread). 171 1.4 mrg CHECK(live_.try_emplace(user_id, tid).second); 172 1.4 mrg } 173 1.1 mrg tctx->SetCreated(user_id, total_threads_++, detached, 174 1.1 mrg parent_tid, arg); 175 1.1 mrg return tid; 176 1.1 mrg } 177 1.1 mrg 178 1.1 mrg void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb, 179 1.1 mrg void *arg) { 180 1.1 mrg CheckLocked(); 181 1.3 mrg for (u32 tid = 0; tid < threads_.size(); tid++) { 182 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 183 1.1 mrg if (tctx == 0) 184 1.1 mrg continue; 185 1.1 mrg cb(tctx, arg); 186 1.1 mrg } 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) { 190 1.3 mrg ThreadRegistryLock l(this); 191 1.3 mrg for (u32 tid = 0; tid < threads_.size(); tid++) { 192 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 193 1.1 mrg if (tctx != 0 && cb(tctx, arg)) 194 1.1 mrg return tctx->tid; 195 1.1 mrg } 196 1.3 mrg return kInvalidTid; 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg ThreadContextBase * 200 1.1 mrg ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) { 201 1.1 mrg CheckLocked(); 202 1.3 mrg for (u32 tid = 0; tid < threads_.size(); tid++) { 203 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 204 1.1 mrg if (tctx != 0 && cb(tctx, arg)) 205 1.1 mrg return tctx; 206 1.1 mrg } 207 1.1 mrg return 0; 208 1.1 mrg } 209 1.1 mrg 210 1.1 mrg static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx, 211 1.1 mrg void *arg) { 212 1.1 mrg return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid && 213 1.1 mrg tctx->status != ThreadStatusDead); 214 1.1 mrg } 215 1.1 mrg 216 1.1 mrg ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) { 217 1.1 mrg return FindThreadContextLocked(FindThreadContextByOsIdCallback, 218 1.1 mrg (void *)os_id); 219 1.1 mrg } 220 1.1 mrg 221 1.1 mrg void ThreadRegistry::SetThreadName(u32 tid, const char *name) { 222 1.3 mrg ThreadRegistryLock l(this); 223 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 224 1.1 mrg CHECK_NE(tctx, 0); 225 1.1 mrg CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning, 226 1.1 mrg tctx->status); 227 1.1 mrg tctx->SetName(name); 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) { 231 1.3 mrg ThreadRegistryLock l(this); 232 1.4 mrg if (const auto *tid = live_.find(user_id)) 233 1.4 mrg threads_[tid->second]->SetName(name); 234 1.1 mrg } 235 1.1 mrg 236 1.1 mrg void ThreadRegistry::DetachThread(u32 tid, void *arg) { 237 1.3 mrg ThreadRegistryLock l(this); 238 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 239 1.1 mrg CHECK_NE(tctx, 0); 240 1.1 mrg if (tctx->status == ThreadStatusInvalid) { 241 1.1 mrg Report("%s: Detach of non-existent thread\n", SanitizerToolName); 242 1.1 mrg return; 243 1.1 mrg } 244 1.1 mrg tctx->OnDetached(arg); 245 1.1 mrg if (tctx->status == ThreadStatusFinished) { 246 1.4 mrg if (tctx->user_id) 247 1.4 mrg live_.erase(tctx->user_id); 248 1.1 mrg tctx->SetDead(); 249 1.1 mrg QuarantinePush(tctx); 250 1.1 mrg } else { 251 1.1 mrg tctx->detached = true; 252 1.1 mrg } 253 1.1 mrg } 254 1.1 mrg 255 1.1 mrg void ThreadRegistry::JoinThread(u32 tid, void *arg) { 256 1.1 mrg bool destroyed = false; 257 1.1 mrg do { 258 1.1 mrg { 259 1.3 mrg ThreadRegistryLock l(this); 260 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 261 1.1 mrg CHECK_NE(tctx, 0); 262 1.1 mrg if (tctx->status == ThreadStatusInvalid) { 263 1.1 mrg Report("%s: Join of non-existent thread\n", SanitizerToolName); 264 1.1 mrg return; 265 1.1 mrg } 266 1.1 mrg if ((destroyed = tctx->GetDestroyed())) { 267 1.4 mrg if (tctx->user_id) 268 1.4 mrg live_.erase(tctx->user_id); 269 1.1 mrg tctx->SetJoined(arg); 270 1.1 mrg QuarantinePush(tctx); 271 1.1 mrg } 272 1.1 mrg } 273 1.1 mrg if (!destroyed) 274 1.1 mrg internal_sched_yield(); 275 1.1 mrg } while (!destroyed); 276 1.1 mrg } 277 1.1 mrg 278 1.1 mrg // Normally this is called when the thread is about to exit. If 279 1.1 mrg // called in ThreadStatusCreated state, then this thread was never 280 1.1 mrg // really started. We just did CreateThread for a prospective new 281 1.1 mrg // thread before trying to create it, and then failed to actually 282 1.1 mrg // create it, and so never called StartThread. 283 1.3 mrg ThreadStatus ThreadRegistry::FinishThread(u32 tid) { 284 1.3 mrg ThreadRegistryLock l(this); 285 1.1 mrg CHECK_GT(alive_threads_, 0); 286 1.1 mrg alive_threads_--; 287 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 288 1.1 mrg CHECK_NE(tctx, 0); 289 1.1 mrg bool dead = tctx->detached; 290 1.3 mrg ThreadStatus prev_status = tctx->status; 291 1.1 mrg if (tctx->status == ThreadStatusRunning) { 292 1.1 mrg CHECK_GT(running_threads_, 0); 293 1.1 mrg running_threads_--; 294 1.1 mrg } else { 295 1.1 mrg // The thread never really existed. 296 1.1 mrg CHECK_EQ(tctx->status, ThreadStatusCreated); 297 1.1 mrg dead = true; 298 1.1 mrg } 299 1.1 mrg tctx->SetFinished(); 300 1.1 mrg if (dead) { 301 1.4 mrg if (tctx->user_id) 302 1.4 mrg live_.erase(tctx->user_id); 303 1.1 mrg tctx->SetDead(); 304 1.1 mrg QuarantinePush(tctx); 305 1.1 mrg } 306 1.1 mrg tctx->SetDestroyed(); 307 1.3 mrg return prev_status; 308 1.1 mrg } 309 1.1 mrg 310 1.1 mrg void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type, 311 1.1 mrg void *arg) { 312 1.3 mrg ThreadRegistryLock l(this); 313 1.1 mrg running_threads_++; 314 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 315 1.1 mrg CHECK_NE(tctx, 0); 316 1.1 mrg CHECK_EQ(ThreadStatusCreated, tctx->status); 317 1.1 mrg tctx->SetStarted(os_id, thread_type, arg); 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) { 321 1.1 mrg if (tctx->tid == 0) 322 1.1 mrg return; // Don't reuse the main thread. It's a special snowflake. 323 1.1 mrg dead_threads_.push_back(tctx); 324 1.1 mrg if (dead_threads_.size() <= thread_quarantine_size_) 325 1.1 mrg return; 326 1.1 mrg tctx = dead_threads_.front(); 327 1.1 mrg dead_threads_.pop_front(); 328 1.1 mrg CHECK_EQ(tctx->status, ThreadStatusDead); 329 1.1 mrg tctx->Reset(); 330 1.1 mrg tctx->reuse_count++; 331 1.1 mrg if (max_reuse_ > 0 && tctx->reuse_count >= max_reuse_) 332 1.1 mrg return; 333 1.1 mrg invalid_threads_.push_back(tctx); 334 1.1 mrg } 335 1.1 mrg 336 1.1 mrg ThreadContextBase *ThreadRegistry::QuarantinePop() { 337 1.1 mrg if (invalid_threads_.size() == 0) 338 1.4 mrg return nullptr; 339 1.1 mrg ThreadContextBase *tctx = invalid_threads_.front(); 340 1.1 mrg invalid_threads_.pop_front(); 341 1.1 mrg return tctx; 342 1.1 mrg } 343 1.1 mrg 344 1.4 mrg u32 ThreadRegistry::ConsumeThreadUserId(uptr user_id) { 345 1.4 mrg ThreadRegistryLock l(this); 346 1.4 mrg u32 tid; 347 1.4 mrg auto *t = live_.find(user_id); 348 1.4 mrg CHECK(t); 349 1.4 mrg tid = t->second; 350 1.4 mrg live_.erase(t); 351 1.4 mrg auto *tctx = threads_[tid]; 352 1.4 mrg CHECK_EQ(tctx->user_id, user_id); 353 1.4 mrg tctx->user_id = 0; 354 1.4 mrg return tid; 355 1.4 mrg } 356 1.4 mrg 357 1.1 mrg void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) { 358 1.3 mrg ThreadRegistryLock l(this); 359 1.1 mrg ThreadContextBase *tctx = threads_[tid]; 360 1.1 mrg CHECK_NE(tctx, 0); 361 1.1 mrg CHECK_NE(tctx->status, ThreadStatusInvalid); 362 1.1 mrg CHECK_NE(tctx->status, ThreadStatusDead); 363 1.1 mrg CHECK_EQ(tctx->user_id, 0); 364 1.1 mrg tctx->user_id = user_id; 365 1.4 mrg CHECK(live_.try_emplace(user_id, tctx->tid).second); 366 1.4 mrg } 367 1.4 mrg 368 1.4 mrg u32 ThreadRegistry::OnFork(u32 tid) { 369 1.4 mrg ThreadRegistryLock l(this); 370 1.4 mrg // We only purge user_id (pthread_t) of live threads because 371 1.4 mrg // they cause CHECK failures if new threads with matching pthread_t 372 1.4 mrg // created after fork. 373 1.4 mrg // Potentially we could purge more info (ThreadContextBase themselves), 374 1.4 mrg // but it's hard to test and easy to introduce new issues by doing this. 375 1.4 mrg for (auto *tctx : threads_) { 376 1.4 mrg if (tctx->tid == tid || !tctx->user_id) 377 1.4 mrg continue; 378 1.4 mrg CHECK(live_.erase(tctx->user_id)); 379 1.4 mrg tctx->user_id = 0; 380 1.4 mrg } 381 1.4 mrg return alive_threads_; 382 1.1 mrg } 383 1.1 mrg 384 1.1 mrg } // namespace __sanitizer 385