#include "SDL_internal.h"
#include <errno.h>
#include <pthread.h>
#include "SDL_sysmutex_c.h"
SDL_Mutex *SDL_CreateMutex(void)
{
SDL_Mutex *mutex;
pthread_mutexattr_t attr;
mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
if (mutex) {
pthread_mutexattr_init(&attr);
#ifdef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#elif defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP)
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
#else
#endif
if (pthread_mutex_init(&mutex->id, &attr) != 0) {
SDL_SetError("pthread_mutex_init() failed");
SDL_free(mutex);
mutex = NULL;
}
pthread_mutexattr_destroy(&attr);
}
return mutex;
}
void SDL_DestroyMutex(SDL_Mutex *mutex)
{
if (mutex) {
pthread_mutex_destroy(&mutex->id);
SDL_free(mutex);
}
}
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS {
if (mutex) {
#ifdef FAKE_RECURSIVE_MUTEX
pthread_t this_thread = pthread_self();
if (mutex->owner == this_thread) {
++mutex->recursive;
} else {
const int rc = pthread_mutex_lock(&mutex->id);
SDL_assert(rc == 0); mutex->owner = this_thread;
mutex->recursive = 0;
}
#else
const int rc = pthread_mutex_lock(&mutex->id);
SDL_assert(rc == 0); #endif
}
}
bool SDL_TryLockMutex(SDL_Mutex *mutex)
{
bool result = true;
if (mutex) {
#ifdef FAKE_RECURSIVE_MUTEX
pthread_t this_thread = pthread_self();
if (mutex->owner == this_thread) {
++mutex->recursive;
} else {
const int rc = pthread_mutex_trylock(&mutex->id);
if (rc == 0) {
mutex->owner = this_thread;
mutex->recursive = 0;
} else if (rc == EBUSY) {
result = false;
} else {
SDL_assert(!"Error trying to lock mutex"); result = false;
}
}
#else
const int rc = pthread_mutex_trylock(&mutex->id);
if (rc != 0) {
if (rc == EBUSY) {
result = false;
} else {
SDL_assert(!"Error trying to lock mutex"); result = false;
}
}
#endif
}
return result;
}
void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS {
if (mutex) {
#ifdef FAKE_RECURSIVE_MUTEX
if (pthread_self() == mutex->owner) {
if (mutex->recursive) {
--mutex->recursive;
} else {
mutex->owner = 0;
pthread_mutex_unlock(&mutex->id);
}
} else {
SDL_SetError("mutex not owned by this thread");
return;
}
#else
const int rc = pthread_mutex_unlock(&mutex->id);
SDL_assert(rc == 0); #endif }
}