From 9545dd7603a0c199b1ba1f331cf318b7108a7b6a Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Sun, 18 Feb 2024 00:54:32 +0100 Subject: [PATCH] Implement detached threads (#88) The `AsyncTerm` thread is never joined but its handle is immediately closed. This works fine on Windows, but causes issues on other platforms where threads need to be explicitly detached if never joined (pthread, wiiu). This adds a new `PltDetachThread` function, which can be used instead of `PltCloseThread` to explictly detach a thread, requiring it to no longer be closed. --- src/Connection.c | 4 ++-- src/Platform.c | 43 +++++++++++++++++++++++++++++++++++++++---- src/PlatformThreads.h | 1 + 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/Connection.c b/src/Connection.c index 2b82eda..dddff92 100644 --- a/src/Connection.c +++ b/src/Connection.c @@ -175,8 +175,8 @@ static void ClInternalConnectionTerminated(int errorCode) LC_ASSERT(err == 0); } - // Close the thread handle since we can never wait on it - PltCloseThread(&terminationCallbackThread); + // Detach the thread since we never wait on it + PltDetachThread(&terminationCallbackThread); } static bool parseRtspPortNumberFromUrl(const char* rtspSessionUrl, uint16_t* port) diff --git a/src/Platform.c b/src/Platform.c index f41ffde..625b924 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -198,18 +198,43 @@ void PltJoinThread(PLT_THREAD* thread) { OSJoinThread(&thread->thread, NULL); #elif defined(__3DS__) threadJoin(thread->thread, U64_MAX); - threadFree(thread->thread); #else pthread_join(thread->thread, NULL); #endif } +void PltDetachThread(PLT_THREAD* thread) +{ + // Assume detached threads are no longer active + activeThreads--; + +#if defined(LC_WINDOWS) + // According MSDN: + // "Closing a thread handle does not terminate the associated thread or remove the thread object." + CloseHandle(thread->handle); +#elif defined(__vita__) + sceKernelDeleteThread(thread->handle); +#elif defined(__WIIU__) + OSDetachThread(&thread->thread); +#elif defined(__3DS__) + threadDetach(thread->thread); +#else + pthread_detach(thread->thread); +#endif +} + void PltCloseThread(PLT_THREAD* thread) { activeThreads--; #if defined(LC_WINDOWS) CloseHandle(thread->handle); #elif defined(__vita__) sceKernelDeleteThread(thread->handle); +#elif defined(__WIIU__) + // Thread is automatically closed after join +#elif defined(__3DS__) + threadFree(thread->thread); +#else + // Thread is automatically closed after join #endif } @@ -262,19 +287,29 @@ int PltCreateThread(const char* name, ThreadEntry entry, void* context, PLT_THRE sceKernelStartThread(thread->handle, sizeof(struct thread_context), ctx); } #elif defined(__WIIU__) - int stack_size = 4 * 1024 * 1024; - void* stack_addr = (uint8_t *)memalign(8, stack_size) + stack_size; + memset(&thread->thread, 0, sizeof(thread->thread)); + + // Allocate stack + const int stack_size = 4 * 1024 * 1024; + uint8_t* stack = (uint8_t*)memalign(16, stack_size); + if (stack == NULL) { + free(ctx); + return -1; + } + // Create thread if (!OSCreateThread(&thread->thread, ThreadProc, 0, (char*)ctx, - stack_addr, stack_size, + stack + stack_size, stack_size, 0x10, OS_THREAD_ATTRIB_AFFINITY_ANY)) { free(ctx); + free(stack); return -1; } + OSSetThreadName(&thread->thread, name); OSSetThreadDeallocator(&thread->thread, thread_deallocator); OSResumeThread(&thread->thread); #elif defined(__3DS__) diff --git a/src/PlatformThreads.h b/src/PlatformThreads.h index 67cdb5e..75d1980 100644 --- a/src/PlatformThreads.h +++ b/src/PlatformThreads.h @@ -66,6 +66,7 @@ void PltCloseThread(PLT_THREAD* thread); void PltInterruptThread(PLT_THREAD* thread); bool PltIsThreadInterrupted(PLT_THREAD* thread); void PltJoinThread(PLT_THREAD* thread); +void PltDetachThread(PLT_THREAD* thread); int PltCreateEvent(PLT_EVENT* event); void PltCloseEvent(PLT_EVENT* event);