Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/base/internal/thread_identity.h"
00016
00017 #ifndef _WIN32
00018 #include <pthread.h>
00019 #include <signal.h>
00020 #endif
00021
00022 #include <atomic>
00023 #include <cassert>
00024 #include <memory>
00025
00026 #include "absl/base/call_once.h"
00027 #include "absl/base/internal/raw_logging.h"
00028 #include "absl/base/internal/spinlock.h"
00029
00030 namespace absl {
00031 namespace base_internal {
00032
00033 #if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11
00034 namespace {
00035
00036 absl::once_flag init_thread_identity_key_once;
00037 pthread_key_t thread_identity_pthread_key;
00038 std::atomic<bool> pthread_key_initialized(false);
00039
00040 void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) {
00041 pthread_key_create(&thread_identity_pthread_key, reclaimer);
00042 pthread_key_initialized.store(true, std::memory_order_release);
00043 }
00044 }
00045 #endif
00046
00047 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
00048 ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
00049
00050
00051
00052
00053
00054
00055 #ifdef __GNUC__
00056 __attribute__((visibility("protected")))
00057 #endif // __GNUC__
00058 ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr;
00059 #endif // TLS or CPP11
00060
00061 void SetCurrentThreadIdentity(
00062 ThreadIdentity* identity, ThreadIdentityReclaimerFunction reclaimer) {
00063 assert(CurrentThreadIdentityIfPresent() == nullptr);
00064
00065
00066
00067 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
00068
00069 absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
00070 reclaimer);
00071
00072 #ifdef __EMSCRIPTEN__
00073
00074
00075
00076 pthread_setspecific(thread_identity_pthread_key,
00077 reinterpret_cast<void*>(identity));
00078 #else
00079
00080
00081
00082
00083
00084
00085 sigset_t all_signals;
00086 sigset_t curr_signals;
00087 sigfillset(&all_signals);
00088 pthread_sigmask(SIG_SETMASK, &all_signals, &curr_signals);
00089 pthread_setspecific(thread_identity_pthread_key,
00090 reinterpret_cast<void*>(identity));
00091 pthread_sigmask(SIG_SETMASK, &curr_signals, nullptr);
00092 #endif // !__EMSCRIPTEN__
00093
00094 #elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS
00095
00096 absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
00097 reclaimer);
00098 pthread_setspecific(thread_identity_pthread_key,
00099 reinterpret_cast<void*>(identity));
00100 thread_identity_ptr = identity;
00101 #elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
00102 thread_local std::unique_ptr<ThreadIdentity, ThreadIdentityReclaimerFunction>
00103 holder(identity, reclaimer);
00104 thread_identity_ptr = identity;
00105 #else
00106 #error Unimplemented ABSL_THREAD_IDENTITY_MODE
00107 #endif
00108 }
00109
00110 void ClearCurrentThreadIdentity() {
00111 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
00112 ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
00113 thread_identity_ptr = nullptr;
00114 #elif ABSL_THREAD_IDENTITY_MODE == \
00115 ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
00116
00117 assert(CurrentThreadIdentityIfPresent() == nullptr);
00118 #endif
00119 }
00120
00121 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
00122 ThreadIdentity* CurrentThreadIdentityIfPresent() {
00123 bool initialized = pthread_key_initialized.load(std::memory_order_acquire);
00124 if (!initialized) {
00125 return nullptr;
00126 }
00127 return reinterpret_cast<ThreadIdentity*>(
00128 pthread_getspecific(thread_identity_pthread_key));
00129 }
00130 #endif
00131
00132 }
00133 }