From e944be0be842d3be1a5b260c497e0dc1fb203f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Pommel?= Date: Mon, 17 Aug 2026 17:59:48 +0200 Subject: [PATCH 1/3] fix: bound malloc arenas and thread stacks in minarch --- workspace/all/common/api.c | 19 +++++++++++++++++-- workspace/all/minarch/minarch.c | 6 ++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 19f3f5439..91c6169d9 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -3858,6 +3858,21 @@ int PAD_tappedSelect(uint32_t now) return PAD_tappedBtn(BTN_SELECT, now); } +/////////////////////////////// + +// the RLIMIT_STACK default (8MB per thread) wastes address space +#define THREAD_STACK_SIZE (1024 * 1024) + +static int spawn_thread(pthread_t *pt, void *(*fn)(void *), void *arg) +{ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE); + int rc = pthread_create(pt, &attr, fn, arg); + pthread_attr_destroy(&attr); + return rc; +} + /////////////////////////////// static struct VIB_Context { @@ -3891,7 +3906,7 @@ static void *VIB_thread(void *arg) void VIB_init(void) { vib.queued_strength = vib.strength = 0; - pthread_create(&vib.pt, NULL, &VIB_thread, NULL); + spawn_thread(&vib.pt, &VIB_thread, NULL); vib.initialized = 1; } void VIB_quit(void) @@ -4026,7 +4041,7 @@ void PWR_init(void) PWR_updateBatteryStatus(); - pthread_create(&pwr.battery_pt, NULL, &PWR_monitorBattery, &pwr); + spawn_thread(&pwr.battery_pt, &PWR_monitorBattery, &pwr); LOG_info("PWR_init complete\n"); } void PWR_quit(void) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index b3e156eda..678dea76c 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -1,3 +1,4 @@ +#include #include #include @@ -139,6 +140,11 @@ int main(int argc , char* argv[]) { if(argc < 2) return EXIT_FAILURE; + // keep malloc arenas and thread stacks out of the address range dynarec cores + // need for their JIT cache (must happen before any thread is created) + mallopt(M_ARENA_MAX, 2); + SDL_SetHint(SDL_HINT_THREAD_STACK_SIZE, "1048576"); + PWR_setCPUSpeed(CPU_SPEED_PERFORMANCE); // start in performance mode for fast loading PWR_pinToCores(CPU_CORE_PERFORMANCE); // thread affinity From f48a01e554cfb16965e0084ba6f15f241c0a2e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Pommel?= Date: Mon, 17 Aug 2026 19:28:04 +0200 Subject: [PATCH 2/3] fix: guard glibc extensions with __GLIBC__ --- workspace/all/minarch/minarch.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index 678dea76c..f89532fe9 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -1,6 +1,8 @@ -#include #include #include +#ifdef __GLIBC__ +#include +#endif #include @@ -142,7 +144,9 @@ int main(int argc , char* argv[]) { // keep malloc arenas and thread stacks out of the address range dynarec cores // need for their JIT cache (must happen before any thread is created) - mallopt(M_ARENA_MAX, 2); +#ifdef __GLIBC__ + mallopt(M_ARENA_MAX, 2); // glibc extension +#endif SDL_SetHint(SDL_HINT_THREAD_STACK_SIZE, "1048576"); PWR_setCPUSpeed(CPU_SPEED_PERFORMANCE); // start in performance mode for fast loading From c1f366b67328082dd0d6478995ac9ba749015933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Pommel?= Date: Tue, 18 Aug 2026 21:58:05 +0200 Subject: [PATCH 3/3] Reference upstream and NextUI issues --- workspace/all/common/api.c | 1 + workspace/all/minarch/minarch.c | 1 + 2 files changed, 2 insertions(+) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 91c6169d9..35be15bc4 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -3861,6 +3861,7 @@ int PAD_tappedSelect(uint32_t now) /////////////////////////////// // the RLIMIT_STACK default (8MB per thread) wastes address space +// workaround for libretro/gpsp#248 and NextUI#814 #define THREAD_STACK_SIZE (1024 * 1024) static int spawn_thread(pthread_t *pt, void *(*fn)(void *), void *arg) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index f89532fe9..fd6afb977 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -144,6 +144,7 @@ int main(int argc , char* argv[]) { // keep malloc arenas and thread stacks out of the address range dynarec cores // need for their JIT cache (must happen before any thread is created) + // workaround for libretro/gpsp#248 and NextUI#814 #ifdef __GLIBC__ mallopt(M_ARENA_MAX, 2); // glibc extension #endif