Commit db12b1f4 authored by Ivan Egorov's avatar Ivan Egorov Committed by Facebook GitHub Bot

Use compatibility pthread implementation

Reviewed By: yfeldblum

Differential Revision: D27261361

fbshipit-source-id: a3aa0b40d1a42313fbeeea5c8ca8f6d43dbc6bdf
parent 3a210ac8
......@@ -16,7 +16,7 @@
#pragma once
#ifndef _WIN32
#if !defined(_WIN32) && !defined(__XROS__)
#include <sys/syscall.h>
#if defined(__APPLE__)
......
......@@ -23,6 +23,10 @@
#include <folly/portability/Unistd.h>
#include <folly/portability/Windows.h>
#ifdef __XROS__
#include <xr/execution/accessors.h> // @manual
#endif
namespace folly {
/**
......@@ -44,6 +48,8 @@ inline uint64_t getCurrentThreadID() {
return uint64_t(pthread_mach_thread_np(pthread_self()));
#elif defined(_WIN32)
return uint64_t(GetCurrentThreadId());
#elif defined(__XROS__)
return uint64_t(xr_execution_get_id());
#else
return uint64_t(pthread_self());
#endif
......@@ -88,6 +94,8 @@ inline uint64_t getOSThreadID() {
long tid;
thr_self(&tid);
return uint64_t(tid);
#elif defined(__XROS__)
return uint64_t(xr_execution_get_id());
#else
return uint64_t(syscall(FOLLY_SYS_gettid));
#endif
......
......@@ -37,7 +37,13 @@
// This looks a bit weird, but it's necessary to avoid
// having an undefined compiler function called.
#if defined(__GLIBC__) && !defined(__APPLE__) && !defined(__ANDROID__)
#if defined(__XROS__)
#if FOLLY_HAVE_PTHREAD
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 1
#else
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 0
#endif
#elif defined(__GLIBC__) && !defined(__APPLE__) && !defined(__ANDROID__)
#if __GLIBC_PREREQ(2, 12)
// has pthread_setname_np(pthread_t, const char*) (2 params)
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 1
......@@ -71,7 +77,7 @@ namespace folly {
namespace {
#if FOLLY_HAVE_PTHREAD && !defined(_WIN32)
#if FOLLY_HAVE_PTHREAD && !defined(_WIN32) && !defined(__XROS__)
pthread_t stdTidToPthreadId(std::thread::id tid) {
static_assert(
std::is_same<pthread_t, std::thread::native_handle_type>::value,
......@@ -102,7 +108,8 @@ bool canSetCurrentThreadName() {
}
bool canSetOtherThreadName() {
#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || defined(_WIN32)
#if (FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME && !defined(__XROS__)) || \
defined(_WIN32)
return true;
#else
return false;
......@@ -111,17 +118,30 @@ bool canSetOtherThreadName() {
static constexpr size_t kMaxThreadNameLength = 16;
Optional<std::string> getThreadName(std::thread::id id) {
static Optional<std::string> getPThreadName(pthread_t pid) {
#if ( \
FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
FOLLY_HAS_PTHREAD_SETNAME_NP_NAME) && \
!defined(__ANDROID__)
// Android NDK does not yet support pthread_getname_np.
std::array<char, kMaxThreadNameLength> buf;
if (id != std::thread::id() &&
pthread_getname_np(stdTidToPthreadId(id), buf.data(), buf.size()) == 0) {
if (pthread_getname_np(pid, buf.data(), buf.size()) == 0) {
return std::string(buf.data());
}
#endif
(void)pid;
return none;
}
Optional<std::string> getThreadName(std::thread::id id) {
#if ( \
FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
FOLLY_HAS_PTHREAD_SETNAME_NP_NAME) && \
!defined(__ANDROID__) && !defined(__XROS__)
// Android NDK does not yet support pthread_getname_np.
if (id != std::thread::id()) {
return getPThreadName(stdTidToPthreadId(id));
}
#elif FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME
std::array<char, kMaxThreadNameLength> buf;
if (id == std::this_thread::get_id() &&
......@@ -134,7 +154,11 @@ Optional<std::string> getThreadName(std::thread::id id) {
} // namespace folly
Optional<std::string> getCurrentThreadName() {
#if FOLLY_HAVE_PTHREAD
return getPThreadName(pthread_self());
#else
return getThreadName(std::this_thread::get_id());
#endif
}
bool setThreadName(std::thread::id tid, StringPiece name) {
......@@ -180,64 +204,58 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
}
return true;
}();
#elif defined(__XROS__)
return std::this_thread::get_id() == tid &&
setThreadName(pthread_self(), name);
#else
return setThreadName(stdTidToPthreadId(tid), name);
#endif
}
bool setThreadName(pthread_t pid, StringPiece name) {
#ifdef _WIN32
static_assert(
sizeof(unsigned int) == sizeof(std::thread::id),
"This assumes std::thread::id is a thin wrapper around "
"the thread id as an unsigned int, but that doesn't appear to be true.");
// std::thread::id is a thin wrapper around an integral thread id,
// so just stick the ID in.
unsigned int tid = pthread_getw32threadid_np(pid);
std::thread::id id;
std::memcpy(&id, &tid, sizeof(id));
return setThreadName(id, name);
#else
name = name.subpiece(0, kMaxThreadNameLength - 1);
char buf[kMaxThreadNameLength] = {};
std::memcpy(buf, name.data(), name.size());
auto id = stdTidToPthreadId(tid);
#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
return 0 == pthread_setname_np(id, buf);
return 0 == pthread_setname_np(pid, buf);
#elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
// Since macOS 10.6 and iOS 3.2 it is possible for a thread
// to set its own name using pthread, but
// not that of some other thread.
if (pthread_equal(pthread_self(), id)) {
if (pthread_equal(pthread_self(), pid)) {
return 0 == pthread_setname_np(buf);
}
#elif FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME
// for Android prctl is used instead of pthread_setname_np
// if Android NDK version is older than API level 9.
if (pthread_equal(pthread_self(), id)) {
if (pthread_equal(pthread_self(), pid)) {
return 0 == prctl(PR_SET_NAME, buf, 0L, 0L, 0L);
}
#endif
(void)id;
(void)pid;
return false;
#endif
}
bool setThreadName(pthread_t pid, StringPiece name) {
#ifdef _WIN32
static_assert(
sizeof(unsigned int) == sizeof(std::thread::id),
"This assumes std::thread::id is a thin wrapper around "
"the thread id as an unsigned int, but that doesn't appear to be true.");
// std::thread::id is a thin wrapper around an integral thread id,
// so just stick the ID in.
unsigned int tid = pthread_getw32threadid_np(pid);
std::thread::id id;
std::memcpy(&id, &tid, sizeof(id));
return setThreadName(id, name);
#else
static_assert(
std::is_same<pthread_t, std::thread::native_handle_type>::value,
"This assumes that the native handle type is pthread_t");
static_assert(
sizeof(std::thread::native_handle_type) == sizeof(std::thread::id),
"This assumes std::thread::id is a thin wrapper around "
"std::thread::native_handle_type, but that doesn't appear to be true.");
// In most implementations, std::thread::id is a thin wrapper around
// std::thread::native_handle_type, which means we can do unsafe things to
// extract it.
std::thread::id id;
std::memcpy(static_cast<void*>(&id), &pid, sizeof(id));
return setThreadName(id, name);
#endif
}
bool setThreadName(StringPiece name) {
#if FOLLY_HAVE_PTHREAD
return setThreadName(pthread_self(), name);
#else
return setThreadName(std::this_thread::get_id(), name);
#endif
}
} // namespace folly
......@@ -56,8 +56,16 @@ TEST(ThreadName, setThreadName_other_pthread) {
SCOPE_EXIT { th.join(); };
handle_set.wait();
SCOPE_EXIT { let_thread_end.post(); };
#ifndef __XROS__
EXPECT_EQ(
expectedSetOtherThreadNameResult, setThreadName(handle, kThreadName));
#else
// XROS portability pthread implementation supports setting other pthread
// name. However setting name of another `std::thread` is not supported, hence
// `canSetOtherThreadName()` is more pessimistic than `setThreadName()`.
EXPECT_FALSE(expectedSetOtherThreadNameResult);
EXPECT_TRUE(setThreadName(handle, kThreadName));
#endif
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment