switch: use pthreads

This commit is contained in:
cpasjuste 2021-06-22 14:33:02 +02:00
parent 4eb5d77750
commit b4f02bcaca
8 changed files with 22 additions and 607 deletions

View File

@ -60,8 +60,11 @@
#include <kernel/OS.h> #include <kernel/OS.h>
#endif #endif
#ifdef __SWITCH__
#include <switch.h>
#endif
#ifndef __NACL__ #if !defined(__NACL__) && !defined(__SWITCH__)
/* List of signals to mask in the subthreads */ /* List of signals to mask in the subthreads */
static const int sig_list[] = { static const int sig_list[] = {
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
@ -126,10 +129,10 @@ SDL_SYS_CreateThread(SDL_Thread * thread)
void void
SDL_SYS_SetupThread(const char *name) SDL_SYS_SetupThread(const char *name)
{ {
#if !defined(__NACL__) #if !defined(__NACL__) && !defined(__SWITCH__)
int i; int i;
sigset_t mask; sigset_t mask;
#endif /* !__NACL__ */ #endif /* !__NACL__ && !__NINTENDO_SWITCH__ */
if (name != NULL) { if (name != NULL) {
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__) #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
@ -159,14 +162,14 @@ SDL_SYS_SetupThread(const char *name)
} }
/* NativeClient does not yet support signals.*/ /* NativeClient does not yet support signals.*/
#if !defined(__NACL__) #if !defined(__NACL__) && !defined(__SWITCH__)
/* Mask asynchronous signals for this thread */ /* Mask asynchronous signals for this thread */
sigemptyset(&mask); sigemptyset(&mask);
for (i = 0; sig_list[i]; ++i) { for (i = 0; sig_list[i]; ++i) {
sigaddset(&mask, sig_list[i]); sigaddset(&mask, sig_list[i]);
} }
pthread_sigmask(SIG_BLOCK, &mask, 0); pthread_sigmask(SIG_BLOCK, &mask, 0);
#endif /* !__NACL__ */ #endif /* !__NACL__ && !__NINTENDO_SWITCH__ */
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
@ -200,6 +203,20 @@ SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
{ {
#if __NACL__ || __RISCOS__ #if __NACL__ || __RISCOS__
/* FIXME: Setting thread priority does not seem to be supported in NACL */ /* FIXME: Setting thread priority does not seem to be supported in NACL */
return 0;
#elif __SWITCH__
Result res;
if (priority == SDL_THREAD_PRIORITY_HIGH) {
res = svcSetThreadPriority(CUR_THREAD_HANDLE, 0x2B);
} else {
// 0x3B = preemptive threading
res = svcSetThreadPriority(CUR_THREAD_HANDLE, 0x3B);
}
if(R_FAILED(res)) {
return SDL_SetError("SDL_SYS_SetThreadPriority: svcSetThreadPriority failed (%x)", res);
}
return 0; return 0;
#else #else
struct sched_param sched; struct sched_param sched;

View File

@ -1,173 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <switch.h>
#include <threads.h>
#include "../../SDL_internal.h"
#if SDL_THREAD_SWITCH
/* An implementation of condition variables using semaphores and mutexes */
/*
This implementation borrows heavily from the BeOS condition variable
implementation, written by Christopher Tate and Owen Smith. Thanks!
*/
#include "SDL_thread.h"
struct SDL_cond
{
cnd_t cnd;
};
struct SDL_mutex
{
mtx_t mtx;
};
/* Create a condition variable */
SDL_cond *
SDL_CreateCond(void)
{
SDL_cond *cond = NULL;
cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
if (cond) {
int res = cnd_init(&cond->cnd);
if (res != thrd_success) {
printf("SDL_CreateCond::cnd_init failed: %i\n", res);
}
}
else {
SDL_OutOfMemory();
}
return (cond);
}
/* Destroy a condition variable */
void
SDL_DestroyCond(SDL_cond *cond)
{
if (cond) {
cnd_destroy(&cond->cnd);
SDL_free(cond);
}
}
/* Restart one of the threads that are waiting on the condition variable */
int
SDL_CondSignal(SDL_cond *cond)
{
int res;
if (!cond) {
return SDL_SetError("Passed a NULL cond");
}
res = cnd_signal(&cond->cnd);
if (res != thrd_success) {
return SDL_SetError("SDL_CondSignal::cnd_signal failed: %i", res);
}
return 0;
}
/* Restart all threads that are waiting on the condition variable */
int
SDL_CondBroadcast(SDL_cond *cond)
{
int res;
if (!cond) {
return SDL_SetError("Passed a NULL cond");
}
res = cnd_broadcast(&cond->cnd);
if (res != thrd_success) {
return SDL_SetError("SDL_CondBroadcast::cnd_broadcast failed: %i", res);
}
return 0;
}
/* Wait on the condition variable for at most 'ms' milliseconds.
The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait.
Typical use:
Thread A:
SDL_LockMutex(lock);
while ( ! condition ) {
SDL_CondWait(cond, lock);
}
SDL_UnlockMutex(lock);
Thread B:
SDL_LockMutex(lock);
...
condition = true;
...
SDL_CondSignal(cond);
SDL_UnlockMutex(lock);
*/
int
SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
{
struct timespec ts;
int res;
if (!cond || !mutex) {
return SDL_SetError("SDL_CondWaitTimeout: passed a NULL cond/mutex");
}
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_nsec += (long) (ms * 1E6);
res = cnd_timedwait(&cond->cnd, &mutex->mtx, &ts);
if (res == thrd_timedout) {
return SDL_MUTEX_TIMEDOUT;
} else if (res != thrd_success) {
return SDL_SetError("SDL_CondWaitTimeout::cnd_timedwait failed: %i", res);
}
return 0;
}
/* Wait on the condition variable forever */
int
SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,86 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_SWITCH
/* An implementation of mutexes */
#include "SDL_thread.h"
#include "SDL_systhread_c.h"
struct SDL_mutex
{
mtx_t mtx;
};
/* Create a mutex */
SDL_mutex *
SDL_CreateMutex(void)
{
SDL_mutex *mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
if (mutex) {
mtx_init(&mutex->mtx, mtx_plain | mtx_recursive);
}
else {
SDL_OutOfMemory();
}
return mutex;
}
/* Free the mutex */
void
SDL_DestroyMutex(SDL_mutex *mutex)
{
if (mutex) {
mtx_destroy(&mutex->mtx);
SDL_free(mutex);
}
}
/* Lock the mutex */
int
SDL_mutexP(SDL_mutex *mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
mtx_lock(&mutex->mtx);
return 0;
}
/* Unlock the mutex */
int
SDL_mutexV(SDL_mutex *mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
mtx_unlock(&mutex->mtx);
return 0;
}
#endif /* SDL_THREAD_SWITCH */

View File

@ -1,22 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"

View File

@ -1,172 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_SWITCH
/* Semaphore functions for the SWITCH. */
#include <stdio.h>
#include "SDL_error.h"
#include "SDL_thread.h"
#include "SDL_timer.h"
struct SDL_semaphore
{
Uint32 count;
Uint32 waiters_count;
SDL_mutex *count_lock;
SDL_cond *count_nonzero;
};
/* Create a semaphore */
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_sem *sem;
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
if (!sem) {
SDL_OutOfMemory();
return NULL;
}
sem->count = initial_value;
sem->waiters_count = 0;
sem->count_lock = SDL_CreateMutex();
sem->count_nonzero = SDL_CreateCond();
if (!sem->count_lock || !sem->count_nonzero) {
SDL_DestroySemaphore(sem);
return NULL;
}
return sem;
}
/* Free the semaphore */
void SDL_DestroySemaphore(SDL_sem *sem)
{
if (sem) {
sem->count = 0xFFFFFFFF;
while (sem->waiters_count > 0) {
SDL_CondSignal(sem->count_nonzero);
SDL_Delay(10);
}
SDL_DestroyCond(sem->count_nonzero);
if (sem->count_lock) {
SDL_mutexP(sem->count_lock);
SDL_mutexV(sem->count_lock);
SDL_DestroyMutex(sem->count_lock);
}
SDL_free(sem);
}
}
/* TODO: This routine is a bit overloaded.
* If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
* NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
* is specified, convert it to microseconds. */
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
if (!sem) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
/* A timeout of 0 is an easy case */
if (timeout == 0) {
return SDL_SemTryWait(sem);
}
SDL_LockMutex(sem->count_lock);
++sem->waiters_count;
retval = 0;
while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
retval = SDL_CondWaitTimeout(sem->count_nonzero, sem->count_lock, timeout);
}
--sem->waiters_count;
if (retval == 0) {
--sem->count;
}
SDL_UnlockMutex(sem->count_lock);
return retval;
}
int SDL_SemTryWait(SDL_sem *sem)
{
int retval;
if (!sem) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
retval = SDL_MUTEX_TIMEDOUT;
SDL_LockMutex(sem->count_lock);
if (sem->count > 0) {
--sem->count;
retval = 0;
}
SDL_UnlockMutex(sem->count_lock);
return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
/* Returns the current count of the semaphore */
Uint32 SDL_SemValue(SDL_sem *sem)
{
Uint32 value;
value = 0;
if (sem) {
SDL_LockMutex(sem->count_lock);
value = sem->count;
SDL_UnlockMutex(sem->count_lock);
}
return value;
}
int SDL_SemPost(SDL_sem *sem)
{
if (!sem) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
SDL_LockMutex(sem->count_lock);
if (sem->waiters_count > 0) {
SDL_CondSignal(sem->count_nonzero);
}
++sem->count;
SDL_UnlockMutex(sem->count_lock);
return 0;
}
#endif /* SDL_THREAD_SWITCH */

View File

@ -1,90 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_SWITCH
/* SWITCH thread management routines for SDL */
#include <stdio.h>
#include <switch.h>
#include "SDL_error.h"
#include "SDL_thread.h"
#include "../SDL_systhread.h"
static int
SDL_SYS_RunThread(void *data)
{
SDL_RunThread(data);
return 0;
}
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{
int res = thrd_create(&thread->handle, SDL_SYS_RunThread, args);
if (res != thrd_success) {
return SDL_SetError("SDL_SYS_CreateThread failed: %i", res);
}
return 0;
}
void SDL_SYS_SetupThread(const char *name)
{
}
SDL_threadID SDL_ThreadID(void)
{
return (SDL_threadID) thrd_current();
}
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
if (thread) {
thrd_join(thread->handle, NULL);
}
}
void SDL_SYS_DetachThread(SDL_Thread *thread)
{
}
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
{
Result res;
if (priority == SDL_THREAD_PRIORITY_HIGH) {
res = svcSetThreadPriority(CUR_THREAD_HANDLE, 0x2B);
}
else {
// 0x3B = preemptive threading
res = svcSetThreadPriority(CUR_THREAD_HANDLE, 0x3B);
}
if(R_FAILED(res)) {
return SDL_SetError("SDL_SYS_SetThreadPriority failed: %i", res);
}
return 0;
}
#endif /* SDL_THREAD_SWITCH */

View File

@ -1,25 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <switch.h>
#include <threads.h>
typedef thrd_t SYS_ThreadHandle;

View File

@ -1,34 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_thread_c.h"
SDL_TLSData *
SDL_SYS_GetTLSData(void)
{
return SDL_Generic_GetTLSData();
}
int
SDL_SYS_SetTLSData(SDL_TLSData *data)
{
return SDL_Generic_SetTLSData(data);
}