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 @@ ...@@ -16,7 +16,7 @@
#pragma once #pragma once
#ifndef _WIN32 #if !defined(_WIN32) && !defined(__XROS__)
#include <sys/syscall.h> #include <sys/syscall.h>
#if defined(__APPLE__) #if defined(__APPLE__)
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#include <folly/portability/Windows.h> #include <folly/portability/Windows.h>
#ifdef __XROS__
#include <xr/execution/accessors.h> // @manual
#endif
namespace folly { namespace folly {
/** /**
...@@ -44,6 +48,8 @@ inline uint64_t getCurrentThreadID() { ...@@ -44,6 +48,8 @@ inline uint64_t getCurrentThreadID() {
return uint64_t(pthread_mach_thread_np(pthread_self())); return uint64_t(pthread_mach_thread_np(pthread_self()));
#elif defined(_WIN32) #elif defined(_WIN32)
return uint64_t(GetCurrentThreadId()); return uint64_t(GetCurrentThreadId());
#elif defined(__XROS__)
return uint64_t(xr_execution_get_id());
#else #else
return uint64_t(pthread_self()); return uint64_t(pthread_self());
#endif #endif
...@@ -88,6 +94,8 @@ inline uint64_t getOSThreadID() { ...@@ -88,6 +94,8 @@ inline uint64_t getOSThreadID() {
long tid; long tid;
thr_self(&tid); thr_self(&tid);
return uint64_t(tid); return uint64_t(tid);
#elif defined(__XROS__)
return uint64_t(xr_execution_get_id());
#else #else
return uint64_t(syscall(FOLLY_SYS_gettid)); return uint64_t(syscall(FOLLY_SYS_gettid));
#endif #endif
......
...@@ -37,7 +37,13 @@ ...@@ -37,7 +37,13 @@
// This looks a bit weird, but it's necessary to avoid // This looks a bit weird, but it's necessary to avoid
// having an undefined compiler function called. // 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) #if __GLIBC_PREREQ(2, 12)
// has pthread_setname_np(pthread_t, const char*) (2 params) // has pthread_setname_np(pthread_t, const char*) (2 params)
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 1 #define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 1
...@@ -71,7 +77,7 @@ namespace folly { ...@@ -71,7 +77,7 @@ namespace folly {
namespace { namespace {
#if FOLLY_HAVE_PTHREAD && !defined(_WIN32) #if FOLLY_HAVE_PTHREAD && !defined(_WIN32) && !defined(__XROS__)
pthread_t stdTidToPthreadId(std::thread::id tid) { pthread_t stdTidToPthreadId(std::thread::id tid) {
static_assert( static_assert(
std::is_same<pthread_t, std::thread::native_handle_type>::value, std::is_same<pthread_t, std::thread::native_handle_type>::value,
...@@ -102,7 +108,8 @@ bool canSetCurrentThreadName() { ...@@ -102,7 +108,8 @@ bool canSetCurrentThreadName() {
} }
bool canSetOtherThreadName() { 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; return true;
#else #else
return false; return false;
...@@ -111,17 +118,30 @@ bool canSetOtherThreadName() { ...@@ -111,17 +118,30 @@ bool canSetOtherThreadName() {
static constexpr size_t kMaxThreadNameLength = 16; static constexpr size_t kMaxThreadNameLength = 16;
Optional<std::string> getThreadName(std::thread::id id) { static Optional<std::string> getPThreadName(pthread_t pid) {
#if ( \ #if ( \
FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \ FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
FOLLY_HAS_PTHREAD_SETNAME_NP_NAME) && \ FOLLY_HAS_PTHREAD_SETNAME_NP_NAME) && \
!defined(__ANDROID__) !defined(__ANDROID__)
// Android NDK does not yet support pthread_getname_np. // Android NDK does not yet support pthread_getname_np.
std::array<char, kMaxThreadNameLength> buf; std::array<char, kMaxThreadNameLength> buf;
if (id != std::thread::id() && if (pthread_getname_np(pid, buf.data(), buf.size()) == 0) {
pthread_getname_np(stdTidToPthreadId(id), buf.data(), buf.size()) == 0) {
return std::string(buf.data()); 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 #elif FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME
std::array<char, kMaxThreadNameLength> buf; std::array<char, kMaxThreadNameLength> buf;
if (id == std::this_thread::get_id() && if (id == std::this_thread::get_id() &&
...@@ -134,7 +154,11 @@ Optional<std::string> getThreadName(std::thread::id id) { ...@@ -134,7 +154,11 @@ Optional<std::string> getThreadName(std::thread::id id) {
} // namespace folly } // namespace folly
Optional<std::string> getCurrentThreadName() { Optional<std::string> getCurrentThreadName() {
#if FOLLY_HAVE_PTHREAD
return getPThreadName(pthread_self());
#else
return getThreadName(std::this_thread::get_id()); return getThreadName(std::this_thread::get_id());
#endif
} }
bool setThreadName(std::thread::id tid, StringPiece name) { bool setThreadName(std::thread::id tid, StringPiece name) {
...@@ -180,64 +204,58 @@ bool setThreadName(std::thread::id tid, StringPiece name) { ...@@ -180,64 +204,58 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
} }
return true; 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 #else
name = name.subpiece(0, kMaxThreadNameLength - 1); name = name.subpiece(0, kMaxThreadNameLength - 1);
char buf[kMaxThreadNameLength] = {}; char buf[kMaxThreadNameLength] = {};
std::memcpy(buf, name.data(), name.size()); std::memcpy(buf, name.data(), name.size());
auto id = stdTidToPthreadId(tid);
#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME #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 #elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
// Since macOS 10.6 and iOS 3.2 it is possible for a thread // Since macOS 10.6 and iOS 3.2 it is possible for a thread
// to set its own name using pthread, but // to set its own name using pthread, but
// not that of some other thread. // not that of some other thread.
if (pthread_equal(pthread_self(), id)) { if (pthread_equal(pthread_self(), pid)) {
return 0 == pthread_setname_np(buf); return 0 == pthread_setname_np(buf);
} }
#elif FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME #elif FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME
// for Android prctl is used instead of pthread_setname_np // for Android prctl is used instead of pthread_setname_np
// if Android NDK version is older than API level 9. // 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); return 0 == prctl(PR_SET_NAME, buf, 0L, 0L, 0L);
} }
#endif #endif
(void)id; (void)pid;
return false; return false;
#endif #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) { bool setThreadName(StringPiece name) {
#if FOLLY_HAVE_PTHREAD
return setThreadName(pthread_self(), name);
#else
return setThreadName(std::this_thread::get_id(), name); return setThreadName(std::this_thread::get_id(), name);
#endif
} }
} // namespace folly } // namespace folly
...@@ -56,8 +56,16 @@ TEST(ThreadName, setThreadName_other_pthread) { ...@@ -56,8 +56,16 @@ TEST(ThreadName, setThreadName_other_pthread) {
SCOPE_EXIT { th.join(); }; SCOPE_EXIT { th.join(); };
handle_set.wait(); handle_set.wait();
SCOPE_EXIT { let_thread_end.post(); }; SCOPE_EXIT { let_thread_end.post(); };
#ifndef __XROS__
EXPECT_EQ( EXPECT_EQ(
expectedSetOtherThreadNameResult, setThreadName(handle, kThreadName)); 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 #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