sanitizer_thread_registry.cpp 11 KB

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