diff options
author | Andy Getzendanner <durandal@google.com> | 2023-05-25 11:32:01 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-05-25 11:32:45 -0700 |
commit | 88cc63ef739d83277b492e881be72e9069fcb1fe (patch) | |
tree | 26cf5dbb0e1a6b9fcd46438c2e8644cd641b005b /absl/base/internal | |
parent | c154d20abce2f1ae6bd35bd774313e351493219b (diff) | |
download | abseil-88cc63ef739d83277b492e881be72e9069fcb1fe.tar.gz abseil-88cc63ef739d83277b492e881be72e9069fcb1fe.tar.bz2 abseil-88cc63ef739d83277b492e881be72e9069fcb1fe.zip |
Implement a better GetTID on Apple platforms, and a better fallback too.
The fallback isn't totally portable, even within POSIX, but we can special case any future platforms where it's not just like this change does for Apple.
PiperOrigin-RevId: 535324103
Change-Id: Ib628925c4946b6c112373678fe37e9bb44259090
Diffstat (limited to 'absl/base/internal')
-rw-r--r-- | absl/base/internal/sysinfo.cc | 84 |
1 files changed, 13 insertions, 71 deletions
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index 8429fb90..ed203355 100644 --- a/absl/base/internal/sysinfo.cc +++ b/absl/base/internal/sysinfo.cc @@ -414,82 +414,24 @@ pid_t GetTID() { return tid; } -#else +#elif defined(__APPLE__) -// Fallback implementation of GetTID using pthread_getspecific. -ABSL_CONST_INIT static once_flag tid_once; -ABSL_CONST_INIT static pthread_key_t tid_key; -ABSL_CONST_INIT static absl::base_internal::SpinLock tid_lock( - absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY); - -// We set a bit per thread in this array to indicate that an ID is in -// use. ID 0 is unused because it is the default value returned by -// pthread_getspecific(). -ABSL_CONST_INIT static std::vector<uint32_t> *tid_array - ABSL_GUARDED_BY(tid_lock) = nullptr; -static constexpr int kBitsPerWord = 32; // tid_array is uint32_t. - -// Returns the TID to tid_array. -static void FreeTID(void *v) { - intptr_t tid = reinterpret_cast<intptr_t>(v); - intptr_t word = tid / kBitsPerWord; - uint32_t mask = ~(1u << (tid % kBitsPerWord)); - absl::base_internal::SpinLockHolder lock(&tid_lock); - assert(0 <= word && static_cast<size_t>(word) < tid_array->size()); - (*tid_array)[static_cast<size_t>(word)] &= mask; +pid_t GetTID() { + uint64_t tid; + // `nullptr` here implies this thread. This only fails if the specified + // thread is invalid or the pointer-to-tid is null, so we needn't worry about + // it. + pthread_threadid_np(nullptr, &tid); + return static_cast<pid_t>(tid); } -static void InitGetTID() { - if (pthread_key_create(&tid_key, FreeTID) != 0) { - // The logging system calls GetTID() so it can't be used here. - perror("pthread_key_create failed"); - abort(); - } - - // Initialize tid_array. - absl::base_internal::SpinLockHolder lock(&tid_lock); - tid_array = new std::vector<uint32_t>(1); - (*tid_array)[0] = 1; // ID 0 is never-allocated. -} +#else -// Return a per-thread small integer ID from pthread's thread-specific data. +// Fallback implementation of `GetTID` using `pthread_self`. pid_t GetTID() { - absl::call_once(tid_once, InitGetTID); - - intptr_t tid = reinterpret_cast<intptr_t>(pthread_getspecific(tid_key)); - if (tid != 0) { - return static_cast<pid_t>(tid); - } - - int bit; // tid_array[word] = 1u << bit; - size_t word; - { - // Search for the first unused ID. - absl::base_internal::SpinLockHolder lock(&tid_lock); - // First search for a word in the array that is not all ones. - word = 0; - while (word < tid_array->size() && ~(*tid_array)[word] == 0) { - ++word; - } - if (word == tid_array->size()) { - tid_array->push_back(0); // No space left, add kBitsPerWord more IDs. - } - // Search for a zero bit in the word. - bit = 0; - while (bit < kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) { - ++bit; - } - tid = - static_cast<intptr_t>((word * kBitsPerWord) + static_cast<size_t>(bit)); - (*tid_array)[word] |= 1u << bit; // Mark the TID as allocated. - } - - if (pthread_setspecific(tid_key, reinterpret_cast<void *>(tid)) != 0) { - perror("pthread_setspecific failed"); - abort(); - } - - return static_cast<pid_t>(tid); + // `pthread_t` need not be arithmetic per POSIX; platforms where it isn't + // should be handled above. + return static_cast<pid_t>(pthread_self()); } #endif |