tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

thread_identity.h (11476B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 // Each active thread has an ThreadIdentity that may represent the thread in
     16 // various level interfaces.  ThreadIdentity objects are never deallocated.
     17 // When a thread terminates, its ThreadIdentity object may be reused for a
     18 // thread created later.
     19 
     20 #ifndef ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
     21 #define ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
     22 
     23 #ifndef _WIN32
     24 #include <pthread.h>
     25 // Defines __GOOGLE_GRTE_VERSION__ (via glibc-specific features.h) when
     26 // supported.
     27 #include <unistd.h>
     28 #endif
     29 
     30 #include <atomic>
     31 #include <cstdint>
     32 
     33 #include "absl/base/config.h"
     34 #include "absl/base/internal/per_thread_tls.h"
     35 #include "absl/base/optimization.h"
     36 
     37 namespace absl {
     38 ABSL_NAMESPACE_BEGIN
     39 
     40 struct SynchLocksHeld;
     41 struct SynchWaitParams;
     42 
     43 namespace base_internal {
     44 
     45 class SpinLock;
     46 struct ThreadIdentity;
     47 
     48 // Used by the implementation of absl::Mutex and absl::CondVar.
     49 struct PerThreadSynch {
     50  // The internal representation of absl::Mutex and absl::CondVar rely
     51  // on the alignment of PerThreadSynch. Both store the address of the
     52  // PerThreadSynch in the high-order bits of their internal state,
     53  // which means the low kLowZeroBits of the address of PerThreadSynch
     54  // must be zero.
     55  static constexpr int kLowZeroBits = 8;
     56  static constexpr int kAlignment = 1 << kLowZeroBits;
     57 
     58  // Returns the associated ThreadIdentity.
     59  // This can be implemented as a cast because we guarantee
     60  // PerThreadSynch is the first element of ThreadIdentity.
     61  ThreadIdentity* thread_identity() {
     62    return reinterpret_cast<ThreadIdentity*>(this);
     63  }
     64 
     65  PerThreadSynch* next;  // Circular waiter queue; initialized to 0.
     66  PerThreadSynch* skip;  // If non-zero, all entries in Mutex queue
     67                         // up to and including "skip" have same
     68                         // condition as this, and will be woken later
     69  bool may_skip;         // if false while on mutex queue, a mutex unlocker
     70                         // is using this PerThreadSynch as a terminator.  Its
     71                         // skip field must not be filled in because the loop
     72                         // might then skip over the terminator.
     73  bool wake;             // This thread is to be woken from a Mutex.
     74  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
     75  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
     76  //
     77  // The value of "x->cond_waiter" is meaningless if "x" is not on a
     78  // Mutex waiter list.
     79  bool cond_waiter;
     80  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
     81                         // true if UnlockSlow could be searching
     82                         // for a waiter to wake.  Used for an optimization
     83                         // in Enqueue().  true is always a valid value.
     84                         // Can be reset to false when the unlocker or any
     85                         // writer releases the lock, or a reader fully
     86                         // releases the lock.  It may not be set to false
     87                         // by a reader that decrements the count to
     88                         // non-zero. protected by mutex spinlock
     89  bool suppress_fatal_errors;  // If true, try to proceed even in the face
     90                               // of broken invariants.  This is used within
     91                               // fatal signal handlers to improve the
     92                               // chances of debug logging information being
     93                               // output successfully.
     94  int priority;                // Priority of thread (updated every so often).
     95 
     96  // State values:
     97  //   kAvailable: This PerThreadSynch is available.
     98  //   kQueued: This PerThreadSynch is unavailable, it's currently queued on a
     99  //            Mutex or CondVar waistlist.
    100  //
    101  // Transitions from kQueued to kAvailable require a release
    102  // barrier. This is needed as a waiter may use "state" to
    103  // independently observe that it's no longer queued.
    104  //
    105  // Transitions from kAvailable to kQueued require no barrier, they
    106  // are externally ordered by the Mutex.
    107  enum State { kAvailable, kQueued };
    108  std::atomic<State> state;
    109 
    110  // The wait parameters of the current wait.  waitp is null if the
    111  // thread is not waiting. Transitions from null to non-null must
    112  // occur before the enqueue commit point (state = kQueued in
    113  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
    114  // null must occur after the wait is finished (state = kAvailable in
    115  // Mutex::Block() and CondVar::WaitCommon()). This field may be
    116  // changed only by the thread that describes this PerThreadSynch.  A
    117  // special case is Fer(), which calls Enqueue() on another thread,
    118  // but with an identical SynchWaitParams pointer, thus leaving the
    119  // pointer unchanged.
    120  SynchWaitParams* waitp;
    121 
    122  intptr_t readers;  // Number of readers in mutex.
    123 
    124  // When priority will next be read (cycles).
    125  int64_t next_priority_read_cycles;
    126 
    127  // Locks held; used during deadlock detection.
    128  // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
    129  SynchLocksHeld* all_locks;
    130 };
    131 
    132 // The instances of this class are allocated in NewThreadIdentity() with an
    133 // alignment of PerThreadSynch::kAlignment and never destroyed. Initialization
    134 // should happen in OneTimeInitThreadIdentity().
    135 //
    136 // Instances may be reused by new threads - fields should be reset in
    137 // ResetThreadIdentityBetweenReuse().
    138 //
    139 // NOTE: The layout of fields in this structure is critical, please do not
    140 //       add, remove, or modify the field placements without fully auditing the
    141 //       layout.
    142 struct ThreadIdentity {
    143  // Must be the first member.  The Mutex implementation requires that
    144  // the PerThreadSynch object associated with each thread is
    145  // PerThreadSynch::kAlignment aligned.  We provide this alignment on
    146  // ThreadIdentity itself.
    147  PerThreadSynch per_thread_synch;
    148 
    149  // Private: Reserved for absl::synchronization_internal::Waiter.
    150  struct WaiterState {
    151    alignas(void*) char data[256];
    152  } waiter_state;
    153 
    154  // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
    155  std::atomic<int>* blocked_count_ptr;
    156 
    157  // The following variables are mostly read/written just by the
    158  // thread itself.  The only exception is that these are read by
    159  // a ticker thread as a hint.
    160  std::atomic<int> ticker;      // Tick counter, incremented once per second.
    161  std::atomic<int> wait_start;  // Ticker value when thread started waiting.
    162  std::atomic<bool> is_idle;    // Has thread become idle yet?
    163 
    164  ThreadIdentity* next;
    165 };
    166 
    167 // Returns the ThreadIdentity object representing the calling thread; guaranteed
    168 // to be unique for its lifetime.  The returned object will remain valid for the
    169 // program's lifetime; although it may be re-assigned to a subsequent thread.
    170 // If one does not exist, return nullptr instead.
    171 //
    172 // Does not malloc(*), and is async-signal safe.
    173 // [*] Technically pthread_setspecific() does malloc on first use; however this
    174 // is handled internally within tcmalloc's initialization already. Note that
    175 // darwin does *not* use tcmalloc, so this can catch you if using MallocHooks
    176 // on Apple platforms. Whatever function is calling your MallocHooks will need
    177 // to watch for recursion on Apple platforms.
    178 //
    179 // New ThreadIdentity objects can be constructed and associated with a thread
    180 // by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.
    181 ThreadIdentity* CurrentThreadIdentityIfPresent();
    182 
    183 using ThreadIdentityReclaimerFunction = void (*)(void*);
    184 
    185 // Sets the current thread identity to the given value.  'reclaimer' is a
    186 // pointer to the global function for cleaning up instances on thread
    187 // destruction.
    188 void SetCurrentThreadIdentity(ThreadIdentity* identity,
    189                              ThreadIdentityReclaimerFunction reclaimer);
    190 
    191 // Removes the currently associated ThreadIdentity from the running thread.
    192 // This must be called from inside the ThreadIdentityReclaimerFunction, and only
    193 // from that function.
    194 void ClearCurrentThreadIdentity();
    195 
    196 // May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode
    197 // index>
    198 #ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
    199 #error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be directly set
    200 #else
    201 #define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0
    202 #endif
    203 
    204 #ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS
    205 #error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be directly set
    206 #else
    207 #define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1
    208 #endif
    209 
    210 #ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11
    211 #error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be directly set
    212 #else
    213 #define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2
    214 #endif
    215 
    216 #ifdef ABSL_THREAD_IDENTITY_MODE
    217 #error ABSL_THREAD_IDENTITY_MODE cannot be directly set
    218 #elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
    219 #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
    220 #elif defined(_WIN32)
    221 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
    222 #elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
    223 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
    224 #elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
    225    (__GOOGLE_GRTE_VERSION__ >= 20140228L)
    226 // Support for async-safe TLS was specifically added in GRTEv4.  It's not
    227 // present in the upstream eglibc.
    228 // Note:  Current default for production systems.
    229 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_TLS
    230 #else
    231 #define ABSL_THREAD_IDENTITY_MODE \
    232  ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
    233 #endif
    234 
    235 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
    236    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
    237 
    238 #if ABSL_PER_THREAD_TLS
    239 ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*
    240    thread_identity_ptr;
    241 #elif defined(ABSL_HAVE_THREAD_LOCAL)
    242 ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
    243 #else
    244 #error Thread-local storage not detected on this platform
    245 #endif
    246 
    247 // thread_local variables cannot be in headers exposed by DLLs or in certain
    248 // build configurations on Apple platforms. However, it is important for
    249 // performance reasons in general that `CurrentThreadIdentityIfPresent` be
    250 // inlined. In the other cases we opt to have the function not be inlined. Note
    251 // that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
    252 // this entire inline definition.
    253 #if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) && \
    254    !defined(ABSL_CONSUME_DLL)
    255 #define ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT 1
    256 #endif
    257 
    258 #ifdef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
    259 inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
    260  return thread_identity_ptr;
    261 }
    262 #endif
    263 
    264 #elif ABSL_THREAD_IDENTITY_MODE != \
    265    ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
    266 #error Unknown ABSL_THREAD_IDENTITY_MODE
    267 #endif
    268 
    269 }  // namespace base_internal
    270 ABSL_NAMESPACE_END
    271 }  // namespace absl
    272 
    273 #endif  // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_