Commit 03358af9 authored by Micky Kelager's avatar Micky Kelager Committed by Facebook Github Bot

Support get/set thread name on Android

Summary:
This will add support to set and get thread name for Android.

`pthread_setname_np` was introduced back in NDK API level 9: https://stackoverflow.com/questions/15241869/pthread-error-in-ndk-build?fbclid=IwAR0yvyaC4KNA6D1GlgIofQSFIuZAgL7qDR5L6m5tkY6lv-R6uTvzreAiFp4

Backwards support added for setting current thread name using `prctl(PR_SET_NAME)`, when `pthread_setname_np` is not available (for `__ANDROID_API__ < 9`).

Currently, Android NDK does not support `pthread_getname_np` so `prctl(PR_GET_NAME)` is used for this.

Reviewed By: yfeldblum

Differential Revision: D17815151

fbshipit-source-id: 474caee070fad26f3e6b118307058d5506f0467b
parent e9cab5a6
...@@ -23,6 +23,18 @@ ...@@ -23,6 +23,18 @@
#include <folly/portability/PThread.h> #include <folly/portability/PThread.h>
#include <folly/portability/Windows.h> #include <folly/portability/Windows.h>
// Android only, prctl is only used when pthread_setname_np
// and pthread_getname_np are not avilable.
#if __linux__
#define FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME 1
#else
#define FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME 0
#endif
#if FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME
#include <sys/prctl.h>
#endif
// 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(__GLIBC__) && !defined(__APPLE__) && !defined(__ANDROID__)
...@@ -32,6 +44,9 @@ ...@@ -32,6 +44,9 @@
#else #else
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 0 #define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 0
#endif #endif
// pthread_setname_np was introduced in Android NDK version 9
#elif defined(__ANDROID__) && __ANDROID_API__ >= 9
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 1
#else #else
#define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 0 #define FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME 0
#endif #endif
...@@ -77,8 +92,9 @@ pthread_t stdTidToPthreadId(std::thread::id tid) { ...@@ -77,8 +92,9 @@ pthread_t stdTidToPthreadId(std::thread::id tid) {
} // namespace } // namespace
bool canSetCurrentThreadName() { bool canSetCurrentThreadName() {
#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \ #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \
FOLLY_HAS_PTHREAD_SETNAME_NP_NAME || defined(_WIN32) FOLLY_HAS_PTHREAD_SETNAME_NP_NAME || FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME || \
defined(_WIN32)
return true; return true;
#else #else
return false; return false;
...@@ -96,20 +112,26 @@ bool canSetOtherThreadName() { ...@@ -96,20 +112,26 @@ bool canSetOtherThreadName() {
static constexpr size_t kMaxThreadNameLength = 16; static constexpr size_t kMaxThreadNameLength = 16;
Optional<std::string> getThreadName(std::thread::id id) { Optional<std::string> getThreadName(std::thread::id id) {
#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME || \ #if ( \
FOLLY_HAS_PTHREAD_SETNAME_NP_NAME 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; std::array<char, kMaxThreadNameLength> buf;
if (id == std::thread::id() || if (id != std::thread::id() &&
pthread_getname_np(stdTidToPthreadId(id), buf.data(), buf.size()) != 0) { pthread_getname_np(stdTidToPthreadId(id), buf.data(), buf.size()) == 0) {
return Optional<std::string>(); return std::string(buf.data());
}
#elif FOLLY_DETAIL_HAS_PRCTL_PR_SET_NAME
std::array<char, kMaxThreadNameLength> buf;
if (id == std::this_thread::get_id() &&
prctl(PR_GET_NAME, buf.data(), 0L, 0L, 0L) == 0) {
return std::string(buf.data());
} }
return folly::make_optional(std::string(buf.data()));
#else
// There's not actually a way to get the thread name on Windows because
// thread names are a concept managed by the debugger, not the runtime.
return Optional<std::string>();
#endif #endif
} (void)id;
return none;
} // namespace folly
Optional<std::string> getCurrentThreadName() { Optional<std::string> getCurrentThreadName() {
return getThreadName(std::this_thread::get_id()); return getThreadName(std::this_thread::get_id());
...@@ -165,12 +187,18 @@ bool setThreadName(std::thread::id tid, StringPiece name) { ...@@ -165,12 +187,18 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
#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(id, 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 to set its own // Since macOS 10.6 and iOS 3.2 it is possible for a thread
// name, but not that of some other 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(), id)) {
return 0 == pthread_setname_np(buf); return 0 == pthread_setname_np(buf);
} }
return false; #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)) {
return 0 == prctl(PR_SET_NAME, buf, 0L, 0L, 0L);
}
#else #else
(void)id; (void)id;
return false; return false;
......
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