diff --git a/src/core/lib/support/cpu_posix.cc b/src/core/lib/support/cpu_posix.cc index 503a96b4c8a..c32ca4659c7 100644 --- a/src/core/lib/support/cpu_posix.cc +++ b/src/core/lib/support/cpu_posix.cc @@ -18,19 +18,20 @@ #include -#ifdef GPR_CPU_POSIX +#if defined(GPR_CPU_POSIX) #include +#include #include #include +#include + #include #include #include #include -static __thread char magic_thread_local; - static long ncpus = 0; static void init_ncpus() { @@ -52,7 +53,27 @@ unsigned gpr_cpu_current_cpu(void) { most code that's using this is using it to shard across work queues though, so here we use thread identity instead to achieve a similar though not identical effect */ - return (unsigned)GPR_HASH_POINTER(&magic_thread_local, gpr_cpu_num_cores()); + static auto DeleteValue = [](void *value_ptr) { + unsigned int *value = static_cast(value_ptr); + if (value) { + delete value; + } + }; + static pthread_key_t thread_id_key; + static int thread_id_key_create_result __attribute__((unused)) = + pthread_key_create(&thread_id_key, DeleteValue); + // pthread_t isn't portably defined to map to an integral type. So keep track + // of thread identity explicitly so hashing works reliably. + static std::atomic thread_counter(0); + + unsigned int *thread_id = + static_cast(pthread_getspecific(thread_id_key)); + if (thread_id == nullptr) { + thread_id = new unsigned int(thread_counter++); + pthread_setspecific(thread_id_key, thread_id); + } + + return (unsigned)GPR_HASH_POINTER(*thread_id, gpr_cpu_num_cores()); } #endif /* GPR_CPU_POSIX */