Use native mutexes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c
index 6584fb2..f918537 100644
--- a/src/thread/vita/SDL_sysmutex.c
+++ b/src/thread/vita/SDL_sysmutex.c
@@ -22,17 +22,15 @@
#if SDL_THREAD_VITA
-/* An implementation of mutexes using semaphores */
-
#include "SDL_thread.h"
#include "SDL_systhread_c.h"
+#include <psp2/kernel/threadmgr.h>
+#include <psp2/kernel/error.h>
struct SDL_mutex
{
- int recursive;
- SDL_threadID owner;
- SDL_sem *sem;
+ SceUID uid;
};
/* Create a mutex */
@@ -44,13 +42,16 @@ SDL_CreateMutex(void)
/* 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;
+
+ mutex->uid = sceKernelCreateMutex("SDL mutex",
+ SCE_KERNEL_MUTEX_ATTR_TH_PRIO | SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
+ 0,
+ NULL
+ );
+
+ if (mutex->uid <= 0) {
+ printf("Error creating mutex: %x\n", mutex->uid);
+ SDL_OutOfMemory(); // TODO: proper error
}
} else {
SDL_OutOfMemory();
@@ -63,37 +64,56 @@ void
SDL_DestroyMutex(SDL_mutex * mutex)
{
if (mutex) {
- if (mutex->sem) {
- SDL_DestroySemaphore(mutex->sem);
- }
+ sceKernelDeleteMutex(mutex->uid);
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 = 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
+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 = sceKernelLockMutex(mutex->uid, 1, NULL);
+ if (res != SCE_KERNEL_OK) {
+ return SDL_SetError("Error trying to lock mutex: %x", res);
}
return 0;
@@ -107,26 +127,17 @@ 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 = sceKernelUnlockMutex(mutex->uid, 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 */
}