SDL: Use lightweight mutex

From 996f30b0e408affee7dc3aa8132fe5e80d99fd81 Mon Sep 17 00:00:00 2001
From: Francisco Javier Trujillo Mata <[EMAIL REDACTED]>
Date: Tue, 23 Nov 2021 15:27:41 +0100
Subject: [PATCH] Use lightweight mutex

---
 src/thread/psp/SDL_sysmutex.c | 102 ++++++++++++++++++++--------------
 1 file changed, 59 insertions(+), 43 deletions(-)

diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c
index 2f401077ca4..69c44d0d661 100644
--- a/src/thread/psp/SDL_sysmutex.c
+++ b/src/thread/psp/SDL_sysmutex.c
@@ -27,30 +27,37 @@
 #include "SDL_thread.h"
 #include "SDL_systhread_c.h"
 
+#include <pspthreadman.h>
+#include <pspkerror.h>
+
+#define SCE_KERNEL_MUTEX_ATTR_RECURSIVE 0x0200U
 
 struct SDL_mutex
 {
-    int recursive;
-    SDL_threadID owner;
-    SDL_sem *sem;
+    SceLwMutexWorkarea lock;
 };
 
 /* Create a mutex */
 SDL_mutex *
 SDL_CreateMutex(void)
 {
-    SDL_mutex *mutex;
+    SDL_mutex *mutex = NULL;
+    SceInt32 res = 0;
 
     /* Allocate mutex memory */
     mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
     if (mutex) {
-        /* Create the mutex semaphore, with initial value 1 */
-        mutex->sem = SDL_CreateSemaphore(1);
-        mutex->recursive = 0;
-        mutex->owner = 0;
-        if (!mutex->sem) {
-            SDL_free(mutex);
-            mutex = NULL;
+
+        res = sceKernelCreateLwMutex(
+            &mutex->lock,
+            "SDL mutex",
+            SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
+            0,
+            NULL
+        );
+
+        if (res < 0) {
+            SDL_SetError("Error trying to create mutex: %x", res);
         }
     } else {
         SDL_OutOfMemory();
@@ -63,37 +70,56 @@ void
 SDL_DestroyMutex(SDL_mutex * mutex)
 {
     if (mutex) {
-        if (mutex->sem) {
-            SDL_DestroySemaphore(mutex->sem);
-        }
+        sceKernelDeleteLwMutex(&mutex->lock);
         SDL_free(mutex);
     }
 }
 
-/* Lock the semaphore */
+/* Try to lock the mutex */
 int
-SDL_mutexP(SDL_mutex * mutex)
+SDL_TryLockMutex(SDL_mutex * mutex)
 {
 #if SDL_THREADS_DISABLED
     return 0;
 #else
-    SDL_threadID this_thread;
+    SceInt32 res = 0;
+    if (mutex == NULL) {
+        return SDL_SetError("Passed a NULL mutex");
+    }
+
+    res = sceKernelTryLockLwMutex(&mutex->lock, 1);
+    switch (res) {
+        case SCE_KERNEL_ERROR_OK:
+            return 0;
+            break;
+        case SCE_KERNEL_ERROR_WAIT_TIMEOUT:
+            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
+SDL_mutexP(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+    return 0;
+#else
+    SceInt32 res = 0;
     if (mutex == NULL) {
         return SDL_SetError("Passed a NULL mutex");
     }
 
-    this_thread = SDL_ThreadID();
-    if (mutex->owner == this_thread) {
-        ++mutex->recursive;
-    } 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;
+    res = sceKernelLockLwMutex(&mutex->lock, 1, NULL);
+    if (res != SCE_KERNEL_ERROR_OK) {
+        return SDL_SetError("Error trying to lock mutex: %x", res);
     }
 
     return 0;
@@ -107,30 +133,20 @@ SDL_mutexV(SDL_mutex * mutex)
 #if SDL_THREADS_DISABLED
     return 0;
 #else
+    SceInt32 res = 0;
+
     if (mutex == NULL) {
         return SDL_SetError("Passed a NULL mutex");
     }
 
-    /* If we don't own the mutex, we can't unlock it */
-    if (SDL_ThreadID() != mutex->owner) {
-        return SDL_SetError("mutex not owned by this thread");
+    res = sceKernelUnlockLwMutex(&mutex->lock, 1);
+    if (res != 0) {
+        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;
 #endif /* SDL_THREADS_DISABLED */
 }
-
 #endif /* SDL_THREAD_PSP */
 
 /* vi: set ts=4 sw=4 expandtab: */