switch: use c11 threads

This commit is contained in:
Cpasjuste 2018-12-13 09:39:43 +01:00 committed by Dave Murphy
parent 063a1c9265
commit 6748b87af8
4 changed files with 71 additions and 73 deletions

View File

@ -19,6 +19,7 @@
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
#include <switch.h> #include <switch.h>
#include <threads.h>
#include "../../SDL_internal.h" #include "../../SDL_internal.h"
#if SDL_THREAD_SWITCH #if SDL_THREAD_SWITCH
@ -33,23 +34,26 @@
struct SDL_cond struct SDL_cond
{ {
CondVar var; cnd_t cnd;
}; };
struct SDL_mutex struct SDL_mutex
{ {
RMutex mtx; mtx_t mtx;
}; };
/* Create a condition variable */ /* Create a condition variable */
SDL_cond * SDL_cond *
SDL_CreateCond(void) SDL_CreateCond(void)
{ {
SDL_cond *cond; SDL_cond *cond = NULL;
cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
if (cond) { if (cond) {
condvarInit(&cond->var); int res = cnd_init(&cond->cnd);
if (res != thrd_success) {
printf("SDL_CreateCond::cnd_init failed: %i\n", res);
}
} }
else { else {
SDL_OutOfMemory(); SDL_OutOfMemory();
@ -62,6 +66,7 @@ void
SDL_DestroyCond(SDL_cond *cond) SDL_DestroyCond(SDL_cond *cond)
{ {
if (cond) { if (cond) {
cnd_destroy(&cond->cnd);
SDL_free(cond); SDL_free(cond);
} }
} }
@ -70,11 +75,16 @@ SDL_DestroyCond(SDL_cond *cond)
int int
SDL_CondSignal(SDL_cond *cond) SDL_CondSignal(SDL_cond *cond)
{ {
int res;
if (!cond) { if (!cond) {
return SDL_SetError("Passed a NULL condition variable"); return SDL_SetError("Passed a NULL cond");
} }
condvarWakeOne(&cond->var); res = cnd_signal(&cond->cnd);
if (res != thrd_success) {
return SDL_SetError("SDL_CondSignal::cnd_signal failed: %i", res);
}
return 0; return 0;
} }
@ -83,11 +93,16 @@ SDL_CondSignal(SDL_cond *cond)
int int
SDL_CondBroadcast(SDL_cond *cond) SDL_CondBroadcast(SDL_cond *cond)
{ {
int res;
if (!cond) { if (!cond) {
return SDL_SetError("Passed a NULL condition variable"); return SDL_SetError("Passed a NULL cond");
} }
condvarWakeAll(&cond->var); res = cnd_broadcast(&cond->cnd);
if (res != thrd_success) {
return SDL_SetError("SDL_CondBroadcast::cnd_broadcast failed: %i", res);
}
return 0; return 0;
} }
@ -116,22 +131,19 @@ Thread B:
int int
SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
{ {
uint32_t mutex_state[2]; struct timespec ts;
int res;
if (!cond) { if (!cond || !mutex) {
return SDL_SetError("Passed a NULL condition variable"); return SDL_SetError("SDL_CondWaitTimeout: passed a NULL cond/mutex");
} }
// backup mutex state ts.tv_sec = ms / 1000;
mutex_state[0] = mutex->mtx.thread_tag; ts.tv_nsec = (ms % 1000) * 1000000;
mutex_state[1] = mutex->mtx.counter; res = cnd_timedwait(&cond->cnd, &mutex->mtx, &ts);
mutex->mtx.thread_tag = 0; if (res != thrd_success) {
mutex->mtx.counter = 0; return SDL_SetError("SDL_CondWaitTimeout::cnd_timedwait failed: %i", res);
}
condvarWaitTimeout(&cond->var, &mutex->mtx.lock, ms * 1000000);
mutex->mtx.thread_tag = mutex_state[0];
mutex->mtx.counter = mutex_state[1];
return 0; return 0;
} }
@ -140,7 +152,18 @@ SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
int int
SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{ {
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); int res;
if (!cond || !mutex) {
return SDL_SetError("SDL_CondWaitTimeout: passed a NULL cond/mutex");
}
res = cnd_wait(&cond->cnd, &mutex->mtx);
if (res != thrd_success) {
return SDL_SetError("SDL_CondWait::cnd_wait failed: %i", res);
}
return 0;
} }
#endif /* SDL_THREAD_SWITCH */ #endif /* SDL_THREAD_SWITCH */

View File

@ -22,14 +22,14 @@
#if SDL_THREAD_SWITCH #if SDL_THREAD_SWITCH
/* An implementation of mutexes using semaphores */ /* An implementation of mutexes */
#include "SDL_thread.h" #include "SDL_thread.h"
#include "SDL_systhread_c.h" #include "SDL_systhread_c.h"
struct SDL_mutex struct SDL_mutex
{ {
RMutex mtx; mtx_t mtx;
}; };
/* Create a mutex */ /* Create a mutex */
@ -38,7 +38,7 @@ SDL_CreateMutex(void)
{ {
SDL_mutex *mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex)); SDL_mutex *mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
if (mutex) { if (mutex) {
rmutexInit(&mutex->mtx); mtx_init(&mutex->mtx, mtx_plain | mtx_recursive);
} }
else { else {
SDL_OutOfMemory(); SDL_OutOfMemory();
@ -52,11 +52,12 @@ void
SDL_DestroyMutex(SDL_mutex *mutex) SDL_DestroyMutex(SDL_mutex *mutex)
{ {
if (mutex) { if (mutex) {
mtx_destroy(&mutex->mtx);
SDL_free(mutex); SDL_free(mutex);
} }
} }
/* Lock the semaphore */ /* Lock the mutex */
int int
SDL_mutexP(SDL_mutex *mutex) SDL_mutexP(SDL_mutex *mutex)
{ {
@ -64,7 +65,7 @@ SDL_mutexP(SDL_mutex *mutex)
return SDL_SetError("Passed a NULL mutex"); return SDL_SetError("Passed a NULL mutex");
} }
rmutexLock(&mutex->mtx); mtx_lock(&mutex->mtx);
return 0; return 0;
} }
@ -77,7 +78,7 @@ SDL_mutexV(SDL_mutex *mutex)
return SDL_SetError("Passed a NULL mutex"); return SDL_SetError("Passed a NULL mutex");
} }
rmutexUnlock(&mutex->mtx); mtx_unlock(&mutex->mtx);
return 0; return 0;
} }

View File

@ -31,39 +31,18 @@
#include "SDL_thread.h" #include "SDL_thread.h"
#include "../SDL_systhread.h" #include "../SDL_systhread.h"
#define STACK_SIZE 0x20000 static int
static void
SDL_SYS_RunThread(void *data) SDL_SYS_RunThread(void *data)
{ {
SDL_RunThread(data); SDL_RunThread(data);
return 0;
} }
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{ {
Result res; int res = thrd_create(&thread->handle, SDL_SYS_RunThread, args);
u64 core_mask = 0; if (res != thrd_success) {
return SDL_SetError("SDL_SYS_CreateThread failed: %i", res);
res = svcGetInfo(&core_mask, 0, CUR_PROCESS_HANDLE, 0);
if (R_FAILED(res)) {
return SDL_SetError("svcGetInfo() failed: 0x%08X", res);
}
res = threadCreate(&thread->handle, SDL_SYS_RunThread, args, STACK_SIZE, 0x2C, -2);
if (R_FAILED(res)) {
return SDL_SetError("threadCreate() failed: 0x%08X", res);
}
res = svcSetThreadCoreMask(thread->handle.handle, -1, (u32) core_mask);
if (R_FAILED(res)) {
threadClose(&thread->handle);
return SDL_SetError("threadCreate() failed: 0x%08X", res);
}
res = threadStart(&thread->handle);
if (R_FAILED(res)) {
threadClose(&thread->handle);
return SDL_SetError("threadStart() failed: 0x%08X", res);
} }
return 0; return 0;
@ -71,45 +50,39 @@ int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
void SDL_SYS_SetupThread(const char *name) void SDL_SYS_SetupThread(const char *name)
{ {
/* Do nothing. */
} }
SDL_threadID SDL_ThreadID(void) SDL_threadID SDL_ThreadID(void)
{ {
u64 tid = 0; return (SDL_threadID) thrd_current();
svcGetThreadId(&tid, CUR_THREAD_HANDLE);
return (SDL_threadID) tid;
} }
void SDL_SYS_WaitThread(SDL_Thread *thread) void SDL_SYS_WaitThread(SDL_Thread *thread)
{ {
if (thread && thread->handle.handle) { if (thread) {
threadWaitForExit(&thread->handle); thrd_join(thread->handle, NULL);
threadClose(&thread->handle);
} }
} }
void SDL_SYS_DetachThread(SDL_Thread *thread) void SDL_SYS_DetachThread(SDL_Thread *thread)
{ {
if (thread && thread->handle.handle) {
threadClose(&thread->handle);
}
} }
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
{ {
u32 value = 0x2C; Result res;
if (priority == SDL_THREAD_PRIORITY_LOW) { if (priority == SDL_THREAD_PRIORITY_HIGH) {
value = 0x2D; res = svcSetThreadPriority(CUR_THREAD_HANDLE, 0x1C);
} }
else if (priority == SDL_THREAD_PRIORITY_HIGH) { else {
value = 0x1C; // 0x3B = preemptive threading
res = svcSetThreadPriority(CUR_THREAD_HANDLE, 0x3B);
} }
svcSetThreadPriority(CUR_THREAD_HANDLE, value); if(R_FAILED(res)) {
return SDL_SetError("SDL_SYS_SetThreadPriority failed: %i", res);
}
return 0; return 0;
} }

View File

@ -20,5 +20,6 @@
*/ */
#include <switch.h> #include <switch.h>
#include <threads.h>
typedef Thread SYS_ThreadHandle; typedef thrd_t SYS_ThreadHandle;