brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · 8adc420 Raw
174 lines · c
1//===-- sanitizer_thread_registry.h -----------------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is shared between sanitizer tools.10//11// General thread bookkeeping functionality.12//===----------------------------------------------------------------------===//13 14#ifndef SANITIZER_THREAD_REGISTRY_H15#define SANITIZER_THREAD_REGISTRY_H16 17#include "sanitizer_common.h"18#include "sanitizer_dense_map.h"19#include "sanitizer_list.h"20#include "sanitizer_mutex.h"21 22namespace __sanitizer {23 24enum ThreadStatus {25  ThreadStatusInvalid,   // Non-existent thread, data is invalid.26  ThreadStatusCreated,   // Created but not yet running.27  ThreadStatusRunning,   // The thread is currently running.28  ThreadStatusFinished,  // Joinable thread is finished but not yet joined.29  ThreadStatusDead       // Joined, but some info is still available.30};31 32enum class ThreadType {33  Regular, // Normal thread34  Worker,  // macOS Grand Central Dispatch (GCD) worker thread35  Fiber,   // Fiber36};37 38// Generic thread context. Specific sanitizer tools may inherit from it.39// If thread is dead, context may optionally be reused for a new thread.40class ThreadContextBase {41 public:42  explicit ThreadContextBase(u32 tid);43  const u32 tid;  // Thread ID. Main thread should have tid = 0.44  u64 unique_id;  // Unique thread ID.45  u32 reuse_count;  // Number of times this tid was reused.46  ThreadID os_id;   // PID (used for reporting).47  uptr user_id;   // Some opaque user thread id (e.g. pthread_t).48  char name[64];  // As annotated by user.49 50  ThreadStatus status;51  bool detached;52  ThreadType thread_type;53 54  u32 parent_tid;55  u32 stack_id;56  ThreadContextBase *next;  // For storing thread contexts in a list.57 58  atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished59 60  void SetName(const char *new_name);61 62  void SetDead();63  void SetJoined(void *arg);64  void SetFinished();65  void SetStarted(ThreadID _os_id, ThreadType _thread_type, void *arg);66  void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,67                  u32 _parent_tid, u32 _stack_tid, void *arg);68  void Reset();69 70  void SetDestroyed();71  bool GetDestroyed();72 73  // The following methods may be overriden by subclasses.74  // Some of them take opaque arg that may be optionally be used75  // by subclasses.76  virtual void OnDead() {}77  virtual void OnJoined(void *arg) {}78  virtual void OnFinished() {}79  virtual void OnStarted(void *arg) {}80  virtual void OnCreated(void *arg) {}81  virtual void OnReset() {}82  virtual void OnDetached(void *arg) {}83 84 protected:85  ~ThreadContextBase();86};87 88typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);89 90class SANITIZER_MUTEX ThreadRegistry {91 public:92  ThreadRegistry(ThreadContextFactory factory);93  ThreadRegistry(ThreadContextFactory factory, u32 max_threads,94                 u32 thread_quarantine_size, u32 max_reuse);95  void GetNumberOfThreads(uptr *total = nullptr, uptr *running = nullptr,96                          uptr *alive = nullptr);97  uptr GetMaxAliveThreads();98 99  void Lock() SANITIZER_ACQUIRE() { mtx_.Lock(); }100  void CheckLocked() const SANITIZER_CHECK_LOCKED() { mtx_.CheckLocked(); }101  void Unlock() SANITIZER_RELEASE() { mtx_.Unlock(); }102 103  // Should be guarded by ThreadRegistryLock.104  ThreadContextBase *GetThreadLocked(u32 tid) {105    return tid < threads_.size() ? threads_[tid] : nullptr;106  }107 108  u32 NumThreadsLocked() const { return threads_.size(); }109 110  u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, u32 stack_tid,111                   void *arg);112  u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg) {113    return CreateThread(user_id, detached, parent_tid, 0, arg);114  }115 116  typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);117  // Invokes callback with a specified arg for each thread context.118  // Should be guarded by ThreadRegistryLock.119  void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg);120 121  typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg);122  // Finds a thread using the provided callback. Returns kInvalidTid if no123  // thread is found.124  u32 FindThread(FindThreadCallback cb, void *arg);125  // Should be guarded by ThreadRegistryLock. Return 0 if no thread126  // is found.127  ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,128                                             void *arg);129  ThreadContextBase *FindThreadContextByOsIDLocked(ThreadID os_id);130 131  void SetThreadName(u32 tid, const char *name);132  void SetThreadNameByUserId(uptr user_id, const char *name);133  void DetachThread(u32 tid, void *arg);134  void JoinThread(u32 tid, void *arg);135  // Finishes thread and returns previous status.136  ThreadStatus FinishThread(u32 tid);137  void StartThread(u32 tid, ThreadID os_id, ThreadType thread_type, void *arg);138  u32 ConsumeThreadUserId(uptr user_id);139  void SetThreadUserId(u32 tid, uptr user_id);140 141  // OnFork must be called in the child process after fork to purge old142  // threads that don't exist anymore (except for the current thread tid).143  // Returns number of alive threads before fork.144  u32 OnFork(u32 tid);145 146 private:147  const ThreadContextFactory context_factory_;148  const u32 max_threads_;149  const u32 thread_quarantine_size_;150  const u32 max_reuse_;151 152  Mutex mtx_;153 154  u64 total_threads_;   // Total number of created threads. May be greater than155                        // max_threads_ if contexts were reused.156  uptr alive_threads_;  // Created or running.157  uptr max_alive_threads_;158  uptr running_threads_;159 160  InternalMmapVector<ThreadContextBase *> threads_;161  IntrusiveList<ThreadContextBase> dead_threads_;162  IntrusiveList<ThreadContextBase> invalid_threads_;163  DenseMap<uptr, Tid> live_;164 165  void QuarantinePush(ThreadContextBase *tctx);166  ThreadContextBase *QuarantinePop();167};168 169typedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock;170 171} // namespace __sanitizer172 173#endif // SANITIZER_THREAD_REGISTRY_H174