Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-18 09:41:34

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // Each active thread has an ThreadIdentity that may represent the thread in
0016 // various level interfaces.  ThreadIdentity objects are never deallocated.
0017 // When a thread terminates, its ThreadIdentity object may be reused for a
0018 // thread created later.
0019 
0020 #ifndef ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
0021 #define ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
0022 
0023 #ifndef _WIN32
0024 #include <pthread.h>
0025 // Defines __GOOGLE_GRTE_VERSION__ (via glibc-specific features.h) when
0026 // supported.
0027 #include <unistd.h>
0028 #endif
0029 
0030 #include <atomic>
0031 #include <cstdint>
0032 
0033 #include "absl/base/config.h"
0034 #include "absl/base/internal/per_thread_tls.h"
0035 #include "absl/base/optimization.h"
0036 
0037 namespace absl {
0038 ABSL_NAMESPACE_BEGIN
0039 
0040 struct SynchLocksHeld;
0041 struct SynchWaitParams;
0042 
0043 namespace base_internal {
0044 
0045 class SpinLock;
0046 struct ThreadIdentity;
0047 
0048 // Used by the implementation of absl::Mutex and absl::CondVar.
0049 struct PerThreadSynch {
0050   // The internal representation of absl::Mutex and absl::CondVar rely
0051   // on the alignment of PerThreadSynch. Both store the address of the
0052   // PerThreadSynch in the high-order bits of their internal state,
0053   // which means the low kLowZeroBits of the address of PerThreadSynch
0054   // must be zero.
0055   static constexpr int kLowZeroBits = 8;
0056   static constexpr int kAlignment = 1 << kLowZeroBits;
0057 
0058   // Returns the associated ThreadIdentity.
0059   // This can be implemented as a cast because we guarantee
0060   // PerThreadSynch is the first element of ThreadIdentity.
0061   ThreadIdentity* thread_identity() {
0062     return reinterpret_cast<ThreadIdentity*>(this);
0063   }
0064 
0065   PerThreadSynch* next;  // Circular waiter queue; initialized to 0.
0066   PerThreadSynch* skip;  // If non-zero, all entries in Mutex queue
0067                          // up to and including "skip" have same
0068                          // condition as this, and will be woken later
0069   bool may_skip;         // if false while on mutex queue, a mutex unlocker
0070                          // is using this PerThreadSynch as a terminator.  Its
0071                          // skip field must not be filled in because the loop
0072                          // might then skip over the terminator.
0073   bool wake;             // This thread is to be woken from a Mutex.
0074   // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
0075   // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
0076   //
0077   // The value of "x->cond_waiter" is meaningless if "x" is not on a
0078   // Mutex waiter list.
0079   bool cond_waiter;
0080   bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
0081                          // true if UnlockSlow could be searching
0082                          // for a waiter to wake.  Used for an optimization
0083                          // in Enqueue().  true is always a valid value.
0084                          // Can be reset to false when the unlocker or any
0085                          // writer releases the lock, or a reader fully
0086                          // releases the lock.  It may not be set to false
0087                          // by a reader that decrements the count to
0088                          // non-zero. protected by mutex spinlock
0089   bool suppress_fatal_errors;  // If true, try to proceed even in the face
0090                                // of broken invariants.  This is used within
0091                                // fatal signal handlers to improve the
0092                                // chances of debug logging information being
0093                                // output successfully.
0094   int priority;                // Priority of thread (updated every so often).
0095 
0096   // State values:
0097   //   kAvailable: This PerThreadSynch is available.
0098   //   kQueued: This PerThreadSynch is unavailable, it's currently queued on a
0099   //            Mutex or CondVar waistlist.
0100   //
0101   // Transitions from kQueued to kAvailable require a release
0102   // barrier. This is needed as a waiter may use "state" to
0103   // independently observe that it's no longer queued.
0104   //
0105   // Transitions from kAvailable to kQueued require no barrier, they
0106   // are externally ordered by the Mutex.
0107   enum State { kAvailable, kQueued };
0108   std::atomic<State> state;
0109 
0110   // The wait parameters of the current wait.  waitp is null if the
0111   // thread is not waiting. Transitions from null to non-null must
0112   // occur before the enqueue commit point (state = kQueued in
0113   // Enqueue() and CondVarEnqueue()). Transitions from non-null to
0114   // null must occur after the wait is finished (state = kAvailable in
0115   // Mutex::Block() and CondVar::WaitCommon()). This field may be
0116   // changed only by the thread that describes this PerThreadSynch.  A
0117   // special case is Fer(), which calls Enqueue() on another thread,
0118   // but with an identical SynchWaitParams pointer, thus leaving the
0119   // pointer unchanged.
0120   SynchWaitParams* waitp;
0121 
0122   intptr_t readers;  // Number of readers in mutex.
0123 
0124   // When priority will next be read (cycles).
0125   int64_t next_priority_read_cycles;
0126 
0127   // Locks held; used during deadlock detection.
0128   // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
0129   SynchLocksHeld* all_locks;
0130 };
0131 
0132 // The instances of this class are allocated in NewThreadIdentity() with an
0133 // alignment of PerThreadSynch::kAlignment.
0134 //
0135 // NOTE: The layout of fields in this structure is critical, please do not
0136 //       add, remove, or modify the field placements without fully auditing the
0137 //       layout.
0138 struct ThreadIdentity {
0139   // Must be the first member.  The Mutex implementation requires that
0140   // the PerThreadSynch object associated with each thread is
0141   // PerThreadSynch::kAlignment aligned.  We provide this alignment on
0142   // ThreadIdentity itself.
0143   PerThreadSynch per_thread_synch;
0144 
0145   // Private: Reserved for absl::synchronization_internal::Waiter.
0146   struct WaiterState {
0147     alignas(void*) char data[256];
0148   } waiter_state;
0149 
0150   // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
0151   std::atomic<int>* blocked_count_ptr;
0152 
0153   // The following variables are mostly read/written just by the
0154   // thread itself.  The only exception is that these are read by
0155   // a ticker thread as a hint.
0156   std::atomic<int> ticker;      // Tick counter, incremented once per second.
0157   std::atomic<int> wait_start;  // Ticker value when thread started waiting.
0158   std::atomic<bool> is_idle;    // Has thread become idle yet?
0159 
0160   ThreadIdentity* next;
0161 };
0162 
0163 // Returns the ThreadIdentity object representing the calling thread; guaranteed
0164 // to be unique for its lifetime.  The returned object will remain valid for the
0165 // program's lifetime; although it may be re-assigned to a subsequent thread.
0166 // If one does not exist, return nullptr instead.
0167 //
0168 // Does not malloc(*), and is async-signal safe.
0169 // [*] Technically pthread_setspecific() does malloc on first use; however this
0170 // is handled internally within tcmalloc's initialization already. Note that
0171 // darwin does *not* use tcmalloc, so this can catch you if using MallocHooks
0172 // on Apple platforms. Whatever function is calling your MallocHooks will need
0173 // to watch for recursion on Apple platforms.
0174 //
0175 // New ThreadIdentity objects can be constructed and associated with a thread
0176 // by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.
0177 ThreadIdentity* CurrentThreadIdentityIfPresent();
0178 
0179 using ThreadIdentityReclaimerFunction = void (*)(void*);
0180 
0181 // Sets the current thread identity to the given value.  'reclaimer' is a
0182 // pointer to the global function for cleaning up instances on thread
0183 // destruction.
0184 void SetCurrentThreadIdentity(ThreadIdentity* identity,
0185                               ThreadIdentityReclaimerFunction reclaimer);
0186 
0187 // Removes the currently associated ThreadIdentity from the running thread.
0188 // This must be called from inside the ThreadIdentityReclaimerFunction, and only
0189 // from that function.
0190 void ClearCurrentThreadIdentity();
0191 
0192 // May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode
0193 // index>
0194 #ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
0195 #error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be directly set
0196 #else
0197 #define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0
0198 #endif
0199 
0200 #ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS
0201 #error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be directly set
0202 #else
0203 #define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1
0204 #endif
0205 
0206 #ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11
0207 #error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be directly set
0208 #else
0209 #define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2
0210 #endif
0211 
0212 #ifdef ABSL_THREAD_IDENTITY_MODE
0213 #error ABSL_THREAD_IDENTITY_MODE cannot be directly set
0214 #elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
0215 #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
0216 #elif defined(_WIN32) && !defined(__MINGW32__)
0217 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
0218 #elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
0219 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
0220 #elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
0221     (__GOOGLE_GRTE_VERSION__ >= 20140228L)
0222 // Support for async-safe TLS was specifically added in GRTEv4.  It's not
0223 // present in the upstream eglibc.
0224 // Note:  Current default for production systems.
0225 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_TLS
0226 #else
0227 #define ABSL_THREAD_IDENTITY_MODE \
0228   ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
0229 #endif
0230 
0231 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
0232     ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
0233 
0234 #if ABSL_PER_THREAD_TLS
0235 ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*
0236     thread_identity_ptr;
0237 #elif defined(ABSL_HAVE_THREAD_LOCAL)
0238 ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
0239 #else
0240 #error Thread-local storage not detected on this platform
0241 #endif
0242 
0243 // thread_local variables cannot be in headers exposed by DLLs or in certain
0244 // build configurations on Apple platforms. However, it is important for
0245 // performance reasons in general that `CurrentThreadIdentityIfPresent` be
0246 // inlined. In the other cases we opt to have the function not be inlined. Note
0247 // that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
0248 // this entire inline definition.
0249 #if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) && \
0250     !defined(ABSL_CONSUME_DLL)
0251 #define ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT 1
0252 #endif
0253 
0254 #ifdef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
0255 inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
0256   return thread_identity_ptr;
0257 }
0258 #endif
0259 
0260 #elif ABSL_THREAD_IDENTITY_MODE != \
0261     ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
0262 #error Unknown ABSL_THREAD_IDENTITY_MODE
0263 #endif
0264 
0265 }  // namespace base_internal
0266 ABSL_NAMESPACE_END
0267 }  // namespace absl
0268 
0269 #endif  // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_