Add a PS Vita optimized threading backend.

This addresses an issue where condition variables would throw the
following error:

  _sceKernelWaitSema returned SCE_KERNEL_ERROR_WAIT_TIMEOUT (0x80028005)

Bypassing the pthread backend and using Vita APIs directly addresses
this and should be more optimal.
This commit is contained in:
David Reid
2026-02-28 19:53:38 +10:00
parent 69396f97a7
commit e552fd20cf
+311 -15
View File
@@ -4782,7 +4782,9 @@ typedef enum
} ma_thread_priority;
#ifndef MA_NO_THREADING
#if defined(MA_POSIX)
#if defined(MA_VITA)
#define MA_THREADING_BACKEND_VITA
#elif defined(MA_POSIX)
#define MA_THREADING_BACKEND_POSIX
#elif defined(MA_WIN32)
#define MA_THREADING_BACKEND_WIN32
@@ -4797,6 +4799,8 @@ typedef enum
typedef ma_pthread_t ma_thread;
#elif defined(MA_THREADING_BACKEND_WIN32)
typedef ma_handle ma_thread;
#elif defined(MA_THREADING_BACKEND_VITA)
typedef int ma_thread;
#else
typedef int ma_thread; /* Fallback for platforms without support for threading. Attempting to create a thread will fail. */
#endif
@@ -4805,6 +4809,8 @@ typedef enum
typedef ma_pthread_mutex_t ma_mutex;
#elif defined(MA_THREADING_BACKEND_WIN32)
typedef ma_handle ma_mutex;
#elif defined(MA_THREADING_BACKEND_VITA)
typedef int ma_mutex;
#else
typedef ma_spinlock ma_mutex; /* Fallback for platforms without support for threading. */
#endif
@@ -4818,6 +4824,8 @@ typedef enum
} ma_event;
#elif defined(MA_THREADING_BACKEND_WIN32)
typedef ma_handle ma_event;
#elif defined(MA_THREADING_BACKEND_VITA)
typedef int ma_event;
#else
typedef ma_uint32 ma_event; /* Fallback for platforms without support for threading. */
#endif
@@ -4831,6 +4839,8 @@ typedef enum
} ma_semaphore;
#elif defined(MA_THREADING_BACKEND_WIN32)
typedef ma_handle ma_semaphore;
#elif defined(MA_THREADING_BACKEND_VITA)
typedef int ma_semaphore;
#else
typedef ma_uint32 ma_semaphore; /* Fallback for platforms without support for threading. */
#endif
@@ -18358,6 +18368,264 @@ static ma_result ma_semaphore_release__win32(ma_semaphore* pSemaphore)
return MA_SUCCESS;
}
#elif defined(MA_THREADING_BACKEND_VITA)
#include <psp2/kernel/threadmgr/thread.h>
#include <psp2/kernel/threadmgr/mutex.h>
#include <psp2/kernel/threadmgr/eventflag.h>
#include <psp2/kernel/threadmgr/semaphore.h>
typedef struct
{
ma_thread_entry_proc entryProc;
void* pData;
} ma_vita_thread_proxy_data;
static int ma_vita_thread_proxy(SceSize dataSize, void* pData)
{
ma_vita_thread_proxy_data* pProxyData = (ma_vita_thread_proxy_data*)pData;
(void)dataSize;
return (int)pProxyData->entryProc(pProxyData->pData);
}
static ma_result ma_thread_create__vita(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
{
int thd;
const char* pNameBase = "ma_thd_";
size_t nameBaseLen = strlen(pNameBase);
char name[64];
static ma_uint32 counter = 0; /* For creating a unique name. Atomically incremented. */
ma_vita_thread_proxy_data data;
int initPriority;
if (pThread == NULL) {
return MA_INVALID_ARGS;
}
ma_strcpy_s(name, sizeof(name), pNameBase);
ma_itoa_s((int)ma_atomic_fetch_add_explicit_32(&counter, 1, ma_atomic_memory_order_relaxed), name + nameBaseLen, sizeof(name) - nameBaseLen, 10);
/* TODO: Not sure how properly set the priority. */
(void)priority;
initPriority = 0x10000100; /* This is the value used in the Vita SDK documentation for sceKernelCreateThread(). I'm not quite sure how to properly use this. */
/* Make sure we have an appropriate default stack size. */
if (stackSize == 0) {
stackSize = 0x10000;
}
thd = sceKernelCreateThread(name, ma_vita_thread_proxy, 0x10000100, (SceSize)stackSize, 0, 0, NULL);
if (thd < 0) {
return MA_ERROR;
}
data.entryProc = entryProc;
data.pData = pData;
sceKernelStartThread(thd, sizeof(data), &data);
*pThread = thd;
return MA_SUCCESS;
}
static void ma_thread_wait__vita(ma_thread* pThread)
{
if (pThread == NULL) {
return;
}
sceKernelWaitThreadEnd(*pThread, NULL, NULL);
sceKernelDeleteThread(*pThread);
}
static ma_result ma_mutex_init__vita(ma_mutex* pMutex)
{
int mtx;
const char* pNameBase = "ma_mtx_";
size_t nameBaseLen = strlen(pNameBase);
char name[64];
static ma_uint32 counter = 0; /* For creating a unique name. Atomically incremented. */
if (pMutex == NULL) {
return MA_INVALID_ARGS;
}
ma_strcpy_s(name, sizeof(name), pNameBase);
ma_itoa_s((int)ma_atomic_fetch_add_explicit_32(&counter, 1, ma_atomic_memory_order_relaxed), name + nameBaseLen, sizeof(name) - nameBaseLen, 10);
mtx = sceKernelCreateMutex(name, 0, 0, NULL);
if (mtx < 0) {
return MA_ERROR;
}
*pMutex = mtx;
return MA_SUCCESS;
}
static void ma_mutex_uninit__vita(ma_mutex* pMutex)
{
if (pMutex == NULL) {
return;
}
sceKernelDeleteMutex(*pMutex);
}
static void ma_mutex_lock__vita(ma_mutex* pMutex)
{
if (pMutex == NULL) {
return;
}
sceKernelLockMutex(*pMutex, 1, NULL);
}
static void ma_mutex_unlock__vita(ma_mutex* pMutex)
{
if (pMutex == NULL) {
return;
}
sceKernelUnlockMutex(*pMutex, 1);
}
static ma_result ma_event_init__vita(ma_event* pEvent)
{
int e;
const char* pNameBase = "ma_evt_";
size_t nameBaseLen = strlen(pNameBase);
char name[64];
static ma_uint32 counter = 0; /* For creating a unique name. Atomically incremented. */
if (pEvent == NULL) {
return MA_INVALID_ARGS;
}
ma_strcpy_s(name, sizeof(name), pNameBase);
ma_itoa_s((int)ma_atomic_fetch_add_explicit_32(&counter, 1, ma_atomic_memory_order_relaxed), name + nameBaseLen, sizeof(name) - nameBaseLen, 10);
e = sceKernelCreateEventFlag(name, SCE_EVENT_WAITMULTIPLE, 0, NULL);
if (e < 0) {
return MA_ERROR;
}
*pEvent = e;
return MA_SUCCESS;
}
static void ma_event_uninit__vita(ma_event* pEvent)
{
if (pEvent == NULL) {
return;
}
sceKernelDeleteEventFlag(*pEvent);
}
static ma_result ma_event_wait__vita(ma_event* pEvent)
{
unsigned int bits;
int result;
if (pEvent == NULL) {
return MA_INVALID_ARGS;
}
result = sceKernelWaitEventFlag(*pEvent, 1, SCE_EVENT_WAITAND | SCE_EVENT_WAITCLEAR, &bits, NULL);
if (result < 0) {
return MA_ERROR;
}
return MA_SUCCESS;
}
static ma_result ma_event_signal__vita(ma_event* pEvent)
{
int result;
if (pEvent == NULL) {
return MA_INVALID_ARGS;
}
result = sceKernelSetEventFlag(*pEvent, 1);
if (result < 0) {
return MA_ERROR;
}
return MA_SUCCESS;
}
static ma_result ma_semaphore_init__vita(int initialValue, ma_semaphore* pSemaphore)
{
int sem;
const char* pNameBase = "ma_sem_";
size_t nameBaseLen = strlen(pNameBase);
char name[64];
static ma_uint32 counter = 0; /* For creating a unique name. Atomically incremented. */
if (pSemaphore == NULL) {
return MA_INVALID_ARGS;
}
ma_strcpy_s(name, sizeof(name), pNameBase);
ma_itoa_s((int)ma_atomic_fetch_add_explicit_32(&counter, 1, ma_atomic_memory_order_relaxed), name + nameBaseLen, sizeof(name) - nameBaseLen, 10);
sem = sceKernelCreateSema(name, 0, initialValue, 0x7FFFFFFF, NULL);
if (sem < 0) {
return MA_ERROR;
}
*pSemaphore = sem;
return MA_SUCCESS;
}
static void ma_semaphore_uninit__vita(ma_semaphore* pSemaphore)
{
if (pSemaphore == NULL) {
return;
}
sceKernelDeleteSema(*pSemaphore);
}
static ma_result ma_semaphore_wait__vita(ma_semaphore* pSemaphore)
{
int result;
if (pSemaphore == NULL) {
return MA_INVALID_ARGS;
}
result = sceKernelWaitSema(*pSemaphore, 1, NULL);
if (result < 0) {
return MA_ERROR;
}
return MA_SUCCESS;
}
static ma_result ma_semaphore_release__vita(ma_semaphore* pSemaphore)
{
int result;
if (pSemaphore == NULL) {
return MA_INVALID_ARGS;
}
result = sceKernelSignalSema(*pSemaphore, 1);
if (result < 0) {
return MA_ERROR;
}
return MA_SUCCESS;
}
#else
static ma_result ma_thread_create__none(ma_thread* pThread, ma_thread_priority priority, size_t stackSize, ma_thread_entry_proc entryProc, void* pData)
{
@@ -18536,7 +18804,9 @@ MA_API ma_result ma_thread_create(ma_thread* pThread, ma_thread_priority priorit
pProxyData->pData = pData;
ma_allocation_callbacks_init_copy(&pProxyData->allocationCallbacks, pAllocationCallbacks);
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
result = ma_thread_create__vita(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
#elif defined(MA_THREADING_BACKEND_POSIX)
result = ma_thread_create__posix(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
#elif defined(MA_THREADING_BACKEND_WIN32)
result = ma_thread_create__win32(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
@@ -18558,7 +18828,9 @@ MA_API void ma_thread_wait(ma_thread* pThread)
return;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
ma_thread_wait__vita(pThread);
#elif defined(MA_THREADING_BACKEND_POSIX)
ma_thread_wait__posix(pThread);
#elif defined(MA_THREADING_BACKEND_WIN32)
ma_thread_wait__win32(pThread);
@@ -18575,7 +18847,9 @@ MA_API ma_result ma_mutex_init(ma_mutex* pMutex)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_mutex_init__vita(pMutex);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_mutex_init__posix(pMutex);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_mutex_init__win32(pMutex);
@@ -18590,7 +18864,9 @@ MA_API void ma_mutex_uninit(ma_mutex* pMutex)
return;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
ma_mutex_uninit__vita(pMutex);
#elif defined(MA_THREADING_BACKEND_POSIX)
ma_mutex_uninit__posix(pMutex);
#elif defined(MA_THREADING_BACKEND_WIN32)
ma_mutex_uninit__win32(pMutex);
@@ -18606,7 +18882,9 @@ MA_API void ma_mutex_lock(ma_mutex* pMutex)
return;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
ma_mutex_lock__vita(pMutex);
#elif defined(MA_THREADING_BACKEND_POSIX)
ma_mutex_lock__posix(pMutex);
#elif defined(MA_THREADING_BACKEND_WIN32)
ma_mutex_lock__win32(pMutex);
@@ -18622,7 +18900,9 @@ MA_API void ma_mutex_unlock(ma_mutex* pMutex)
return;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
ma_mutex_unlock__vita(pMutex);
#elif defined(MA_THREADING_BACKEND_POSIX)
ma_mutex_unlock__posix(pMutex);
#elif defined(MA_THREADING_BACKEND_WIN32)
ma_mutex_unlock__win32(pMutex);
@@ -18639,7 +18919,9 @@ MA_API ma_result ma_event_init(ma_event* pEvent)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_event_init__vita(pEvent);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_event_init__posix(pEvent);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_event_init__win32(pEvent);
@@ -18682,7 +18964,9 @@ MA_API void ma_event_uninit(ma_event* pEvent)
return;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
ma_event_uninit__vita(pEvent);
#elif defined(MA_THREADING_BACKEND_POSIX)
ma_event_uninit__posix(pEvent);
#elif defined(MA_THREADING_BACKEND_WIN32)
ma_event_uninit__win32(pEvent);
@@ -18710,7 +18994,9 @@ MA_API ma_result ma_event_wait(ma_event* pEvent)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_event_wait__vita(pEvent);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_event_wait__posix(pEvent);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_event_wait__win32(pEvent);
@@ -18726,7 +19012,9 @@ MA_API ma_result ma_event_signal(ma_event* pEvent)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_event_signal__vita(pEvent);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_event_signal__posix(pEvent);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_event_signal__win32(pEvent);
@@ -18743,7 +19031,9 @@ MA_API ma_result ma_semaphore_init(int initialValue, ma_semaphore* pSemaphore)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_semaphore_init__vita(initialValue, pSemaphore);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_semaphore_init__posix(initialValue, pSemaphore);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_semaphore_init__win32(initialValue, pSemaphore);
@@ -18759,7 +19049,9 @@ MA_API void ma_semaphore_uninit(ma_semaphore* pSemaphore)
return;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
ma_semaphore_uninit__vita(pSemaphore);
#elif defined(MA_THREADING_BACKEND_POSIX)
ma_semaphore_uninit__posix(pSemaphore);
#elif defined(MA_THREADING_BACKEND_WIN32)
ma_semaphore_uninit__win32(pSemaphore);
@@ -18775,7 +19067,9 @@ MA_API ma_result ma_semaphore_wait(ma_semaphore* pSemaphore)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_semaphore_wait__vita(pSemaphore);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_semaphore_wait__posix(pSemaphore);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_semaphore_wait__win32(pSemaphore);
@@ -18791,7 +19085,9 @@ MA_API ma_result ma_semaphore_release(ma_semaphore* pSemaphore)
return MA_INVALID_ARGS;
}
#if defined(MA_THREADING_BACKEND_POSIX)
#if defined(MA_THREADING_BACKEND_VITA)
return ma_semaphore_release__vita(pSemaphore);
#elif defined(MA_THREADING_BACKEND_POSIX)
return ma_semaphore_release__posix(pSemaphore);
#elif defined(MA_THREADING_BACKEND_WIN32)
return ma_semaphore_release__win32(pSemaphore);