blob: d2a65fd81126469ea33ad7a069607c96e5c26214 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// 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
Austin Schuhb4691e92020-12-31 12:37:18 -080033#include "absl/base/config.h"
Austin Schuh36244a12019-09-21 17:52:38 -070034#include "absl/base/internal/per_thread_tls.h"
Austin Schuhb4691e92020-12-31 12:37:18 -080035#include "absl/base/optimization.h"
Austin Schuh36244a12019-09-21 17:52:38 -070036
37namespace absl {
Austin Schuhb4691e92020-12-31 12:37:18 -080038ABSL_NAMESPACE_BEGIN
Austin Schuh36244a12019-09-21 17:52:38 -070039
40struct SynchLocksHeld;
41struct SynchWaitParams;
42
43namespace base_internal {
44
45class SpinLock;
46struct ThreadIdentity;
47
48// Used by the implementation of absl::Mutex and absl::CondVar.
49struct 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.
Austin Schuhb4691e92020-12-31 12:37:18 -080073 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).
Austin Schuh36244a12019-09-21 17:52:38 -070095
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 {
108 kAvailable,
109 kQueued
110 };
111 std::atomic<State> state;
112
Austin Schuhb4691e92020-12-31 12:37:18 -0800113 // The wait parameters of the current wait. waitp is null if the
114 // thread is not waiting. Transitions from null to non-null must
115 // occur before the enqueue commit point (state = kQueued in
116 // Enqueue() and CondVarEnqueue()). Transitions from non-null to
117 // null must occur after the wait is finished (state = kAvailable in
118 // Mutex::Block() and CondVar::WaitCommon()). This field may be
119 // changed only by the thread that describes this PerThreadSynch. A
120 // special case is Fer(), which calls Enqueue() on another thread,
121 // but with an identical SynchWaitParams pointer, thus leaving the
122 // pointer unchanged.
123 SynchWaitParams* waitp;
Austin Schuh36244a12019-09-21 17:52:38 -0700124
Austin Schuhb4691e92020-12-31 12:37:18 -0800125 intptr_t readers; // Number of readers in mutex.
Austin Schuh36244a12019-09-21 17:52:38 -0700126
Austin Schuhb4691e92020-12-31 12:37:18 -0800127 // When priority will next be read (cycles).
128 int64_t next_priority_read_cycles;
Austin Schuh36244a12019-09-21 17:52:38 -0700129
130 // Locks held; used during deadlock detection.
131 // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
132 SynchLocksHeld *all_locks;
133};
134
Austin Schuhb4691e92020-12-31 12:37:18 -0800135// The instances of this class are allocated in NewThreadIdentity() with an
136// alignment of PerThreadSynch::kAlignment.
Austin Schuh36244a12019-09-21 17:52:38 -0700137struct ThreadIdentity {
138 // Must be the first member. The Mutex implementation requires that
139 // the PerThreadSynch object associated with each thread is
140 // PerThreadSynch::kAlignment aligned. We provide this alignment on
141 // ThreadIdentity itself.
142 PerThreadSynch per_thread_synch;
143
144 // Private: Reserved for absl::synchronization_internal::Waiter.
145 struct WaiterState {
146 char data[128];
147 } waiter_state;
148
149 // Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
150 std::atomic<int>* blocked_count_ptr;
151
152 // The following variables are mostly read/written just by the
153 // thread itself. The only exception is that these are read by
154 // a ticker thread as a hint.
155 std::atomic<int> ticker; // Tick counter, incremented once per second.
156 std::atomic<int> wait_start; // Ticker value when thread started waiting.
157 std::atomic<bool> is_idle; // Has thread become idle yet?
158
159 ThreadIdentity* next;
160};
161
162// Returns the ThreadIdentity object representing the calling thread; guaranteed
163// to be unique for its lifetime. The returned object will remain valid for the
164// program's lifetime; although it may be re-assigned to a subsequent thread.
165// If one does not exist, return nullptr instead.
166//
167// Does not malloc(*), and is async-signal safe.
168// [*] Technically pthread_setspecific() does malloc on first use; however this
169// is handled internally within tcmalloc's initialization already.
170//
171// New ThreadIdentity objects can be constructed and associated with a thread
172// by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.
173ThreadIdentity* CurrentThreadIdentityIfPresent();
174
175using ThreadIdentityReclaimerFunction = void (*)(void*);
176
177// Sets the current thread identity to the given value. 'reclaimer' is a
178// pointer to the global function for cleaning up instances on thread
179// destruction.
180void SetCurrentThreadIdentity(ThreadIdentity* identity,
181 ThreadIdentityReclaimerFunction reclaimer);
182
183// Removes the currently associated ThreadIdentity from the running thread.
184// This must be called from inside the ThreadIdentityReclaimerFunction, and only
185// from that function.
186void ClearCurrentThreadIdentity();
187
188// May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode
189// index>
190#ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
191#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be direcly set
192#else
193#define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0
194#endif
195
196#ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS
197#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be direcly set
198#else
199#define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1
200#endif
201
202#ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11
203#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be direcly set
204#else
205#define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2
206#endif
207
208#ifdef ABSL_THREAD_IDENTITY_MODE
209#error ABSL_THREAD_IDENTITY_MODE cannot be direcly set
210#elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
211#define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
Austin Schuhb4691e92020-12-31 12:37:18 -0800212#elif defined(_WIN32) && !defined(__MINGW32__)
Austin Schuh36244a12019-09-21 17:52:38 -0700213#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
Austin Schuhb4691e92020-12-31 12:37:18 -0800214#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
215#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
216#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
Austin Schuh36244a12019-09-21 17:52:38 -0700217 (__GOOGLE_GRTE_VERSION__ >= 20140228L)
218// Support for async-safe TLS was specifically added in GRTEv4. It's not
219// present in the upstream eglibc.
220// Note: Current default for production systems.
221#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_TLS
222#else
223#define ABSL_THREAD_IDENTITY_MODE \
224 ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
225#endif
226
227#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
228 ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
229
Austin Schuhb4691e92020-12-31 12:37:18 -0800230#if ABSL_PER_THREAD_TLS
231ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*
232 thread_identity_ptr;
233#elif defined(ABSL_HAVE_THREAD_LOCAL)
234ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
235#else
236#error Thread-local storage not detected on this platform
237#endif
Austin Schuh36244a12019-09-21 17:52:38 -0700238
Austin Schuhb4691e92020-12-31 12:37:18 -0800239// thread_local variables cannot be in headers exposed by DLLs. However, it is
240// important for performance reasons in general that
241// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a
242// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note
243// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
244// this entire inline definition when compiling as a DLL.
245#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL)
Austin Schuh36244a12019-09-21 17:52:38 -0700246inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
247 return thread_identity_ptr;
248}
Austin Schuhb4691e92020-12-31 12:37:18 -0800249#endif
Austin Schuh36244a12019-09-21 17:52:38 -0700250
251#elif ABSL_THREAD_IDENTITY_MODE != \
252 ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
253#error Unknown ABSL_THREAD_IDENTITY_MODE
254#endif
255
256} // namespace base_internal
Austin Schuhb4691e92020-12-31 12:37:18 -0800257ABSL_NAMESPACE_END
Austin Schuh36244a12019-09-21 17:52:38 -0700258} // namespace absl
259
260#endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_