Try to get a bit better at detaching threads that have used JNI from the VM.

This commit is contained in:
Henrik Rydgård
2023-01-03 19:01:51 +01:00
parent a73ccd77e3
commit 916404f0e4
8 changed files with 71 additions and 7 deletions
+7 -4
View File
@@ -44,6 +44,7 @@ struct ThreadContext {
std::atomic<bool> cancelled;
std::atomic<Task *> private_single;
std::deque<Task *> private_queue;
char name[16];
};
ThreadManager::ThreadManager() : global_(new GlobalThreadContext()) {
@@ -124,14 +125,13 @@ bool ThreadManager::TeardownTask(Task *task, bool enqueue) {
}
static void WorkerThreadFunc(GlobalThreadContext *global, ThreadContext *thread) {
char threadName[16];
if (thread->type == TaskType::CPU_COMPUTE) {
snprintf(threadName, sizeof(threadName), "PoolWorker %d", thread->index);
snprintf(thread->name, sizeof(thread->name), "PoolWorker %d", thread->index);
} else {
_assert_(thread->type == TaskType::IO_BLOCKING);
snprintf(threadName, sizeof(threadName), "PoolWorkerIO %d", thread->index);
snprintf(thread->name, sizeof(thread->name), "PoolWorkerIO %d", thread->index);
}
SetCurrentThreadName(threadName);
SetCurrentThreadName(thread->name);
const bool isCompute = thread->type == TaskType::CPU_COMPUTE;
const auto global_queue_size = [isCompute, &global]() -> int {
@@ -185,6 +185,9 @@ static void WorkerThreadFunc(GlobalThreadContext *global, ThreadContext *thread)
thread->queue_size--;
}
}
// In case it got attached to JNI, detach it. Don't think this has any side effects if called redundantly.
DetachThreadFromJNI();
}
void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) {
+21 -1
View File
@@ -12,10 +12,15 @@
#elif defined(__ANDROID__)
#include "android/jni/app-android.h"
#define TLS_SUPPORTED
#endif
// TODO: Many other platforms also support TLS, in fact probably nearly all that we support
// these days.
#include <cstring>
#include <cstdint>
@@ -62,6 +67,13 @@ static EXCEPTION_DISPOSITION NTAPI ignore_handler(EXCEPTION_RECORD *rec,
}
#endif
void DetachThreadFromJNI() {
#if PPSSPP_PLATFORM(ANDROID)
Android_DetachThreadFromJNI();
#else
// Do nothing
#endif
}
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
typedef HRESULT (WINAPI *TSetThreadDescription)(HANDLE, PCWSTR);
@@ -90,7 +102,15 @@ static void InitializeSetThreadDescription() {
void SetCurrentThreadNameThroughException(const char *threadName);
#endif
void SetCurrentThreadName(const char* threadName) {
const char *GetCurrentThreadName() {
#ifdef TLS_SUPPORTED
return curThreadName;
#else
return "";
#endif
}
void SetCurrentThreadName(const char *threadName) {
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
InitializeSetThreadDescription();
if (g_pSetThreadDescription) {
+16 -1
View File
@@ -2,11 +2,26 @@
#include <mutex>
// Note that name must be a global string that lives until the end of the process,
// Note that the string pointed to must be have a lifetime until the end of the thread,
// for AssertCurrentThreadName to work.
void SetCurrentThreadName(const char *threadName);
void AssertCurrentThreadName(const char *threadName);
// If TLS is not supported, this will return an empty string.
const char *GetCurrentThreadName();
// Just gets a cheap thread identifier so that you can see different threads in debug output,
// exactly what it is is badly specified and not useful for anything.
int GetCurrentThreadIdForDebug();
// Call when leaving threads. On Android, calls DetachCurrentThread.
// Threads that use scoped storage I/O end up attached as JNI threads, and will thus
// need this in order to follow the rules correctly. Some devices seem to enforce this.
void DetachThreadFromJNI();
class AndroidJNIThreadContext {
public:
~AndroidJNIThreadContext() {
DetachThreadFromJNI();
}
};