• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
thread_identityPerThreadSynch61   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) && !defined(__MINGW32__)
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
CurrentThreadIdentityIfPresent()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_
274