[Threading] Android thread naming and other cleanup
This commit is contained in:
parent
aca23c08cf
commit
63ff758049
|
@ -35,16 +35,20 @@ void Initialize(const ANativeActivity* activity) {
|
|||
AConfiguration_delete(configuration);
|
||||
|
||||
if (api_level_ >= 26) {
|
||||
// Leaked intentionally, already loaded into the address space.
|
||||
// Leaked intentionally as these will be usable anywhere, already loaded
|
||||
// into the address space as the application is linked against them.
|
||||
// https://chromium.googlesource.com/chromium/src/+/master/third_party/ashmem/ashmem-dev.c#201
|
||||
void* libandroid = dlopen("libandroid.so", RTLD_NOW);
|
||||
assert_not_null(libandroid);
|
||||
#define XE_PLATFORM_ANDROID_LOAD_API_FUNCTION(name, api) \
|
||||
void* libc = dlopen("libc.so", RTLD_NOW);
|
||||
assert_not_null(libc);
|
||||
#define XE_PLATFORM_ANDROID_LOAD_API_FUNCTION(lib, name, api) \
|
||||
api_functions_.api_##api.name = \
|
||||
reinterpret_cast<decltype(api_functions_.api_##api.name)>( \
|
||||
dlsym(libandroid, #name)); \
|
||||
dlsym(lib, #name)); \
|
||||
assert_not_null(api_functions_.api_##api.name);
|
||||
XE_PLATFORM_ANDROID_LOAD_API_FUNCTION(ASharedMemory_create, 26);
|
||||
XE_PLATFORM_ANDROID_LOAD_API_FUNCTION(libandroid, ASharedMemory_create, 26);
|
||||
XE_PLATFORM_ANDROID_LOAD_API_FUNCTION(libc, pthread_getname_np, 26);
|
||||
#undef XE_PLATFORM_ANDROID_LOAD_API_FUNCTION
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// avoided!
|
||||
|
||||
#include <android/native_activity.h>
|
||||
#include <pthread.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -32,7 +33,10 @@ int32_t api_level();
|
|||
// Android API functions added after the minimum supported API version.
|
||||
struct ApiFunctions {
|
||||
struct {
|
||||
// libandroid
|
||||
int (*ASharedMemory_create)(const char* name, size_t size);
|
||||
// libc
|
||||
int (*pthread_getname_np)(pthread_t pthread, char* buf, size_t n);
|
||||
} api_26;
|
||||
};
|
||||
const ApiFunctions& api_functions();
|
||||
|
|
|
@ -95,9 +95,6 @@ void set_current_thread_id(uint32_t id);
|
|||
|
||||
// Sets the current thread name.
|
||||
void set_name(const std::string_view name);
|
||||
// Sets the target thread name.
|
||||
void set_name(std::thread::native_handle_type handle,
|
||||
const std::string_view name);
|
||||
|
||||
// Yields the current thread to the scheduler. Maybe.
|
||||
void MaybeYield();
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/threading.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace xe {
|
||||
namespace threading {} // namespace threading
|
||||
} // namespace xe
|
|
@ -26,10 +26,6 @@ uint32_t current_thread_id() {
|
|||
|
||||
void set_name(const std::string& name) { pthread_setname_np(name.c_str()); }
|
||||
|
||||
void set_name(std::thread::native_handle_type handle, const std::string& name) {
|
||||
// ?
|
||||
}
|
||||
|
||||
void MaybeYield() { pthread_yield_np(); }
|
||||
|
||||
void Sleep(std::chrono::microseconds duration) {
|
||||
|
|
|
@ -21,11 +21,15 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
|
||||
#if XE_PLATFORM_ANDROID
|
||||
#include <sched.h>
|
||||
|
||||
#include "xenia/base/platform_android.h"
|
||||
#include "xenia/base/string_util.h"
|
||||
#endif
|
||||
|
||||
namespace xe {
|
||||
|
@ -92,13 +96,6 @@ uint32_t current_thread_system_id() {
|
|||
return static_cast<uint32_t>(syscall(SYS_gettid));
|
||||
}
|
||||
|
||||
void set_name(std::thread::native_handle_type handle,
|
||||
const std::string_view name) {
|
||||
pthread_setname_np(handle, std::string(name).c_str());
|
||||
}
|
||||
|
||||
void set_name(const std::string_view name) { set_name(pthread_self(), name); }
|
||||
|
||||
void MaybeYield() {
|
||||
#if XE_PLATFORM_ANDROID
|
||||
sched_yield();
|
||||
|
@ -498,7 +495,11 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
signaled_(false),
|
||||
exit_code_(0),
|
||||
state_(State::kUninitialized),
|
||||
suspend_count_(0) {}
|
||||
suspend_count_(0) {
|
||||
#if XE_PLATFORM_ANDROID
|
||||
android_pre_api_26_name_[0] = '\0';
|
||||
#endif
|
||||
}
|
||||
bool Initialize(Thread::CreationParameters params,
|
||||
ThreadStartData* start_data) {
|
||||
start_data->create_suspended = params.create_suspended;
|
||||
|
@ -534,7 +535,11 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
: thread_(thread),
|
||||
signaled_(false),
|
||||
exit_code_(0),
|
||||
state_(State::kRunning) {}
|
||||
state_(State::kRunning) {
|
||||
#if XE_PLATFORM_ANDROID
|
||||
android_pre_api_26_name_[0] = '\0';
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~PosixCondition() {
|
||||
if (thread_ && !signaled_) {
|
||||
|
@ -561,8 +566,24 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
auto result = std::array<char, 17>{'\0'};
|
||||
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||
if (state_ != State::kUninitialized && state_ != State::kFinished) {
|
||||
if (pthread_getname_np(thread_, result.data(), result.size() - 1) != 0)
|
||||
#if XE_PLATFORM_ANDROID
|
||||
// pthread_getname_np was added in API 26 - below that, store the name in
|
||||
// this object, which may be only modified through Xenia threading, but
|
||||
// should be enough in most cases.
|
||||
if (xe::platform::android::api_level() >= 26) {
|
||||
if (xe::platform::android::api_functions().api_26.pthread_getname_np(
|
||||
thread_, result.data(), result.size() - 1) != 0) {
|
||||
assert_always();
|
||||
}
|
||||
} else {
|
||||
std::lock_guard<std::mutex> lock(android_pre_api_26_name_mutex_);
|
||||
std::strcpy(result.data(), android_pre_api_26_name_);
|
||||
}
|
||||
#else
|
||||
if (pthread_getname_np(thread_, result.data(), result.size() - 1) != 0) {
|
||||
assert_always();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return std::string(result.data());
|
||||
}
|
||||
|
@ -571,11 +592,24 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
WaitStarted();
|
||||
std::unique_lock<std::mutex> lock(state_mutex_);
|
||||
if (state_ != State::kUninitialized && state_ != State::kFinished) {
|
||||
threading::set_name(static_cast<std::thread::native_handle_type>(thread_),
|
||||
name);
|
||||
pthread_setname_np(thread_, std::string(name).c_str());
|
||||
#if XE_PLATFORM_ANDROID
|
||||
SetAndroidPreApi26Name(name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if XE_PLATFORM_ANDROID
|
||||
void SetAndroidPreApi26Name(const std::string_view name) {
|
||||
if (xe::platform::android::api_level() >= 26) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(android_pre_api_26_name_mutex_);
|
||||
xe::string_util::copy_truncating(android_pre_api_26_name_, name,
|
||||
xe::countof(android_pre_api_26_name_));
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t system_id() const { return static_cast<uint32_t>(thread_); }
|
||||
|
||||
uint64_t affinity_mask() {
|
||||
|
@ -647,8 +681,13 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
user_callback_ = std::move(callback);
|
||||
sigval value{};
|
||||
value.sival_ptr = this;
|
||||
#if XE_PLATFORM_ANDROID
|
||||
sigqueue(pthread_gettid_np(thread_),
|
||||
GetSystemSignal(SignalType::kThreadUserCallback), value);
|
||||
#else
|
||||
pthread_sigqueue(thread_, GetSystemSignal(SignalType::kThreadUserCallback),
|
||||
value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CallUserCallback() {
|
||||
|
@ -751,6 +790,12 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
mutable std::mutex callback_mutex_;
|
||||
mutable std::condition_variable state_signal_;
|
||||
std::function<void()> user_callback_;
|
||||
#if XE_PLATFORM_ANDROID
|
||||
// Name accessible via name() on Android before API 26 which added
|
||||
// pthread_getname_np.
|
||||
mutable std::mutex android_pre_api_26_name_mutex_;
|
||||
char android_pre_api_26_name_[16];
|
||||
#endif
|
||||
};
|
||||
|
||||
class PosixWaitHandle {
|
||||
|
@ -770,7 +815,7 @@ class PosixConditionHandle : public T, public PosixWaitHandle {
|
|||
PosixConditionHandle(uint32_t initial_count, uint32_t maximum_count);
|
||||
~PosixConditionHandle() override = default;
|
||||
|
||||
PosixConditionBase& condition() override { return handle_; }
|
||||
PosixCondition<T>& condition() override { return handle_; }
|
||||
void* native_handle() const override { return handle_.native_handle(); }
|
||||
|
||||
protected:
|
||||
|
@ -1079,6 +1124,15 @@ void Thread::Exit(int exit_code) {
|
|||
}
|
||||
}
|
||||
|
||||
void set_name(const std::string_view name) {
|
||||
pthread_setname_np(pthread_self(), std::string(name).c_str());
|
||||
#if XE_PLATFORM_ANDROID
|
||||
if (xe::platform::android::api_level() < 26 && current_thread_) {
|
||||
current_thread_->condition().SetAndroidPreApi26Name(name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void signal_handler(int signal, siginfo_t* info, void* /*context*/) {
|
||||
switch (GetSystemSignalType(signal)) {
|
||||
case SignalType::kHighResolutionTimer: {
|
||||
|
|
|
@ -57,7 +57,7 @@ void raise_thread_name_exception(HANDLE thread, const std::string& name) {
|
|||
}
|
||||
}
|
||||
|
||||
void set_name(HANDLE thread, const std::string_view name) {
|
||||
static void set_name(HANDLE thread, const std::string_view name) {
|
||||
auto kernel = GetModuleHandleW(L"kernel32.dll");
|
||||
if (kernel) {
|
||||
auto func =
|
||||
|
|
Loading…
Reference in New Issue