mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-11-11 21:08:40 +00:00
thread: Locking mutexes and rwlocks are now void functions.
Almost nothing checks these return values, and there's no reason a valid lock should fail to operate. The cases where a lock isn't valid (it's a bogus pointer, it was previously destroyed, a thread is unlocking a lock it doesn't own, etc) are undefined behavior and always were, and should be treated as an application bug. Reference Issue #8096.
This commit is contained in:
@@ -30,7 +30,7 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||
SDL_Mutex *mutex;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
/* Allocate the structure */
|
||||
// Allocate the structure
|
||||
mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
|
||||
if (mutex) {
|
||||
pthread_mutexattr_init(&attr);
|
||||
@@ -39,7 +39,7 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||
#elif defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP)
|
||||
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
#else
|
||||
/* No extra attributes necessary */
|
||||
// No extra attributes necessary
|
||||
#endif
|
||||
if (pthread_mutex_init(&mutex->id, &attr) != 0) {
|
||||
SDL_SetError("pthread_mutex_init() failed");
|
||||
@@ -60,116 +60,96 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
||||
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||
{
|
||||
if (mutex != NULL) {
|
||||
#ifdef FAKE_RECURSIVE_MUTEX
|
||||
pthread_t this_thread;
|
||||
#endif
|
||||
|
||||
if (mutex == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAKE_RECURSIVE_MUTEX
|
||||
this_thread = pthread_self();
|
||||
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.
|
||||
*/
|
||||
if (pthread_mutex_lock(&mutex->id) == 0) {
|
||||
pthread_t this_thread = pthread_self();
|
||||
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.
|
||||
*/
|
||||
const int rc = pthread_mutex_lock(&mutex->id);
|
||||
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||
mutex->owner = this_thread;
|
||||
mutex->recursive = 0;
|
||||
} else {
|
||||
return SDL_SetError("pthread_mutex_lock() failed");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (pthread_mutex_lock(&mutex->id) != 0) {
|
||||
return SDL_SetError("pthread_mutex_lock() failed");
|
||||
}
|
||||
const int rc = pthread_mutex_lock(&mutex->id);
|
||||
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||
{
|
||||
int retval;
|
||||
int result;
|
||||
#ifdef FAKE_RECURSIVE_MUTEX
|
||||
pthread_t this_thread;
|
||||
#endif
|
||||
int retval = 0;
|
||||
|
||||
if (mutex == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
if (mutex != NULL) {
|
||||
#ifdef FAKE_RECURSIVE_MUTEX
|
||||
this_thread = pthread_self();
|
||||
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.
|
||||
*/
|
||||
result = pthread_mutex_trylock(&mutex->id);
|
||||
if (result == 0) {
|
||||
mutex->owner = this_thread;
|
||||
mutex->recursive = 0;
|
||||
} else if (result == EBUSY) {
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
pthread_t this_thread = pthread_self();
|
||||
if (mutex->owner == this_thread) {
|
||||
++mutex->recursive;
|
||||
} else {
|
||||
retval = SDL_SetError("pthread_mutex_trylock() failed");
|
||||
/* The order of operations is important.
|
||||
We set the locking thread id after we obtain the lock
|
||||
so unlocks from other threads will fail.
|
||||
*/
|
||||
const int result = pthread_mutex_trylock(&mutex->id);
|
||||
if (result == 0) {
|
||||
mutex->owner = this_thread;
|
||||
mutex->recursive = 0;
|
||||
} else if (result == EBUSY) {
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
} else {
|
||||
SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
result = pthread_mutex_trylock(&mutex->id);
|
||||
if (result != 0) {
|
||||
if (result == EBUSY) {
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
} else {
|
||||
retval = SDL_SetError("pthread_mutex_trylock() failed");
|
||||
const int result = pthread_mutex_trylock(&mutex->id);
|
||||
if (result != 0) {
|
||||
if (result == EBUSY) {
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
} else {
|
||||
SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
||||
void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||
{
|
||||
if (mutex == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mutex != NULL) {
|
||||
#ifdef FAKE_RECURSIVE_MUTEX
|
||||
/* We can only unlock the mutex if we own it */
|
||||
if (pthread_self() == mutex->owner) {
|
||||
if (mutex->recursive) {
|
||||
--mutex->recursive;
|
||||
// We can only unlock the mutex if we own it
|
||||
if (pthread_self() == mutex->owner) {
|
||||
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;
|
||||
pthread_mutex_unlock(&mutex->id);
|
||||
}
|
||||
} 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;
|
||||
pthread_mutex_unlock(&mutex->id);
|
||||
return SDL_SetError("mutex not owned by this thread");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("mutex not owned by this thread");
|
||||
}
|
||||
|
||||
#else
|
||||
if (pthread_mutex_unlock(&mutex->id) != 0) {
|
||||
return SDL_SetError("pthread_mutex_unlock() failed");
|
||||
const int rc = pthread_mutex_unlock(&mutex->id);
|
||||
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||
#endif // FAKE_RECURSIVE_MUTEX
|
||||
}
|
||||
#endif /* FAKE_RECURSIVE_MUTEX */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,42 +55,36 @@ void SDL_DestroyRWLock(SDL_RWLock *rwlock)
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
||||
void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||
{
|
||||
if (rwlock == NULL) {
|
||||
return SDL_InvalidParamError("rwlock");
|
||||
} else if (pthread_rwlock_rdlock(&rwlock->id) != 0) {
|
||||
return SDL_SetError("pthread_rwlock_rdlock() failed");
|
||||
if (rwlock) {
|
||||
const int rc = pthread_rwlock_rdlock(&rwlock->id);
|
||||
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
||||
void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||
{
|
||||
if (rwlock == NULL) {
|
||||
return SDL_InvalidParamError("rwlock");
|
||||
} else if (pthread_rwlock_wrlock(&rwlock->id) != 0) {
|
||||
return SDL_SetError("pthread_rwlock_wrlock() failed");
|
||||
if (rwlock) {
|
||||
const int rc = pthread_rwlock_wrlock(&rwlock->id);
|
||||
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (rwlock == NULL) {
|
||||
retval = SDL_InvalidParamError("rwlock");
|
||||
} else {
|
||||
if (rwlock) {
|
||||
const int result = pthread_rwlock_tryrdlock(&rwlock->id);
|
||||
if (result != 0) {
|
||||
if (result == EBUSY) {
|
||||
retval = SDL_RWLOCK_TIMEDOUT;
|
||||
} else {
|
||||
retval = SDL_SetError("pthread_rwlock_tryrdlock() failed");
|
||||
retval = SDL_RWLOCK_TIMEDOUT;
|
||||
if (result != EBUSY) {
|
||||
SDL_assert(!"Error trying to lock rwlock for reading"); // assume we're in a lot of trouble if this assert fails.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -98,15 +92,12 @@ int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (rwlock == NULL) {
|
||||
retval = SDL_InvalidParamError("rwlock");
|
||||
} else {
|
||||
if (rwlock) {
|
||||
const int result = pthread_rwlock_trywrlock(&rwlock->id);
|
||||
if (result != 0) {
|
||||
if (result == EBUSY) {
|
||||
retval = SDL_RWLOCK_TIMEDOUT;
|
||||
} else {
|
||||
retval = SDL_SetError("pthread_rwlock_tryrdlock() failed");
|
||||
retval = SDL_RWLOCK_TIMEDOUT;
|
||||
if (result != EBUSY) {
|
||||
SDL_assert(!"Error trying to lock rwlock for writing"); // assume we're in a lot of trouble if this assert fails.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,13 +105,11 @@ int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
||||
void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||
{
|
||||
if (rwlock == NULL) {
|
||||
return SDL_InvalidParamError("rwlock");
|
||||
} else if (pthread_rwlock_unlock(&rwlock->id) != 0) {
|
||||
return SDL_SetError("pthread_rwlock_unlock() failed");
|
||||
if (rwlock) {
|
||||
const int rc = pthread_rwlock_unlock(&rwlock->id);
|
||||
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user