diff --git a/Makefile.libnx b/Makefile.libnx index 13c7e52ab1..ab43db7ce4 100644 --- a/Makefile.libnx +++ b/Makefile.libnx @@ -19,8 +19,8 @@ OBJ := # For threading we need to overwrite some vars with global defines because devkitPro's includes # make it hard for us. This works for the pthread wrapper -DEFINES_THREAD := -Dpthread_t=Thread -Dpthread_mutex_t=Mutex -Dpthread_mutexattr_t='void*' -Dpthread_attr_t=int -Dpthread_cond_t=CondVar -Dpthread_condattr_t='int' -DEFINES := -U__linux__ -U__linux -DRARCH_INTERNAL -DGLOBAL_CONFIG_DIR='"/switch"' +DEFINES_THREAD := -Dpthread_t=Thread -Dpthread_mutex_t=Mutex -Dpthread_mutexattr_t='void*' -Dpthread_attr_t=int -Dpthread_cond_t=CondVar -Dpthread_condattr_t='int' -D_SYS__PTHREADTYPES_H_ +DEFINES := -U__linux__ -U__linux -DRARCH_INTERNAL -DGLOBAL_CONFIG_DIR='"/switch"' $(DEFINES_THREAD) HAVE_CC_RESAMPLER = 1 HAVE_MENU_COMMON = 1 @@ -42,8 +42,8 @@ HAVE_RUNAHEAD = 1 # RetroArch libnx useful flags HAVE_OVERLAY = 0 -HAVE_THREADS = 0 -HAVE_PTHREADS = 0 +HAVE_THREADS = 1 +HAVE_PTHREADS = 1 HAVE_FREETYPE = 0 HAVE_SWITCH = 1 HAVE_LIBNX = 1 @@ -76,12 +76,12 @@ OBJ := $(filter-out $(BLACKLIST),$(OBJ)) # - icon.jpg # - /default_icon.jpg #--------------------------------------------------------------------------------- -BUILD := build -SOURCES := $(CURDIR)/source -DATA := data +BUILD := build +SOURCES := $(CURDIR)/source +DATA := data INCLUDES := include -EXEFS_SRC := exefs_src -#ROMFS := switch/romfs +EXEFS_SRC := exefs_src +#ROMFS := switch/romfs APP_TITLE := RetroArch APP_VERSION := 1.0.0 diff --git a/libretro-common/rthreads/rthreads.c b/libretro-common/rthreads/rthreads.c index e155075555..b8f04f106c 100644 --- a/libretro-common/rthreads/rthreads.c +++ b/libretro-common/rthreads/rthreads.c @@ -47,6 +47,8 @@ #endif #elif defined(GEKKO) #include "gx_pthread.h" +#elif defined(HAVE_LIBNX) +#include "switch_pthread.h" #elif defined(_3DS) #include "ctr_pthread.h" #elif defined(__CELLOS_LV2__) diff --git a/libretro-common/rthreads/switch_pthread.h b/libretro-common/rthreads/switch_pthread.h new file mode 100644 index 0000000000..5d51194666 --- /dev/null +++ b/libretro-common/rthreads/switch_pthread.h @@ -0,0 +1,207 @@ +/* Copyright (C) 2018 - M4xw , RetroArch Team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (switch_pthread.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _SWITCH_PTHREAD_WRAP_ +#define _SWITCH_PTHREAD_WRAP_ + +#include +#include +#include +#include + +#include "../include/retro_inline.h" +#include "../../verbosity.h" + +#define THREADVARS_MAGIC 0x21545624 // !TV$ + +// This structure is exactly 0x20 bytes, if more is needed modify getThreadVars() below +typedef struct +{ + // Magic value used to check if the struct is initialized + u32 magic; + + // Thread handle, for mutexes + Handle handle; + + // Pointer to the current thread (if exists) + Thread *thread_ptr; + + // Pointer to this thread's newlib state + struct _reent *reent; + + // Pointer to this thread's thread-local segment + void *tls_tp; // !! Offset needs to be TLS+0x1F8 for __aarch64_read_tp !! +} ThreadVars; + +static INLINE ThreadVars *getThreadVars(void) +{ + return (ThreadVars *)((u8 *)armGetTls() + 0x1E0); +} + +#define STACKSIZE (8 * 1024) + +/* libnx threads return void but pthreads return void pointer */ + +static uint32_t threadCounter = 1; + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) +{ + u32 prio = 0; + Thread new_switch_thread; + + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + + // Launch threads on Core 1 + int rc = threadCreate(&new_switch_thread, (void (*)(void *))start_routine, arg, STACKSIZE, prio - 1, 1); + + if (R_FAILED(rc)) + { + return EAGAIN; + } + + printf("[Threading]: Starting Thread(#%i)\n", threadCounter); + if (R_FAILED(threadStart(&new_switch_thread))) + { + threadClose(&new_switch_thread); + return -1; + } + + *thread = new_switch_thread; + + return 0; +} + +void pthread_exit(void *retval) +{ + (void)retval; + printf("[Threading]: Exiting Thread\n"); + svcExitThread(); +} + +static INLINE Thread threadGetCurrent(void) +{ + ThreadVars *tv = getThreadVars(); + return *tv->thread_ptr; +} + +static INLINE pthread_t pthread_self(void) +{ + return threadGetCurrent(); +} + +static INLINE int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + mutexInit(mutex); + + return 0; +} + +INLINE int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + // Nothing + *mutex = 0; + + return 0; +} + +static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + mutexLock(mutex); + return 0; +} + +static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + mutexUnlock(mutex); + + return 0; +} + +INLINE int pthread_detach(pthread_t thread) +{ + (void)thread; + // Nothing for now + return 0; +} + +static INLINE int pthread_join(pthread_t thread, void **retval) +{ + printf("[Threading]: Waiting for Thread Exit\n"); + threadWaitForExit(&thread); + threadClose(&thread); + + return 0; +} + +static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + return mutexTryLock(mutex) ? 0 : 1; +} + +static INLINE int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + condvarWait(cond, mutex); + + return 0; +} + +static INLINE int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +{ + condvarWaitTimeout(cond, mutex, abstime->tv_nsec); + + return 0; +} + +static INLINE int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + condvarInit(cond); + + return 0; +} + +static INLINE int pthread_cond_signal(pthread_cond_t *cond) +{ + condvarWakeOne(cond); + return 0; +} + +static INLINE int pthread_cond_broadcast(pthread_cond_t *cond) +{ + condvarWakeAll(cond); + return 0; +} + +INLINE int pthread_cond_destroy(pthread_cond_t *cond) +{ + // Nothing + return 0; +} + +INLINE int pthread_equal(pthread_t t1, pthread_t t2) +{ + if (t1.handle == t2.handle) + return 1; + + return 0; +} + +#endif diff --git a/tasks/task_autodetect.c b/tasks/task_autodetect.c index 4f8ac88943..5da349b32b 100644 --- a/tasks/task_autodetect.c +++ b/tasks/task_autodetect.c @@ -843,8 +843,12 @@ static void input_autoconfigure_connect_handler(retro_task_t *task) if (!params || string_is_empty(params->name)) goto end; +#ifndef HAVE_LIBNX // This seems to be problematic on switch with threading if ( !input_autoconfigure_joypad_from_conf_dir(params, task) && !input_autoconfigure_joypad_from_conf_internal(params, task)) +#else + if ( !input_autoconfigure_joypad_from_conf_internal(params, task)) +#endif { char msg[255];