|
|
|
@ -18,19 +18,20 @@ |
|
|
|
|
|
|
|
|
|
#include <grpc/support/port_platform.h> |
|
|
|
|
|
|
|
|
|
#ifdef GPR_CPU_POSIX |
|
|
|
|
#if defined(GPR_CPU_POSIX) |
|
|
|
|
|
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <pthread.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
#include <atomic> |
|
|
|
|
|
|
|
|
|
#include <grpc/support/cpu.h> |
|
|
|
|
#include <grpc/support/log.h> |
|
|
|
|
#include <grpc/support/sync.h> |
|
|
|
|
#include <grpc/support/useful.h> |
|
|
|
|
|
|
|
|
|
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<unsigned int *>(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<unsigned int> thread_counter(0); |
|
|
|
|
|
|
|
|
|
unsigned int *thread_id = |
|
|
|
|
static_cast<unsigned int *>(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 */ |
|
|
|
|