3ds: customize thread creation
authornotaz <notasas@gmail.com>
Mon, 14 Oct 2024 22:49:22 +0000 (01:49 +0300)
committernotaz <notasas@gmail.com>
Wed, 23 Oct 2024 21:17:35 +0000 (00:17 +0300)
Makefile
frontend/3ds/3ds_utils.h
frontend/3ds/pthread.h
frontend/libretro-rthreads.c
frontend/libretro-rthreads.h
frontend/libretro.c
frontend/libretro_core_options.h
frontend/main.c
libpcsxcore/cdrom-async.c
libpcsxcore/new_dynarec/emu_if.c

index f30816f..69b7ab3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -369,7 +369,7 @@ endif # $(PLATFORM) == "libretro"
 ifeq "$(USE_RTHREADS)" "1"
 OBJS += frontend/libretro-rthreads.o
 OBJS += deps/libretro-common/features/features_cpu.o
-frontend/main.o: CFLAGS += -DHAVE_CPU_FEATURES
+frontend/main.o: CFLAGS += -DHAVE_RTHREADS
 INC_LIBRETRO_COMMON := 1
 endif
 ifeq "$(INC_LIBRETRO_COMMON)" "1"
index 75ab63b..f7c8ddc 100644 (file)
@@ -3,7 +3,8 @@
 
 #include <stdio.h>
 #include <stdbool.h>
-#include <3ds.h>
+#include <3ds/os.h>
+#include <3ds/svc.h>
 
 #ifdef OS_HEAP_AREA_BEGIN // defined in libctru 2.0+
 #define USE_CTRULIB_2 1
index 76f1681..63afa32 100644 (file)
 #ifndef _CTR_PTHREAD_WRAP_CTR_
 #define _CTR_PTHREAD_WRAP_CTR_
 
+#include <3ds/thread.h>
+#include <3ds/services/apt.h>
 #include "3ds_utils.h"
 
+#include <sys/time.h>
 #include <time.h>
 #include <errno.h>
 
index 72784d4..2450750 100644 (file)
@@ -1,20 +1,98 @@
-// temporary(?) workaround:
-// https://github.com/libretro/libretro-common/pull/216
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE // *_np
+#endif
 #ifdef _3DS
 #include <3ds/svc.h>
+#include <3ds/os.h>
 #include <3ds/services/apt.h>
 #include <sys/time.h>
 #endif
 
 #include "../deps/libretro-common/rthreads/rthreads.c"
+#include "features/features_cpu.h"
+#include "libretro-rthreads.h"
+
+// pcsxr "extensions"
+extern void SysPrintf(const char *fmt, ...);
+
+#ifdef _3DS
+static bool is_new_3ds;
+#endif
 
-// an "extension"
-int sthread_set_name(sthread_t *thread, const char *name)
+void pcsxr_sthread_init(void)
 {
-#if defined(__GLIBC__) || defined(__MACH__) || \
-   (defined(__ANDROID_API__) && __ANDROID_API__ >= 26)
-       if (thread)
-               return pthread_setname_np(thread->id, name);
+       SysPrintf("%d cpu core(s) detected\n", cpu_features_get_core_amount());
+#ifdef _3DS
+       int64_t version = 0;
+       APT_CheckNew3DS(&is_new_3ds);
+       svcGetSystemInfo(&version, 0x10000, 0);
+
+       APT_SetAppCpuTimeLimit(35);
+       u32 percent = -1;
+       APT_GetAppCpuTimeLimit(&percent);
+
+       SysPrintf("%s3ds detected, v%d.%d, AppCpuTimeLimit=%ld\n",
+               is_new_3ds ? "new" : "old", (int)GET_VERSION_MAJOR(version),
+               (int)GET_VERSION_MINOR(version), percent);
+#endif
+}
+
+sthread_t *pcsxr_sthread_create(void (*thread_func)(void *),
+       enum pcsxr_thread_type type)
+{
+       sthread_t *h = NULL;
+#ifdef _3DS
+       Thread ctr_thread;
+       int core_id = 0;
+       s32 prio = 0x30;
+
+       h = calloc(1, sizeof(*h));
+       if (!h)
+               return NULL;
+
+       svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
+
+       switch (type) {
+       case PCSXRT_CDR:
+       case PCSXRT_SPU:
+               core_id = 1;
+               break;
+       case PCSXRT_DRC:
+       case PCSXRT_GPU:
+               core_id = is_new_3ds ? 2 : 1;
+               break;
+       case PCSXRT_COUNT:
+               break;
+       }
+
+       ctr_thread = threadCreate(thread_func, NULL, STACKSIZE, prio, core_id, false);
+       if (!ctr_thread) {
+               if (core_id == 1) {
+                       SysPrintf("threadCreate pcsxt %d core %d failed\n",
+                               type, core_id);
+                       core_id = is_new_3ds ? 2 : -1;
+                       ctr_thread = threadCreate(thread_func, NULL, STACKSIZE,
+                               prio, core_id, false);
+               }
+       }
+       if (!ctr_thread) {
+               SysPrintf("threadCreate pcsxt %d core %d failed\n", type, core_id);
+               free(h);
+               return NULL;
+       }
+       h->id = (pthread_t)ctr_thread;
+#else
+       h = sthread_create(thread_func, NULL);
+ #if defined(__GLIBC__) || defined(__MACH__) || \
+    (defined(__ANDROID_API__) && __ANDROID_API__ >= 26)
+       if (h && (unsigned int)type < (unsigned int)PCSXRT_COUNT)
+       {
+               const char * const pcsxr_tnames[PCSXRT_COUNT] = {
+                       "pcsxr-cdrom", "pcsxr-drc", "pcsxr-gpu", "pcsxr-spu"
+               };
+               pthread_setname_np(h->id, pcsxr_tnames[type]);
+       }
+ #endif
 #endif
-       return -1;
+       return h;
 }
index 851d448..6a2d004 100644 (file)
@@ -1,3 +1,19 @@
+#ifndef __LIBRETRO_PCSXR_RTHREADS_H__
+#define __LIBRETRO_PCSXR_RTHREADS_H__
+
 #include "rthreads/rthreads.h"
 
-int sthread_set_name(sthread_t *thread, const char *name);
+enum pcsxr_thread_type
+{
+       PCSXRT_CDR = 0,
+       PCSXRT_DRC,
+       PCSXRT_GPU,
+       PCSXRT_SPU,
+       PCSXRT_COUNT // must be last
+};
+
+void pcsxr_sthread_init(void);
+sthread_t *pcsxr_sthread_create(void (*thread_func)(void*),
+       enum pcsxr_thread_type type);
+
+#endif // __LIBRETRO_PCSXR_RTHREADS_H__
index f7eb64c..ce0e742 100644 (file)
@@ -50,6 +50,9 @@
 #endif
 
 #ifdef _3DS
+#include <3ds/svc.h>
+#include <3ds/services/apt.h>
+#include <3ds/allocator/linear.h>
 #include "3ds/3ds_utils.h"
 #endif
 
@@ -2778,6 +2781,15 @@ static void update_variables(bool in_flight)
       mouse_sensitivity = atof(var.value);
    }
 
+#ifdef _3DS
+   var.value = NULL;
+   var.key = "pcsx_rearmed_3ds_appcputime";
+   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+   {
+      APT_SetAppCpuTimeLimit(strtol(var.value, NULL, 10));
+   }
+#endif
+
    if (found_bios)
    {
       var.value = NULL;
index a4ead77..8910ad2 100644 (file)
@@ -1612,6 +1612,30 @@ struct retro_core_option_v2_definition option_defs_us[] = {
       },
       "disabled",
    },
+#ifdef _3DS
+#define V(x) { #x, NULL }
+   {
+      "pcsx_rearmed_3ds_appcputime",
+      "3DS AppCpuTimeLimit",
+      NULL,
+      "% of syscore (core #1) CPU time allocated to the emulator",
+      NULL,
+      "speed_hack",
+      {
+         V( 5),  V(10),
+         V(15),  V(20),
+         V(25),  V(30),
+         V(35),  V(40),
+         V(45),  V(50),
+         V(55),  V(60),
+         V(65),  V(70),
+         V(75),  V(80),
+         { NULL, NULL},
+      },
+      "35",
+   },
+#undef V
+#endif // _3DS
    {
       "pcsx_rearmed_cd_turbo",
       "Turbo CD",
index 0bb4a6d..949ba65 100644 (file)
@@ -14,8 +14,8 @@
 #if !defined(_WIN32) && !defined(NO_DYLIB)
 #include <dlfcn.h>
 #endif
-#ifdef HAVE_CPU_FEATURES
-#include "features/features_cpu.h"
+#ifdef HAVE_RTHREADS
+#include "../frontend/libretro-rthreads.h"
 #endif
 
 #include "main.h"
@@ -513,10 +513,8 @@ int emu_core_preinit(void)
 int emu_core_init(void)
 {
        SysPrintf("Starting PCSX-ReARMed " REV "%s\n", get_build_info());
-#ifdef HAVE_CPU_FEATURES
-       SysPrintf("%d cpu core(s) detected\n", cpu_features_get_core_amount());
-#endif
 
+       pcsxr_sthread_init();
 #ifndef NO_FRONTEND
        check_profile();
        check_memcards();
index 4da0f37..81b2e12 100644 (file)
@@ -268,12 +268,11 @@ static void cdra_start_thread(void)
    if (acdrom.buf_cache && acdrom.buf_lock && acdrom.read_lock && acdrom.cond)
    {
       int i;
-      acdrom.thread = sthread_create(cdra_prefetch_thread, NULL);
+      acdrom.thread = pcsxr_sthread_create(cdra_prefetch_thread, PCSXRT_CDR);
       for (i = 0; i < acdrom.buf_cnt; i++)
          acdrom.buf_cache[i].lba = ~0;
    }
    if (acdrom.thread) {
-      sthread_set_name(acdrom.thread, "pcsxr-cdrom");
       SysPrintf("cdrom precache: %d buffers%s\n",
             acdrom.buf_cnt, acdrom.have_subchannel ? " +sub" : "");
    }
index e495801..57fe663 100644 (file)
@@ -499,7 +499,7 @@ static void ari64_thread_init(void)
                ndrc_g.thread.cond = scond_new();
        }
        if (ndrc_g.thread.lock && ndrc_g.thread.cond)
-               ndrc_g.thread.handle = sthread_create(ari64_compile_thread, NULL);
+               ndrc_g.thread.handle = pcsxr_sthread_create(ari64_compile_thread, PCSXRT_DRC);
        if (ndrc_g.thread.handle) {
                psxRec.Execute = ari64_execute_threaded;
                psxRec.ExecuteBlock = ari64_execute_threaded_block;