sanitizer_thread_registry.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //===-- sanitizer_thread_registry.h -----------------------------*- C++ -*-===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is shared between sanitizer tools.
  9. //
  10. // General thread bookkeeping functionality.
  11. //===----------------------------------------------------------------------===//
  12. #ifndef SANITIZER_THREAD_REGISTRY_H
  13. #define SANITIZER_THREAD_REGISTRY_H
  14. #include "sanitizer_common.h"
  15. #include "sanitizer_list.h"
  16. #include "sanitizer_mutex.h"
  17. namespace __sanitizer {
  18. enum ThreadStatus {
  19. ThreadStatusInvalid, // Non-existent thread, data is invalid.
  20. ThreadStatusCreated, // Created but not yet running.
  21. ThreadStatusRunning, // The thread is currently running.
  22. ThreadStatusFinished, // Joinable thread is finished but not yet joined.
  23. ThreadStatusDead // Joined, but some info is still available.
  24. };
  25. // Generic thread context. Specific sanitizer tools may inherit from it.
  26. // If thread is dead, context may optionally be reused for a new thread.
  27. class ThreadContextBase {
  28. public:
  29. explicit ThreadContextBase(u32 tid);
  30. ~ThreadContextBase(); // Should never be called.
  31. const u32 tid; // Thread ID. Main thread should have tid = 0.
  32. u64 unique_id; // Unique thread ID.
  33. u32 reuse_count; // Number of times this tid was reused.
  34. uptr os_id; // PID (used for reporting).
  35. uptr user_id; // Some opaque user thread id (e.g. pthread_t).
  36. char name[64]; // As annotated by user.
  37. ThreadStatus status;
  38. bool detached;
  39. u32 parent_tid;
  40. ThreadContextBase *next; // For storing thread contexts in a list.
  41. void SetName(const char *new_name);
  42. void SetDead();
  43. void SetJoined(void *arg);
  44. void SetFinished();
  45. void SetStarted(uptr _os_id, void *arg);
  46. void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
  47. u32 _parent_tid, void *arg);
  48. void Reset();
  49. // The following methods may be overriden by subclasses.
  50. // Some of them take opaque arg that may be optionally be used
  51. // by subclasses.
  52. virtual void OnDead() {}
  53. virtual void OnJoined(void *arg) {}
  54. virtual void OnFinished() {}
  55. virtual void OnStarted(void *arg) {}
  56. virtual void OnCreated(void *arg) {}
  57. virtual void OnReset() {}
  58. virtual void OnDetached(void *arg) {}
  59. };
  60. typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);
  61. class ThreadRegistry {
  62. public:
  63. static const u32 kUnknownTid;
  64. ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
  65. u32 thread_quarantine_size, u32 max_reuse = 0);
  66. void GetNumberOfThreads(uptr *total = 0, uptr *running = 0, uptr *alive = 0);
  67. uptr GetMaxAliveThreads();
  68. void Lock() { mtx_.Lock(); }
  69. void CheckLocked() { mtx_.CheckLocked(); }
  70. void Unlock() { mtx_.Unlock(); }
  71. // Should be guarded by ThreadRegistryLock.
  72. ThreadContextBase *GetThreadLocked(u32 tid) {
  73. DCHECK_LT(tid, n_contexts_);
  74. return threads_[tid];
  75. }
  76. u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);
  77. typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
  78. // Invokes callback with a specified arg for each thread context.
  79. // Should be guarded by ThreadRegistryLock.
  80. void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg);
  81. typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg);
  82. // Finds a thread using the provided callback. Returns kUnknownTid if no
  83. // thread is found.
  84. u32 FindThread(FindThreadCallback cb, void *arg);
  85. // Should be guarded by ThreadRegistryLock. Return 0 if no thread
  86. // is found.
  87. ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,
  88. void *arg);
  89. ThreadContextBase *FindThreadContextByOsIDLocked(uptr os_id);
  90. void SetThreadName(u32 tid, const char *name);
  91. void SetThreadNameByUserId(uptr user_id, const char *name);
  92. void DetachThread(u32 tid, void *arg);
  93. void JoinThread(u32 tid, void *arg);
  94. void FinishThread(u32 tid);
  95. void StartThread(u32 tid, uptr os_id, void *arg);
  96. private:
  97. const ThreadContextFactory context_factory_;
  98. const u32 max_threads_;
  99. const u32 thread_quarantine_size_;
  100. const u32 max_reuse_;
  101. BlockingMutex mtx_;
  102. u32 n_contexts_; // Number of created thread contexts,
  103. // at most max_threads_.
  104. u64 total_threads_; // Total number of created threads. May be greater than
  105. // max_threads_ if contexts were reused.
  106. uptr alive_threads_; // Created or running.
  107. uptr max_alive_threads_;
  108. uptr running_threads_;
  109. ThreadContextBase **threads_; // Array of thread contexts is leaked.
  110. IntrusiveList<ThreadContextBase> dead_threads_;
  111. IntrusiveList<ThreadContextBase> invalid_threads_;
  112. void QuarantinePush(ThreadContextBase *tctx);
  113. ThreadContextBase *QuarantinePop();
  114. };
  115. typedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock;
  116. } // namespace __sanitizer
  117. #endif // SANITIZER_THREAD_REGISTRY_H