diff --git a/src/xenia/base/platform_android.cc b/src/xenia/base/platform_android.cc index 177eb8dfe..f2c807856 100644 --- a/src/xenia/base/platform_android.cc +++ b/src/xenia/base/platform_android.cc @@ -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( \ - 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 } diff --git a/src/xenia/base/platform_android.h b/src/xenia/base/platform_android.h index 1aa549aca..711084578 100644 --- a/src/xenia/base/platform_android.h +++ b/src/xenia/base/platform_android.h @@ -15,6 +15,7 @@ // avoided! #include +#include #include #include @@ -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(); diff --git a/src/xenia/base/platform_posix.h b/src/xenia/base/platform_posix.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/xenia/base/threading.h b/src/xenia/base/threading.h index 776a158e0..36665d7a4 100644 --- a/src/xenia/base/threading.h +++ b/src/xenia/base/threading.h @@ -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(); diff --git a/src/xenia/base/threading_linux.cc b/src/xenia/base/threading_linux.cc deleted file mode 100644 index 3535f3011..000000000 --- a/src/xenia/base/threading_linux.cc +++ /dev/null @@ -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 -#include - -namespace xe { -namespace threading {} // namespace threading -} // namespace xe diff --git a/src/xenia/base/threading_mac.cc b/src/xenia/base/threading_mac.cc index 2ea681817..108354b93 100644 --- a/src/xenia/base/threading_mac.cc +++ b/src/xenia/base/threading_mac.cc @@ -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) { diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 78f08ed04..436e81cfb 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -21,11 +21,15 @@ #include #include #include +#include #include #include #if XE_PLATFORM_ANDROID #include + +#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(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 : 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 : 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 : public PosixConditionBase { auto result = std::array{'\0'}; std::unique_lock 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 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 : public PosixConditionBase { WaitStarted(); std::unique_lock lock(state_mutex_); if (state_ != State::kUninitialized && state_ != State::kFinished) { - threading::set_name(static_cast(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 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(thread_); } uint64_t affinity_mask() { @@ -647,8 +681,13 @@ class PosixCondition : 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 : public PosixConditionBase { mutable std::mutex callback_mutex_; mutable std::condition_variable state_signal_; std::function 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& 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: { diff --git a/src/xenia/base/threading_win.cc b/src/xenia/base/threading_win.cc index 6b4e31a99..e91cdf1ce 100644 --- a/src/xenia/base/threading_win.cc +++ b/src/xenia/base/threading_win.cc @@ -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 =