From 4f8ba2beb9fb818d9e072942b7d089c18eba3d3b Mon Sep 17 00:00:00 2001 From: rogerman Date: Mon, 30 Aug 2021 20:02:49 -0700 Subject: [PATCH] task.cpp: Support thread naming on macOS. - Related to commit 11fe823 and commit e70e065. --- .../src/libretro-common/rthreads/rthreads.c | 8 +++- desmume/src/utils/task.cpp | 45 ++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/desmume/src/libretro-common/rthreads/rthreads.c b/desmume/src/libretro-common/rthreads/rthreads.c index 45d84f5df..e2238823b 100644 --- a/desmume/src/libretro-common/rthreads/rthreads.c +++ b/desmume/src/libretro-common/rthreads/rthreads.c @@ -314,7 +314,13 @@ void sthread_setname(sthread_t *thread, const char *name) { if (!thread) return; - // TODO: implement that for Windows (and Mac?) too. + // TODO: implement that for Windows too. + // This can't be implemented on Apple OSes because pthread_setname_np() works + // substantially different. Not only does pthread_setname_np() take only the + // 'name' parameter, but it can only change the thread name on the current + // thread, when standard pthread_setname_np() can set the thread name from + // any thread. At the time of this writing (2021/08/30), there is no way to + // set the thread name from a different thread when running an Apple OS. #if !defined(USE_WIN32_THREADS) && !defined(__APPLE__) pthread_setname_np(thread->id, name); #endif diff --git a/desmume/src/utils/task.cpp b/desmume/src/utils/task.cpp index 8f785e2ae..d1e898cd2 100644 --- a/desmume/src/utils/task.cpp +++ b/desmume/src/utils/task.cpp @@ -16,11 +16,18 @@ */ #include +#include #include "types.h" #include "task.h" #include +#ifdef __APPLE__ +#include +#include +#include +#endif + class Task::Impl { private: sthread_t* _thread; @@ -35,6 +42,9 @@ public: void* finish(); void shutdown(); + bool needSetThreadName; + char threadName[16]; // pthread_setname_np() assumes a max character length of 16. + slock_t *mutex; scond_t *condWork; TWork workFunc; @@ -46,6 +56,19 @@ public: static void taskProc(void *arg) { Task::Impl *ctx = (Task::Impl *)arg; + + // The pthread_setname_np() function is gimped on macOS because it can't set thread + // names from any thread other than the current thread. That's why we can only set the + // thread name right here. We are not modifying rthreads, which is meant to be + // cross-platform, due to the substantially different nature of macOS's gimped version + // of pthread_setname_np(). +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + if (ctx->needSetThreadName) + { + pthread_setname_np(ctx->threadName); + ctx->needSetThreadName = false; + } +#endif do { slock_lock(ctx->mutex); @@ -75,6 +98,9 @@ Task::Impl::Impl() workFuncParam = NULL; ret = NULL; exitThread = false; + + memset(threadName, 0, sizeof(threadName)); + needSetThreadName = false; mutex = slock_new(); condWork = scond_new(); @@ -102,8 +128,23 @@ void Task::Impl::start(bool spinlock, int threadPriority, const char *name) this->exitThread = false; this->_thread = sthread_create_with_priority(&taskProc, this, threadPriority); this->_isThreadRunning = true; - if (name) - sthread_setname(this->_thread, name); + +#if !defined(USE_WIN32_THREADS) && !defined(__APPLE__) + sthread_setname(this->_thread, name); +#else + +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) + // Setting the thread name on macOS uses pthread_setname_np(), but this requires macOS v10.6 or later. + this->needSetThreadName = (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_6) && (name != NULL); +#else + this->needSetThreadName = (name != NULL); +#endif + + if (this->needSetThreadName) + { + strncpy(this->threadName, name, sizeof(this->threadName)); + } +#endif slock_unlock(this->mutex); }