Use native mutexes

This commit is contained in:
Ivan Epifanov 2021-01-20 23:33:28 +03:00 committed by Sam Lantinga
parent 7423ae1ac7
commit 87a118b6b6

View file

@ -22,17 +22,15 @@
#if SDL_THREAD_VITA #if SDL_THREAD_VITA
/* An implementation of mutexes using semaphores */
#include "SDL_thread.h" #include "SDL_thread.h"
#include "SDL_systhread_c.h" #include "SDL_systhread_c.h"
#include <psp2/kernel/threadmgr.h>
#include <psp2/kernel/error.h>
struct SDL_mutex struct SDL_mutex
{ {
int recursive; SceUID uid;
SDL_threadID owner;
SDL_sem *sem;
}; };
/* Create a mutex */ /* Create a mutex */
@ -44,13 +42,16 @@ SDL_CreateMutex(void)
/* Allocate mutex memory */ /* Allocate mutex memory */
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex)); mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
if (mutex) { if (mutex) {
/* Create the mutex semaphore, with initial value 1 */
mutex->sem = SDL_CreateSemaphore(1); mutex->uid = sceKernelCreateMutex("SDL mutex",
mutex->recursive = 0; SCE_KERNEL_MUTEX_ATTR_TH_PRIO | SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
mutex->owner = 0; 0,
if (!mutex->sem) { NULL
SDL_free(mutex); );
mutex = NULL;
if (mutex->uid <= 0) {
printf("Error creating mutex: %x\n", mutex->uid);
SDL_OutOfMemory(); // TODO: proper error
} }
} else { } else {
SDL_OutOfMemory(); SDL_OutOfMemory();
@ -63,37 +64,56 @@ void
SDL_DestroyMutex(SDL_mutex * mutex) SDL_DestroyMutex(SDL_mutex * mutex)
{ {
if (mutex) { if (mutex) {
if (mutex->sem) { sceKernelDeleteMutex(mutex->uid);
SDL_DestroySemaphore(mutex->sem);
}
SDL_free(mutex); SDL_free(mutex);
} }
} }
/* Lock the semaphore */ /* Try to lock the mutex */
int
SDL_TryLockMutex(SDL_mutex * mutex)
{
#if SDL_THREADS_DISABLED
return 0;
#else
SceInt32 res = 0;
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
res = sceKernelTryLockMutex(mutex->uid, 1);
switch (res) {
case SCE_KERNEL_OK:
return 0;
break;
case SCE_KERNEL_ERROR_MUTEX_FAILED_TO_OWN:
return SDL_MUTEX_TIMEDOUT;
break;
default:
return SDL_SetError("Error trying to lock mutex: %x", res);
break;
}
return -1;
#endif /* SDL_THREADS_DISABLED */
}
/* Lock the mutex */
int int
SDL_mutexP(SDL_mutex * mutex) SDL_mutexP(SDL_mutex * mutex)
{ {
#if SDL_THREADS_DISABLED #if SDL_THREADS_DISABLED
return 0; return 0;
#else #else
SDL_threadID this_thread; SceInt32 res = 0;
if (mutex == NULL) { if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex"); return SDL_SetError("Passed a NULL mutex");
} }
this_thread = SDL_ThreadID(); res = sceKernelLockMutex(mutex->uid, 1, NULL);
if (mutex->owner == this_thread) { if (res != SCE_KERNEL_OK) {
++mutex->recursive; return SDL_SetError("Error trying to lock mutex: %x", res);
} else {
/* The order of operations is important.
We set the locking thread id after we obtain the lock
so unlocks from other threads will fail.
*/
SDL_SemWait(mutex->sem);
mutex->owner = this_thread;
mutex->recursive = 0;
} }
return 0; return 0;
@ -107,26 +127,17 @@ SDL_mutexV(SDL_mutex * mutex)
#if SDL_THREADS_DISABLED #if SDL_THREADS_DISABLED
return 0; return 0;
#else #else
SceInt32 res = 0;
if (mutex == NULL) { if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex"); return SDL_SetError("Passed a NULL mutex");
} }
/* If we don't own the mutex, we can't unlock it */ res = sceKernelUnlockMutex(mutex->uid, 1);
if (SDL_ThreadID() != mutex->owner) { if (res != 0) {
return SDL_SetError("mutex not owned by this thread"); return SDL_SetError("Error trying to unlock mutex: %x", res);
} }
if (mutex->recursive) {
--mutex->recursive;
} else {
/* The order of operations is important.
First reset the owner so another thread doesn't lock
the mutex and set the ownership before we reset it,
then release the lock semaphore.
*/
mutex->owner = 0;
SDL_SemPost(mutex->sem);
}
return 0; return 0;
#endif /* SDL_THREADS_DISABLED */ #endif /* SDL_THREADS_DISABLED */
} }