mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-22 12:48:28 +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:
parent
082ef41566
commit
899eb0d042
21 changed files with 496 additions and 746 deletions
|
@ -707,6 +707,8 @@ The following functions have been renamed:
|
||||||
|
|
||||||
## SDL_mutex.h
|
## SDL_mutex.h
|
||||||
|
|
||||||
|
SDL_LockMutex and SDL_UnlockMutex now return void; if the mutex is valid (including being a NULL pointer, which returns immediately), these functions never fail. If the mutex is invalid or the caller does something illegal, like unlock another thread's mutex, this is considered undefined behavior.
|
||||||
|
|
||||||
The following functions have been renamed:
|
The following functions have been renamed:
|
||||||
* SDL_CondBroadcast() => SDL_BroadcastCondition()
|
* SDL_CondBroadcast() => SDL_BroadcastCondition()
|
||||||
* SDL_CondSignal() => SDL_SignalCondition()
|
* SDL_CondSignal() => SDL_SignalCondition()
|
||||||
|
|
|
@ -169,13 +169,15 @@ extern DECLSPEC SDL_Mutex *SDLCALL SDL_CreateMutex(void);
|
||||||
* unlock it the same number of times before it is actually made available for
|
* unlock it the same number of times before it is actually made available for
|
||||||
* other threads in the system (this is known as a "recursive mutex").
|
* other threads in the system (this is known as a "recursive mutex").
|
||||||
*
|
*
|
||||||
|
* This function does not fail; if mutex is NULL, it will return immediately
|
||||||
|
* having locked nothing. If the mutex is valid, this function will always
|
||||||
|
* block until it can lock the mutex, and return with it locked.
|
||||||
|
*
|
||||||
* \param mutex the mutex to lock
|
* \param mutex the mutex to lock
|
||||||
* \returns 0 on success or a negative error code on failure; call
|
|
||||||
* SDL_GetError() for more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex);
|
extern DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to lock a mutex without blocking.
|
* Try to lock a mutex without blocking.
|
||||||
|
@ -186,9 +188,13 @@ extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex);
|
||||||
* This technique is useful if you need exclusive access to a resource but
|
* This technique is useful if you need exclusive access to a resource but
|
||||||
* don't want to wait for it, and will return to it to try again later.
|
* don't want to wait for it, and will return to it to try again later.
|
||||||
*
|
*
|
||||||
|
* This function does not fail; if mutex is NULL, it will return 0 immediately
|
||||||
|
* having locked nothing. If the mutex is valid, this function will always
|
||||||
|
* either lock the mutex and return 0, or return SDL_MUTEX_TIMEOUT and lock
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
* \param mutex the mutex to try to lock
|
* \param mutex the mutex to try to lock
|
||||||
* \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for
|
* \returns 0 or `SDL_MUTEX_TIMEDOUT`
|
||||||
* more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*
|
*
|
||||||
|
@ -210,12 +216,10 @@ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0
|
||||||
* thread, and doing so results in undefined behavior.
|
* thread, and doing so results in undefined behavior.
|
||||||
*
|
*
|
||||||
* \param mutex the mutex to unlock.
|
* \param mutex the mutex to unlock.
|
||||||
* \returns 0 on success or a negative error code on failure; call
|
|
||||||
* SDL_GetError() for more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex);
|
extern DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a mutex created with SDL_CreateMutex().
|
* Destroy a mutex created with SDL_CreateMutex().
|
||||||
|
@ -321,15 +325,17 @@ extern DECLSPEC SDL_RWLock *SDLCALL SDL_CreateRWLock(void);
|
||||||
* lock before requesting a read-only lock. (But, of course, if you have the
|
* lock before requesting a read-only lock. (But, of course, if you have the
|
||||||
* write lock, you don't need further locks to read in any case.)
|
* write lock, you don't need further locks to read in any case.)
|
||||||
*
|
*
|
||||||
|
* This function does not fail; if rwlock is NULL, it will return immediately
|
||||||
|
* having locked nothing. If the rwlock is valid, this function will always
|
||||||
|
* block until it can lock the mutex, and return with it locked.
|
||||||
|
*
|
||||||
* \param rwlock the read/write lock to lock
|
* \param rwlock the read/write lock to lock
|
||||||
* \returns 0 on success or a negative error code on failure; call
|
|
||||||
* SDL_GetError() for more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_UnlockRWLock
|
* \sa SDL_UnlockRWLock
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock);
|
extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock the read/write lock for _write_ operations.
|
* Lock the read/write lock for _write_ operations.
|
||||||
|
@ -348,15 +354,17 @@ extern DECLSPEC int SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQ
|
||||||
* read-only lock. Doing so results in undefined behavior. Unlock the
|
* read-only lock. Doing so results in undefined behavior. Unlock the
|
||||||
* read-only lock before requesting a write lock.
|
* read-only lock before requesting a write lock.
|
||||||
*
|
*
|
||||||
|
* This function does not fail; if rwlock is NULL, it will return immediately
|
||||||
|
* having locked nothing. If the rwlock is valid, this function will always
|
||||||
|
* block until it can lock the mutex, and return with it locked.
|
||||||
|
*
|
||||||
* \param rwlock the read/write lock to lock
|
* \param rwlock the read/write lock to lock
|
||||||
* \returns 0 on success or a negative error code on failure; call
|
|
||||||
* SDL_GetError() for more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*
|
*
|
||||||
* \sa SDL_UnlockRWLock
|
* \sa SDL_UnlockRWLock
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock);
|
extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to lock a read/write lock _for reading_ without blocking.
|
* Try to lock a read/write lock _for reading_ without blocking.
|
||||||
|
@ -370,9 +378,13 @@ extern DECLSPEC int SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQ
|
||||||
* Trying to lock for read-only access can succeed if other threads are
|
* Trying to lock for read-only access can succeed if other threads are
|
||||||
* holding read-only locks, as this won't prevent access.
|
* holding read-only locks, as this won't prevent access.
|
||||||
*
|
*
|
||||||
|
* This function does not fail; if rwlock is NULL, it will return 0 immediately
|
||||||
|
* having locked nothing. If rwlock is valid, this function will always
|
||||||
|
* either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT and lock
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
* \param rwlock the rwlock to try to lock
|
* \param rwlock the rwlock to try to lock
|
||||||
* \returns 0, `SDL_RWLOCK_TIMEDOUT`, or -1 on error; call SDL_GetError() for
|
* \returns 0 or `SDL_RWLOCK_TIMEDOUT`
|
||||||
* more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*
|
*
|
||||||
|
@ -400,9 +412,13 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_
|
||||||
* read-only lock. Doing so results in undefined behavior. Unlock the
|
* read-only lock. Doing so results in undefined behavior. Unlock the
|
||||||
* read-only lock before requesting a write lock.
|
* read-only lock before requesting a write lock.
|
||||||
*
|
*
|
||||||
|
* This function does not fail; if rwlock is NULL, it will return 0 immediately
|
||||||
|
* having locked nothing. If rwlock is valid, this function will always
|
||||||
|
* either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT and lock
|
||||||
|
* nothing.
|
||||||
|
*
|
||||||
* \param rwlock the rwlock to try to lock
|
* \param rwlock the rwlock to try to lock
|
||||||
* \returns 0, `SDL_RWLOCK_TIMEDOUT`, or -1 on error; call SDL_GetError() for
|
* \returns 0 or `SDL_RWLOCK_TIMEDOUT`
|
||||||
* more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*
|
*
|
||||||
|
@ -428,12 +444,10 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_
|
||||||
* thread, and doing so results in undefined behavior.
|
* thread, and doing so results in undefined behavior.
|
||||||
*
|
*
|
||||||
* \param rwlock the rwlock to unlock.
|
* \param rwlock the rwlock to unlock.
|
||||||
* \returns 0 on success or a negative error code on failure; call
|
|
||||||
* SDL_GetError() for more information.
|
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock);
|
extern DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a read/write lock created with SDL_CreateRWLock().
|
* Destroy a read/write lock created with SDL_CreateRWLock().
|
||||||
|
|
|
@ -123,17 +123,16 @@ SDL_PropertiesID SDL_CreateProperties(void)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) {
|
SDL_LockRWLockForWriting(SDL_properties_lock);
|
||||||
|
++SDL_last_properties_id;
|
||||||
|
if (SDL_last_properties_id == 0) {
|
||||||
++SDL_last_properties_id;
|
++SDL_last_properties_id;
|
||||||
if (SDL_last_properties_id == 0) {
|
|
||||||
++SDL_last_properties_id;
|
|
||||||
}
|
|
||||||
props = SDL_last_properties_id;
|
|
||||||
if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) {
|
|
||||||
inserted = SDL_TRUE;
|
|
||||||
}
|
|
||||||
SDL_UnlockRWLock(SDL_properties_lock);
|
|
||||||
}
|
}
|
||||||
|
props = SDL_last_properties_id;
|
||||||
|
if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) {
|
||||||
|
inserted = SDL_TRUE;
|
||||||
|
}
|
||||||
|
SDL_UnlockRWLock(SDL_properties_lock);
|
||||||
|
|
||||||
if (inserted) {
|
if (inserted) {
|
||||||
/* All done! */
|
/* All done! */
|
||||||
|
@ -152,15 +151,17 @@ int SDL_LockProperties(SDL_PropertiesID props)
|
||||||
if (!props) {
|
if (!props) {
|
||||||
return SDL_InvalidParamError("props");
|
return SDL_InvalidParamError("props");
|
||||||
}
|
}
|
||||||
if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) {
|
|
||||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
SDL_LockRWLockForReading(SDL_properties_lock);
|
||||||
SDL_UnlockRWLock(SDL_properties_lock);
|
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||||
}
|
SDL_UnlockRWLock(SDL_properties_lock);
|
||||||
|
|
||||||
if (!properties) {
|
if (!properties) {
|
||||||
SDL_InvalidParamError("props");
|
return SDL_InvalidParamError("props");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return SDL_LockMutex(properties->lock);
|
|
||||||
|
SDL_LockMutex(properties->lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_UnlockProperties(SDL_PropertiesID props)
|
void SDL_UnlockProperties(SDL_PropertiesID props)
|
||||||
|
@ -170,13 +171,15 @@ void SDL_UnlockProperties(SDL_PropertiesID props)
|
||||||
if (!props) {
|
if (!props) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) {
|
|
||||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
SDL_LockRWLockForReading(SDL_properties_lock);
|
||||||
SDL_UnlockRWLock(SDL_properties_lock);
|
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||||
}
|
SDL_UnlockRWLock(SDL_properties_lock);
|
||||||
|
|
||||||
if (!properties) {
|
if (!properties) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockMutex(properties->lock);
|
SDL_UnlockMutex(properties->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,10 +196,10 @@ int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value, void
|
||||||
return SDL_InvalidParamError("name");
|
return SDL_InvalidParamError("name");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) {
|
SDL_LockRWLockForReading(SDL_properties_lock);
|
||||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||||
SDL_UnlockRWLock(SDL_properties_lock);
|
SDL_UnlockRWLock(SDL_properties_lock);
|
||||||
}
|
|
||||||
if (!properties) {
|
if (!properties) {
|
||||||
return SDL_InvalidParamError("props");
|
return SDL_InvalidParamError("props");
|
||||||
}
|
}
|
||||||
|
@ -242,10 +245,10 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_LockRWLockForReading(SDL_properties_lock) == 0) {
|
SDL_LockRWLockForReading(SDL_properties_lock);
|
||||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||||
SDL_UnlockRWLock(SDL_properties_lock);
|
SDL_UnlockRWLock(SDL_properties_lock);
|
||||||
}
|
|
||||||
if (!properties) {
|
if (!properties) {
|
||||||
SDL_InvalidParamError("props");
|
SDL_InvalidParamError("props");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -280,8 +283,7 @@ void SDL_DestroyProperties(SDL_PropertiesID props)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_LockRWLockForWriting(SDL_properties_lock) == 0) {
|
SDL_LockRWLockForWriting(SDL_properties_lock);
|
||||||
SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props);
|
SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props);
|
||||||
SDL_UnlockRWLock(SDL_properties_lock);
|
SDL_UnlockRWLock(SDL_properties_lock);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,12 +476,20 @@ int SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallba
|
||||||
|
|
||||||
int SDL_LockAudioStream(SDL_AudioStream *stream)
|
int SDL_LockAudioStream(SDL_AudioStream *stream)
|
||||||
{
|
{
|
||||||
return stream ? SDL_LockMutex(stream->lock) : SDL_InvalidParamError("stream");
|
if (!stream) {
|
||||||
|
return SDL_InvalidParamError("stream");
|
||||||
|
}
|
||||||
|
SDL_LockMutex(stream->lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_UnlockAudioStream(SDL_AudioStream *stream)
|
int SDL_UnlockAudioStream(SDL_AudioStream *stream)
|
||||||
{
|
{
|
||||||
return stream ? SDL_UnlockMutex(stream->lock) : SDL_InvalidParamError("stream");
|
if (!stream) {
|
||||||
|
return SDL_InvalidParamError("stream");
|
||||||
|
}
|
||||||
|
SDL_UnlockMutex(stream->lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec)
|
int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec)
|
||||||
|
|
|
@ -519,9 +519,9 @@ SDL_DYNAPI_PROC(void*,SDL_LoadFile_RW,(SDL_RWops *a, size_t *b, SDL_bool c),(a,b
|
||||||
SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_LoadFunction,(void *a, const char *b),(a,b),return)
|
SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_LoadFunction,(void *a, const char *b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return)
|
SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),)
|
SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),)
|
||||||
SDL_DYNAPI_PROC(int,SDL_LockMutex,(SDL_Mutex *a),(a),return)
|
SDL_DYNAPI_PROC(void,SDL_LockMutex,(SDL_Mutex *a),(a),)
|
||||||
SDL_DYNAPI_PROC(int,SDL_LockRWLockForReading,(SDL_RWLock *a),(a),return)
|
SDL_DYNAPI_PROC(void,SDL_LockRWLockForReading,(SDL_RWLock *a),(a),)
|
||||||
SDL_DYNAPI_PROC(int,SDL_LockRWLockForWriting,(SDL_RWLock *a),(a),return)
|
SDL_DYNAPI_PROC(void,SDL_LockRWLockForWriting,(SDL_RWLock *a),(a),)
|
||||||
SDL_DYNAPI_PROC(int,SDL_LockSurface,(SDL_Surface *a),(a),return)
|
SDL_DYNAPI_PROC(int,SDL_LockSurface,(SDL_Surface *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c, int *d),(a,b,c,d),return)
|
SDL_DYNAPI_PROC(int,SDL_LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c, int *d),(a,b,c,d),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return)
|
SDL_DYNAPI_PROC(int,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return)
|
||||||
|
@ -706,8 +706,8 @@ SDL_DYNAPI_PROC(int,SDL_TryLockRWLockForWriting,(SDL_RWLock *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_TryWaitSemaphore,(SDL_Semaphore *a),(a),return)
|
SDL_DYNAPI_PROC(int,SDL_TryWaitSemaphore,(SDL_Semaphore *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),)
|
SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),)
|
||||||
SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),)
|
SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),)
|
||||||
SDL_DYNAPI_PROC(int,SDL_UnlockMutex,(SDL_Mutex *a),(a),return)
|
SDL_DYNAPI_PROC(void,SDL_UnlockMutex,(SDL_Mutex *a),(a),)
|
||||||
SDL_DYNAPI_PROC(int,SDL_UnlockRWLock,(SDL_RWLock *a),(a),return)
|
SDL_DYNAPI_PROC(void,SDL_UnlockRWLock,(SDL_RWLock *a),(a),)
|
||||||
SDL_DYNAPI_PROC(void,SDL_UnlockSurface,(SDL_Surface *a),(a),)
|
SDL_DYNAPI_PROC(void,SDL_UnlockSurface,(SDL_Surface *a),(a),)
|
||||||
SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),)
|
SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),)
|
||||||
SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),)
|
SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
#include "SDL_internal.h"
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
/* An implementation of mutexes using semaphores */
|
// An implementation of mutexes using semaphores
|
||||||
|
|
||||||
#include "SDL_systhread_c.h"
|
#include "SDL_systhread_c.h"
|
||||||
|
|
||||||
|
@ -31,13 +31,9 @@ struct SDL_Mutex
|
||||||
SDL_Semaphore *sem;
|
SDL_Semaphore *sem;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create a mutex */
|
|
||||||
SDL_Mutex *SDL_CreateMutex(void)
|
SDL_Mutex *SDL_CreateMutex(void)
|
||||||
{
|
{
|
||||||
SDL_Mutex *mutex;
|
SDL_Mutex *mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
|
||||||
|
|
||||||
/* Allocate mutex memory */
|
|
||||||
mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
|
|
||||||
|
|
||||||
#ifndef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
|
@ -52,12 +48,11 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
} else {
|
} else {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
#endif /* !SDL_THREADS_DISABLED */
|
#endif // !SDL_THREADS_DISABLED
|
||||||
|
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the mutex */
|
|
||||||
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
|
@ -68,94 +63,72 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
return 0;
|
if (mutex != NULL) {
|
||||||
#else
|
SDL_threadID this_thread = SDL_ThreadID();
|
||||||
SDL_threadID this_thread;
|
if (mutex->owner == this_thread) {
|
||||||
|
++mutex->recursive;
|
||||||
if (mutex == NULL) {
|
} else {
|
||||||
return 0;
|
/* The order of operations is important.
|
||||||
}
|
We set the locking thread id after we obtain the lock
|
||||||
|
so unlocks from other threads will fail.
|
||||||
this_thread = SDL_ThreadID();
|
*/
|
||||||
if (mutex->owner == this_thread) {
|
SDL_WaitSemaphore(mutex->sem);
|
||||||
++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_WaitSemaphore(mutex->sem);
|
|
||||||
mutex->owner = this_thread;
|
|
||||||
mutex->recursive = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* try Lock the mutex */
|
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
|
||||||
{
|
|
||||||
#ifdef SDL_THREADS_DISABLED
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
int retval = 0;
|
|
||||||
SDL_threadID this_thread;
|
|
||||||
|
|
||||||
if (mutex == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
retval = SDL_TryWaitSemaphore(mutex->sem);
|
|
||||||
if (retval == 0) {
|
|
||||||
mutex->owner = this_thread;
|
mutex->owner = this_thread;
|
||||||
mutex->recursive = 0;
|
mutex->recursive = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
#endif /* SDL_THREADS_DISABLED */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
int retval = 0;
|
||||||
return 0;
|
#ifndef SDL_THREADS_DISABLED
|
||||||
#else
|
if (mutex != NULL) {
|
||||||
if (mutex == NULL) {
|
SDL_threadID this_thread = SDL_ThreadID();
|
||||||
return 0;
|
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.
|
||||||
|
*/
|
||||||
|
retval = SDL_TryWaitSemaphore(mutex->sem);
|
||||||
|
if (retval == 0) {
|
||||||
|
mutex->owner = this_thread;
|
||||||
|
mutex->recursive = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
/* If we don't own the mutex, we can't unlock it */
|
return retval;
|
||||||
if (SDL_ThreadID() != mutex->owner) {
|
}
|
||||||
return SDL_SetError("mutex not owned by this thread");
|
|
||||||
}
|
void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
|
{
|
||||||
if (mutex->recursive) {
|
#ifndef SDL_THREADS_DISABLED
|
||||||
--mutex->recursive;
|
if (mutex != NULL) {
|
||||||
} else {
|
// If we don't own the mutex, we can't unlock it
|
||||||
/* The order of operations is important.
|
if (SDL_ThreadID() != mutex->owner) {
|
||||||
First reset the owner so another thread doesn't lock
|
SDL_assert(!"Tried to unlock a mutex we don't own!");
|
||||||
the mutex and set the ownership before we reset it,
|
return; // (undefined behavior!) SDL_SetError("mutex not owned by this thread");
|
||||||
then release the lock semaphore.
|
}
|
||||||
*/
|
|
||||||
mutex->owner = 0;
|
if (mutex->recursive) {
|
||||||
SDL_PostSemaphore(mutex->sem);
|
--mutex->recursive;
|
||||||
}
|
} else {
|
||||||
return 0;
|
/* The order of operations is important.
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
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_PostSemaphore(mutex->sem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
#include "SDL_internal.h"
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
/* An implementation of rwlocks using mutexes, condition variables, and atomics. */
|
// An implementation of rwlocks using mutexes, condition variables, and atomics.
|
||||||
|
|
||||||
#include "SDL_systhread_c.h"
|
#include "SDL_systhread_c.h"
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
* will be chosen at runtime), the function names need to be
|
* will be chosen at runtime), the function names need to be
|
||||||
* suffixed
|
* suffixed
|
||||||
*/
|
*/
|
||||||
/* !!! FIXME: this is quite a tapdance with macros and the build system, maybe we can simplify how we do this. --ryan. */
|
// !!! FIXME: this is quite a tapdance with macros and the build system, maybe we can simplify how we do this. --ryan.
|
||||||
#ifndef SDL_THREAD_GENERIC_RWLOCK_SUFFIX
|
#ifndef SDL_THREAD_GENERIC_RWLOCK_SUFFIX
|
||||||
#define SDL_CreateRWLock_generic SDL_CreateRWLock
|
#define SDL_CreateRWLock_generic SDL_CreateRWLock
|
||||||
#define SDL_DestroyRWLock_generic SDL_DestroyRWLock
|
#define SDL_DestroyRWLock_generic SDL_DestroyRWLock
|
||||||
|
@ -95,63 +95,48 @@ void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
void SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
#ifndef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
if (!rwlock) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
// !!! FIXME: these don't have to be atomic, we always gate them behind a mutex.
|
||||||
} else if (SDL_LockMutex(rwlock->lock) == -1) {
|
SDL_LockMutex(rwlock->lock);
|
||||||
return -1;
|
SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); // shouldn't be able to grab lock if there's a writer!
|
||||||
|
SDL_AtomicAdd(&rwlock->reader_count, 1);
|
||||||
|
SDL_UnlockMutex(rwlock->lock); // other readers can attempt to share the lock.
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); /* shouldn't be able to grab lock if there's a writer! */
|
|
||||||
|
|
||||||
SDL_AtomicAdd(&rwlock->reader_count, 1);
|
|
||||||
SDL_UnlockMutex(rwlock->lock); /* other readers can attempt to share the lock. */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
void SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
#ifndef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
if (!rwlock) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
SDL_LockMutex(rwlock->lock);
|
||||||
} else if (SDL_LockMutex(rwlock->lock) == -1) {
|
while (SDL_AtomicGet(&rwlock->reader_count) > 0) { // while something is holding the shared lock, keep waiting.
|
||||||
return -1;
|
SDL_WaitCondition(rwlock->condition, rwlock->lock); // release the lock and wait for readers holding the shared lock to release it, regrab the lock.
|
||||||
}
|
}
|
||||||
|
|
||||||
while (SDL_AtomicGet(&rwlock->reader_count) > 0) { /* while something is holding the shared lock, keep waiting. */
|
// we hold the lock!
|
||||||
SDL_WaitCondition(rwlock->condition, rwlock->lock); /* release the lock and wait for readers holding the shared lock to release it, regrab the lock. */
|
SDL_AtomicAdd(&rwlock->writer_count, 1); // we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly!
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we hold the lock! */
|
|
||||||
SDL_AtomicAdd(&rwlock->writer_count, 1); /* we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly! */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock)
|
int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
#ifndef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
int rc;
|
if (rwlock) {
|
||||||
|
const int rc = SDL_TryLockMutex(rwlock->lock);
|
||||||
|
if (rc != 0) {
|
||||||
|
// !!! FIXME: there is a small window where a reader has to lock the mutex, and if we hit that, we will return SDL_RWLOCK_TIMEDOUT even though we could have shared the lock.
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (!rwlock) {
|
SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); // shouldn't be able to grab lock if there's a writer!
|
||||||
return SDL_InvalidParamError("rwlock");
|
SDL_AtomicAdd(&rwlock->reader_count, 1);
|
||||||
|
SDL_UnlockMutex(rwlock->lock); // other readers can attempt to share the lock.
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = SDL_TryLockMutex(rwlock->lock);
|
|
||||||
if (rc != 0) {
|
|
||||||
/* !!! FIXME: there is a small window where a reader has to lock the mutex, and if we hit that, we will return SDL_RWLOCK_TIMEDOUT even though we could have shared the lock. */
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_assert(SDL_AtomicGet(&rwlock->writer_count) == 0); /* shouldn't be able to grab lock if there's a writer! */
|
|
||||||
|
|
||||||
SDL_AtomicAdd(&rwlock->reader_count, 1);
|
|
||||||
SDL_UnlockMutex(rwlock->lock); /* other readers can attempt to share the lock. */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -160,46 +145,41 @@ int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock)
|
||||||
int SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock)
|
int SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
#ifndef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
int rc;
|
if (rwlock) {
|
||||||
|
const int rc = SDL_TryLockMutex(rwlock->lock);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (!rwlock) {
|
if (SDL_AtomicGet(&rwlock->reader_count) > 0) { // a reader is using the shared lock, treat it as unavailable.
|
||||||
return SDL_InvalidParamError("rwlock");
|
SDL_UnlockMutex(rwlock->lock);
|
||||||
} else if ((rc = SDL_TryLockMutex(rwlock->lock)) != 0) {
|
return SDL_RWLOCK_TIMEDOUT;
|
||||||
return rc;
|
}
|
||||||
|
|
||||||
|
// we hold the lock!
|
||||||
|
SDL_AtomicAdd(&rwlock->writer_count, 1); // we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly!
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_AtomicGet(&rwlock->reader_count) > 0) { /* a reader is using the shared lock, treat it as unavailable. */
|
|
||||||
SDL_UnlockMutex(rwlock->lock);
|
|
||||||
return SDL_RWLOCK_TIMEDOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we hold the lock! */
|
|
||||||
SDL_AtomicAdd(&rwlock->writer_count, 1); /* we let these be recursive, but the API doesn't require this. It _does_ trust you unlock correctly! */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_UnlockRWLock_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
void SDL_UnlockRWLock_generic(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
#ifndef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
if (!rwlock) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
SDL_LockMutex(rwlock->lock); // recursive lock for writers, readers grab lock to make sure things are sane.
|
||||||
|
|
||||||
|
if (SDL_AtomicGet(&rwlock->reader_count) > 0) { // we're a reader
|
||||||
|
SDL_AtomicAdd(&rwlock->reader_count, -1);
|
||||||
|
SDL_BroadcastCondition(rwlock->condition); // alert any pending writers to attempt to try to grab the lock again.
|
||||||
|
} else if (SDL_AtomicGet(&rwlock->writer_count) > 0) { // we're a writer
|
||||||
|
SDL_AtomicAdd(&rwlock->writer_count, -1);
|
||||||
|
SDL_UnlockMutex(rwlock->lock); // recursive unlock.
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_UnlockMutex(rwlock->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_LockMutex(rwlock->lock); /* recursive lock for writers, readers grab lock to make sure things are sane. */
|
|
||||||
|
|
||||||
if (SDL_AtomicGet(&rwlock->reader_count) > 0) { /* we're a reader */
|
|
||||||
SDL_AtomicAdd(&rwlock->reader_count, -1);
|
|
||||||
SDL_BroadcastCondition(rwlock->condition); /* alert any pending writers to attempt to try to grab the lock again. */
|
|
||||||
} else if (SDL_AtomicGet(&rwlock->writer_count) > 0) { /* we're a writer */
|
|
||||||
SDL_AtomicAdd(&rwlock->writer_count, -1);
|
|
||||||
SDL_UnlockMutex(rwlock->lock); /* recursive unlock. */
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UnlockMutex(rwlock->lock);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@
|
||||||
|
|
||||||
SDL_RWLock *SDL_CreateRWLock_generic(void);
|
SDL_RWLock *SDL_CreateRWLock_generic(void);
|
||||||
void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock);
|
void SDL_DestroyRWLock_generic(SDL_RWLock *rwlock);
|
||||||
int SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock);
|
void SDL_LockRWLockForReading_generic(SDL_RWLock *rwlock);
|
||||||
int SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock);
|
void SDL_LockRWLockForWriting_generic(SDL_RWLock *rwlock);
|
||||||
int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock);
|
int SDL_TryLockRWLockForReading_generic(SDL_RWLock *rwlock);
|
||||||
int SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock);
|
int SDL_TryLockRWLockForWriting_generic(SDL_RWLock *rwlock);
|
||||||
int SDL_UnlockRWLock_generic(SDL_RWLock *rwlock);
|
void SDL_UnlockRWLock_generic(SDL_RWLock *rwlock);
|
||||||
|
|
||||||
#endif /* SDL_THREAD_GENERIC_RWLOCK_SUFFIX */
|
#endif // SDL_THREAD_GENERIC_RWLOCK_SUFFIX
|
||||||
|
|
||||||
#endif /* SDL_sysrwlock_c_h_ */
|
#endif // SDL_sysrwlock_c_h_
|
||||||
|
|
|
@ -22,17 +22,13 @@
|
||||||
|
|
||||||
#ifdef SDL_THREAD_N3DS
|
#ifdef SDL_THREAD_N3DS
|
||||||
|
|
||||||
/* An implementation of mutexes using libctru's RecursiveLock */
|
// An implementation of mutexes using libctru's RecursiveLock
|
||||||
|
|
||||||
#include "SDL_sysmutex_c.h"
|
#include "SDL_sysmutex_c.h"
|
||||||
|
|
||||||
/* Create a mutex */
|
|
||||||
SDL_Mutex *SDL_CreateMutex(void)
|
SDL_Mutex *SDL_CreateMutex(void)
|
||||||
{
|
{
|
||||||
SDL_Mutex *mutex;
|
SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
|
||||||
|
|
||||||
/* Allocate mutex memory */
|
|
||||||
mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
|
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
RecursiveLock_Init(&mutex->lock);
|
RecursiveLock_Init(&mutex->lock);
|
||||||
} else {
|
} else {
|
||||||
|
@ -41,7 +37,6 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the mutex */
|
|
||||||
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
|
@ -49,38 +44,23 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
RecursiveLock_Lock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveLock_Lock(&mutex->lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try Lock the mutex */
|
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
return (mutex == NULL) ? 0 : RecursiveLock_TryLock(&mutex->lock);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RecursiveLock_TryLock(&mutex->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
RecursiveLock_Unlock(&mutex->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveLock_Unlock(&mutex->lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_THREAD_N3DS */
|
#endif // SDL_THREAD_N3DS
|
||||||
|
|
|
@ -67,17 +67,13 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the 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) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
RMutex rmutex;
|
||||||
|
rmutex.SetHandle(mutex->handle);
|
||||||
|
rmutex.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
RMutex rmutex;
|
|
||||||
rmutex.SetHandle(mutex->handle);
|
|
||||||
rmutex.Wait();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to lock the mutex */
|
/* Try to lock the mutex */
|
||||||
|
@ -95,16 +91,12 @@ int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Unlock the mutex */
|
/* Unlock the mutex */
|
||||||
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) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
RMutex rmutex;
|
||||||
|
rmutex.SetHandle(mutex->handle);
|
||||||
|
rmutex.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
RMutex rmutex;
|
|
||||||
rmutex.SetHandle(mutex->handle);
|
|
||||||
rmutex.Signal();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#ifdef SDL_THREAD_PSP
|
#ifdef SDL_THREAD_PSP
|
||||||
|
|
||||||
/* An implementation of mutexes using semaphores */
|
// An implementation of mutexes using semaphores
|
||||||
|
|
||||||
#include "SDL_systhread_c.h"
|
#include "SDL_systhread_c.h"
|
||||||
|
|
||||||
|
@ -36,17 +36,11 @@ struct SDL_Mutex
|
||||||
SceLwMutexWorkarea lock;
|
SceLwMutexWorkarea lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create a mutex */
|
|
||||||
SDL_Mutex *SDL_CreateMutex(void)
|
SDL_Mutex *SDL_CreateMutex(void)
|
||||||
{
|
{
|
||||||
SDL_Mutex *mutex = NULL;
|
SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
|
||||||
SceInt32 res = 0;
|
|
||||||
|
|
||||||
/* Allocate mutex memory */
|
|
||||||
mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
|
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
|
const SceInt32 res = sceKernelCreateLwMutex(
|
||||||
res = sceKernelCreateLwMutex(
|
|
||||||
&mutex->lock,
|
&mutex->lock,
|
||||||
"SDL mutex",
|
"SDL mutex",
|
||||||
SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
|
SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
|
||||||
|
@ -54,6 +48,8 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
SDL_free(mutex);
|
||||||
|
mutex = NULL;
|
||||||
SDL_SetError("Error trying to create mutex: %lx", res);
|
SDL_SetError("Error trying to create mutex: %lx", res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,7 +58,6 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the mutex */
|
|
||||||
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
|
@ -71,75 +66,43 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
return 0;
|
if (mutex != NULL) {
|
||||||
#else
|
const SceInt32 res = sceKernelLockLwMutex(&mutex->lock, 1, NULL);
|
||||||
SceInt32 res = 0;
|
SDL_assert(res == SCE_KERNEL_ERROR_OK); // assume we're in a lot of trouble if this assert fails.
|
||||||
|
|
||||||
if (mutex == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
res = sceKernelLockLwMutex(&mutex->lock, 1, NULL);
|
|
||||||
if (res != SCE_KERNEL_ERROR_OK) {
|
|
||||||
return SDL_SetError("Error trying to lock mutex: %lx", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to lock the mutex */
|
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
int retval = 0;
|
||||||
return 0;
|
#ifndef SDL_THREADS_DISABLED
|
||||||
#else
|
if (mutex != NULL) {
|
||||||
SceInt32 res = 0;
|
const SceInt32 res = sceKernelTryLockLwMutex(&mutex->lock, 1);
|
||||||
|
if (res == SCE_KERNEL_ERROR_OK) {
|
||||||
if (mutex == NULL) {
|
retval = 0;
|
||||||
return 0;
|
} else if (res == SCE_KERNEL_ERROR_WAIT_TIMEOUT) {
|
||||||
|
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 // SDL_THREADS_DISABLED
|
||||||
res = sceKernelTryLockLwMutex(&mutex->lock, 1);
|
return retval;
|
||||||
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: %lx", res);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
return 0;
|
if (mutex != NULL) {
|
||||||
#else
|
const SceInt32 res = sceKernelUnlockLwMutex(&mutex->lock, 1);
|
||||||
SceInt32 res = 0;
|
SDL_assert(res == 0); // assume we're in a lot of trouble if this assert fails.
|
||||||
|
|
||||||
if (mutex == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
res = sceKernelUnlockLwMutex(&mutex->lock, 1);
|
|
||||||
if (res != 0) {
|
|
||||||
return SDL_SetError("Error trying to unlock mutex: %lx", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_THREAD_PSP */
|
#endif // SDL_THREAD_PSP
|
||||||
|
|
|
@ -30,7 +30,7 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
SDL_Mutex *mutex;
|
SDL_Mutex *mutex;
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
|
|
||||||
/* Allocate the structure */
|
// Allocate the structure
|
||||||
mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
|
mutex = (SDL_Mutex *)SDL_calloc(1, sizeof(*mutex));
|
||||||
if (mutex) {
|
if (mutex) {
|
||||||
pthread_mutexattr_init(&attr);
|
pthread_mutexattr_init(&attr);
|
||||||
|
@ -39,7 +39,7 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
#elif defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP)
|
#elif defined(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP)
|
||||||
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||||
#else
|
#else
|
||||||
/* No extra attributes necessary */
|
// No extra attributes necessary
|
||||||
#endif
|
#endif
|
||||||
if (pthread_mutex_init(&mutex->id, &attr) != 0) {
|
if (pthread_mutex_init(&mutex->id, &attr) != 0) {
|
||||||
SDL_SetError("pthread_mutex_init() failed");
|
SDL_SetError("pthread_mutex_init() failed");
|
||||||
|
@ -60,116 +60,96 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
|
if (mutex != NULL) {
|
||||||
#ifdef FAKE_RECURSIVE_MUTEX
|
#ifdef FAKE_RECURSIVE_MUTEX
|
||||||
pthread_t this_thread;
|
pthread_t this_thread = pthread_self();
|
||||||
#endif
|
if (mutex->owner == this_thread) {
|
||||||
|
++mutex->recursive;
|
||||||
if (mutex == NULL) {
|
} else {
|
||||||
return 0;
|
/* The order of operations is important.
|
||||||
}
|
We set the locking thread id after we obtain the lock
|
||||||
|
so unlocks from other threads will fail.
|
||||||
#ifdef FAKE_RECURSIVE_MUTEX
|
*/
|
||||||
this_thread = pthread_self();
|
const int rc = pthread_mutex_lock(&mutex->id);
|
||||||
if (mutex->owner == this_thread) {
|
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||||
++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) {
|
|
||||||
mutex->owner = this_thread;
|
mutex->owner = this_thread;
|
||||||
mutex->recursive = 0;
|
mutex->recursive = 0;
|
||||||
} else {
|
|
||||||
return SDL_SetError("pthread_mutex_lock() failed");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (pthread_mutex_lock(&mutex->id) != 0) {
|
const int rc = pthread_mutex_lock(&mutex->id);
|
||||||
return SDL_SetError("pthread_mutex_lock() failed");
|
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval = 0;
|
||||||
int result;
|
|
||||||
#ifdef FAKE_RECURSIVE_MUTEX
|
|
||||||
pthread_t this_thread;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = 0;
|
|
||||||
#ifdef FAKE_RECURSIVE_MUTEX
|
#ifdef FAKE_RECURSIVE_MUTEX
|
||||||
this_thread = pthread_self();
|
pthread_t this_thread = pthread_self();
|
||||||
if (mutex->owner == this_thread) {
|
if (mutex->owner == this_thread) {
|
||||||
++mutex->recursive;
|
++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;
|
|
||||||
} else {
|
} 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
|
#else
|
||||||
result = pthread_mutex_trylock(&mutex->id);
|
const int result = pthread_mutex_trylock(&mutex->id);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
if (result == EBUSY) {
|
if (result == EBUSY) {
|
||||||
retval = SDL_MUTEX_TIMEDOUT;
|
retval = SDL_MUTEX_TIMEDOUT;
|
||||||
} else {
|
} else {
|
||||||
retval = SDL_SetError("pthread_mutex_trylock() failed");
|
SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
|
||||||
|
retval = SDL_MUTEX_TIMEDOUT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
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) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef FAKE_RECURSIVE_MUTEX
|
#ifdef FAKE_RECURSIVE_MUTEX
|
||||||
/* We can only unlock the mutex if we own it */
|
// We can only unlock the mutex if we own it
|
||||||
if (pthread_self() == mutex->owner) {
|
if (pthread_self() == mutex->owner) {
|
||||||
if (mutex->recursive) {
|
if (mutex->recursive) {
|
||||||
--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 {
|
} else {
|
||||||
/* The order of operations is important.
|
return SDL_SetError("mutex not owned by this thread");
|
||||||
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 {
|
|
||||||
return SDL_SetError("mutex not owned by this thread");
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if (pthread_mutex_unlock(&mutex->id) != 0) {
|
const int rc = pthread_mutex_unlock(&mutex->id);
|
||||||
return SDL_SetError("pthread_mutex_unlock() failed");
|
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) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
const int rc = pthread_rwlock_rdlock(&rwlock->id);
|
||||||
} else if (pthread_rwlock_rdlock(&rwlock->id) != 0) {
|
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||||
return SDL_SetError("pthread_rwlock_rdlock() failed");
|
|
||||||
}
|
}
|
||||||
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) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
const int rc = pthread_rwlock_wrlock(&rwlock->id);
|
||||||
} else if (pthread_rwlock_wrlock(&rwlock->id) != 0) {
|
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||||
return SDL_SetError("pthread_rwlock_wrlock() failed");
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (rwlock == NULL) {
|
if (rwlock) {
|
||||||
retval = SDL_InvalidParamError("rwlock");
|
|
||||||
} else {
|
|
||||||
const int result = pthread_rwlock_tryrdlock(&rwlock->id);
|
const int result = pthread_rwlock_tryrdlock(&rwlock->id);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
if (result == EBUSY) {
|
retval = SDL_RWLOCK_TIMEDOUT;
|
||||||
retval = SDL_RWLOCK_TIMEDOUT;
|
if (result != EBUSY) {
|
||||||
} else {
|
SDL_assert(!"Error trying to lock rwlock for reading"); // assume we're in a lot of trouble if this assert fails.
|
||||||
retval = SDL_SetError("pthread_rwlock_tryrdlock() failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,15 +92,12 @@ int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (rwlock == NULL) {
|
if (rwlock) {
|
||||||
retval = SDL_InvalidParamError("rwlock");
|
|
||||||
} else {
|
|
||||||
const int result = pthread_rwlock_trywrlock(&rwlock->id);
|
const int result = pthread_rwlock_trywrlock(&rwlock->id);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
if (result == EBUSY) {
|
retval = SDL_RWLOCK_TIMEDOUT;
|
||||||
retval = SDL_RWLOCK_TIMEDOUT;
|
if (result != EBUSY) {
|
||||||
} else {
|
SDL_assert(!"Error trying to lock rwlock for writing"); // assume we're in a lot of trouble if this assert fails.
|
||||||
retval = SDL_SetError("pthread_rwlock_tryrdlock() failed");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,13 +105,11 @@ int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
||||||
return retval;
|
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) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
const int rc = pthread_rwlock_unlock(&rwlock->id);
|
||||||
} else if (pthread_rwlock_unlock(&rwlock->id) != 0) {
|
SDL_assert(rc == 0); // assume we're in a lot of trouble if this assert fails.
|
||||||
return SDL_SetError("pthread_rwlock_unlock() failed");
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,74 +27,51 @@ extern "C" {
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#include "SDL_sysmutex_c.h"
|
#include "SDL_sysmutex_c.h"
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
/* Create a mutex */
|
extern "C" SDL_Mutex * SDL_CreateMutex(void)
|
||||||
extern "C" SDL_Mutex *
|
|
||||||
SDL_CreateMutex(void)
|
|
||||||
{
|
{
|
||||||
/* Allocate and initialize the mutex */
|
// Allocate and initialize the mutex
|
||||||
try {
|
try {
|
||||||
SDL_Mutex *mutex = new SDL_Mutex;
|
SDL_Mutex *mutex = new SDL_Mutex;
|
||||||
return mutex;
|
return mutex;
|
||||||
} catch (std::system_error &ex) {
|
} catch (std::system_error &ex) {
|
||||||
SDL_SetError("unable to create a C++ mutex: code=%d; %s", ex.code(), ex.what());
|
SDL_SetError("unable to create a C++ mutex: code=%d; %s", ex.code(), ex.what());
|
||||||
return NULL;
|
|
||||||
} catch (std::bad_alloc &) {
|
} catch (std::bad_alloc &) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the mutex */
|
extern "C" void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
extern "C" void
|
|
||||||
SDL_DestroyMutex(SDL_Mutex *mutex)
|
|
||||||
{
|
{
|
||||||
if (mutex != NULL) {
|
if (mutex != NULL) {
|
||||||
delete mutex;
|
delete mutex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
extern "C" void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
extern "C" int
|
|
||||||
SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
try {
|
||||||
}
|
mutex->cpp_mutex.lock();
|
||||||
|
} catch (std::system_error &ex) {
|
||||||
try {
|
SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
|
||||||
mutex->cpp_mutex.lock();
|
//return SDL_SetError("unable to lock a C++ mutex: code=%d; %s", ex.code(), ex.what());
|
||||||
return 0;
|
}
|
||||||
} catch (std::system_error &ex) {
|
|
||||||
return SDL_SetError("unable to lock a C++ mutex: code=%d; %s", ex.code(), ex.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TryLock the mutex */
|
extern "C" int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
|
||||||
{
|
{
|
||||||
int retval = 0;
|
return ((mutex == NULL) || mutex->cpp_mutex.try_lock()) ? 0 : SDL_MUTEX_TIMEDOUT;
|
||||||
|
|
||||||
if (mutex == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mutex->cpp_mutex.try_lock() == false) {
|
|
||||||
retval = SDL_MUTEX_TIMEDOUT;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
/* Unlock the mutex */
|
||||||
extern "C" int
|
extern "C" void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
mutex->cpp_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex->cpp_mutex.unlock();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,8 @@ struct SDL_RWLock
|
||||||
SDL_threadID write_owner;
|
SDL_threadID write_owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create a rwlock */
|
|
||||||
extern "C" SDL_RWLock *SDL_CreateRWLock(void)
|
extern "C" SDL_RWLock *SDL_CreateRWLock(void)
|
||||||
{
|
{
|
||||||
/* Allocate and initialize the rwlock */
|
|
||||||
try {
|
try {
|
||||||
SDL_RWLock *rwlock = new SDL_RWLock;
|
SDL_RWLock *rwlock = new SDL_RWLock;
|
||||||
return rwlock;
|
return rwlock;
|
||||||
|
@ -46,7 +44,6 @@ extern "C" SDL_RWLock *SDL_CreateRWLock(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the rwlock */
|
|
||||||
extern "C" void SDL_DestroyRWLock(SDL_RWLock *rwlock)
|
extern "C" void SDL_DestroyRWLock(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
if (rwlock != NULL) {
|
if (rwlock != NULL) {
|
||||||
|
@ -54,77 +51,64 @@ extern "C" void SDL_DestroyRWLock(SDL_RWLock *rwlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the rwlock */
|
extern "C" void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
extern "C" int SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (!rwlock) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
try {
|
||||||
}
|
rwlock->cpp_mutex.lock_shared();
|
||||||
|
} catch (std::system_error &ex) {
|
||||||
try {
|
SDL_assert(!"Error trying to lock rwlock for reading"); // assume we're in a lot of trouble if this assert fails.
|
||||||
rwlock->cpp_mutex.lock_shared();
|
//return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what());
|
||||||
return 0;
|
}
|
||||||
} catch (std::system_error &ex) {
|
|
||||||
return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the rwlock for writing */
|
extern "C" void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
extern "C" int SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (!rwlock) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
try {
|
||||||
}
|
rwlock->cpp_mutex.lock();
|
||||||
|
rwlock->write_owner = SDL_ThreadID();
|
||||||
try {
|
} catch (std::system_error &ex) {
|
||||||
rwlock->cpp_mutex.lock();
|
SDL_assert(!"Error trying to lock rwlock for writing"); // assume we're in a lot of trouble if this assert fails.
|
||||||
rwlock->write_owner = SDL_ThreadID();
|
//return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what());
|
||||||
return 0;
|
}
|
||||||
} catch (std::system_error &ex) {
|
|
||||||
return SDL_SetError("unable to lock a C++ rwlock: code=%d; %s", ex.code(), ex.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TryLock the rwlock for reading */
|
extern "C" int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
||||||
int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
if (rwlock) {
|
||||||
if (!rwlock) {
|
if (rwlock->cpp_mutex.try_lock_shared() == false) {
|
||||||
retval = SDL_InvalidParamError("rwlock");
|
retval = SDL_RWLOCK_TIMEDOUT;
|
||||||
} else if (rwlock->cpp_mutex.try_lock_shared() == false) {
|
}
|
||||||
retval = SDL_RWLOCK_TIMEDOUT;
|
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TryLock the rwlock for writing */
|
extern "C" int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
||||||
int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
if (rwlock) {
|
||||||
if (!rwlock) {
|
if (rwlock->cpp_mutex.try_lock() == false) {
|
||||||
retval = SDL_InvalidParamError("rwlock");
|
retval = SDL_RWLOCK_TIMEDOUT;
|
||||||
} else if (rwlock->cpp_mutex.try_lock() == false) {
|
} else {
|
||||||
retval = SDL_RWLOCK_TIMEDOUT;
|
rwlock->write_owner = SDL_ThreadID();
|
||||||
} else {
|
}
|
||||||
rwlock->write_owner = SDL_ThreadID();
|
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the rwlock */
|
extern "C" void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
extern "C" int
|
|
||||||
SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
if (!rwlock) {
|
if (rwlock) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
if (rwlock->write_owner == SDL_ThreadID()) {
|
||||||
} else if (rwlock->write_owner == SDL_ThreadID()) {
|
rwlock->write_owner = 0;
|
||||||
rwlock->write_owner = 0;
|
rwlock->cpp_mutex.unlock();
|
||||||
rwlock->cpp_mutex.unlock();
|
} else {
|
||||||
} else {
|
rwlock->cpp_mutex.unlock_shared();
|
||||||
rwlock->cpp_mutex.unlock_shared();
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,24 +32,20 @@ struct SDL_Mutex
|
||||||
SceKernelLwMutexWork lock;
|
SceKernelLwMutexWork lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create a mutex */
|
|
||||||
SDL_Mutex *SDL_CreateMutex(void)
|
SDL_Mutex *SDL_CreateMutex(void)
|
||||||
{
|
{
|
||||||
SDL_Mutex *mutex = NULL;
|
SDL_Mutex *mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
|
||||||
SceInt32 res = 0;
|
|
||||||
|
|
||||||
/* Allocate mutex memory */
|
|
||||||
mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
|
|
||||||
if (mutex != NULL) {
|
if (mutex != NULL) {
|
||||||
|
const SceInt32 res = sceKernelCreateLwMutex(
|
||||||
res = sceKernelCreateLwMutex(
|
&mutex->lock,
|
||||||
&mutex->lock,
|
"SDL mutex",
|
||||||
"SDL mutex",
|
SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
|
||||||
SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
|
0,
|
||||||
0,
|
NULL);
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
SDL_free(mutex);
|
||||||
|
mutex = NULL;
|
||||||
SDL_SetError("Error trying to create mutex: %x", res);
|
SDL_SetError("Error trying to create mutex: %x", res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,7 +54,6 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the mutex */
|
|
||||||
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex != NULL) {
|
if (mutex != NULL) {
|
||||||
|
@ -67,28 +62,16 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
void SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
return 0;
|
if (mutex != NULL) {
|
||||||
#else
|
const SceInt32 res = sceKernelLockLwMutex(&mutex->lock, 1, NULL);
|
||||||
SceInt32 res = 0;
|
SDL_assert(res == SCE_KERNEL_OK); // assume we're in a lot of trouble if this assert fails.
|
||||||
|
|
||||||
if (mutex == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
res = sceKernelLockLwMutex(&mutex->lock, 1, NULL);
|
|
||||||
if (res != SCE_KERNEL_OK) {
|
|
||||||
return SDL_SetError("Error trying to lock mutex: %x", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to lock the mutex */
|
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
#ifdef SDL_THREADS_DISABLED
|
||||||
|
@ -102,40 +85,24 @@ int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
|
|
||||||
res = sceKernelTryLockLwMutex(&mutex->lock, 1);
|
res = sceKernelTryLockLwMutex(&mutex->lock, 1);
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case SCE_KERNEL_OK:
|
case SCE_KERNEL_OK: return 0;
|
||||||
return 0;
|
case SCE_KERNEL_ERROR_MUTEX_FAILED_TO_OWN: return SDL_MUTEX_TIMEDOUT;
|
||||||
break;
|
default: 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;
|
SDL_assert(!"Error trying to lock mutex"); // assume we're in a lot of trouble if this assert fails.
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
return SDL_MUTEX_TIMEDOUT;
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
void SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
#ifdef SDL_THREADS_DISABLED
|
#ifndef SDL_THREADS_DISABLED
|
||||||
return 0;
|
if (mutex != NULL) {
|
||||||
#else
|
const SceInt32 res = sceKernelUnlockLwMutex(&mutex->lock, 1);
|
||||||
SceInt32 res = 0;
|
SDL_assert(res == SCE_KERNEL_OK); // assume we're in a lot of trouble if this assert fails.
|
||||||
|
|
||||||
if (mutex == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
#endif // SDL_THREADS_DISABLED
|
||||||
res = sceKernelUnlockLwMutex(&mutex->lock, 1);
|
|
||||||
if (res != 0) {
|
|
||||||
return SDL_SetError("Error trying to unlock mutex: %x", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif /* SDL_THREADS_DISABLED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_THREAD_VITA */
|
#endif // SDL_THREAD_VITA
|
||||||
|
|
|
@ -76,12 +76,11 @@ static void SDL_DestroyMutex_srw(SDL_Mutex *mutex)
|
||||||
SDL_free(mutex);
|
SDL_free(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_LockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
static void SDL_LockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
|
SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
|
||||||
DWORD this_thread;
|
const DWORD this_thread = GetCurrentThreadId();
|
||||||
|
|
||||||
this_thread = GetCurrentThreadId();
|
|
||||||
if (mutex->owner == this_thread) {
|
if (mutex->owner == this_thread) {
|
||||||
++mutex->count;
|
++mutex->count;
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,16 +93,14 @@ static int SDL_LockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /*
|
||||||
mutex->owner = this_thread;
|
mutex->owner = this_thread;
|
||||||
mutex->count = 1;
|
mutex->count = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_TryLockMutex_srw(SDL_Mutex *_mutex)
|
static int SDL_TryLockMutex_srw(SDL_Mutex *_mutex)
|
||||||
{
|
{
|
||||||
SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
|
SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
|
||||||
DWORD this_thread;
|
const DWORD this_thread = GetCurrentThreadId();
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
this_thread = GetCurrentThreadId();
|
|
||||||
if (mutex->owner == this_thread) {
|
if (mutex->owner == this_thread) {
|
||||||
++mutex->count;
|
++mutex->count;
|
||||||
} else {
|
} else {
|
||||||
|
@ -118,7 +115,7 @@ static int SDL_TryLockMutex_srw(SDL_Mutex *_mutex)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_UnlockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
static void SDL_UnlockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
|
SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
|
||||||
|
|
||||||
|
@ -128,10 +125,8 @@ static int SDL_UnlockMutex_srw(SDL_Mutex *_mutex) SDL_NO_THREAD_SAFETY_ANALYSIS
|
||||||
pReleaseSRWLockExclusive(&mutex->srw);
|
pReleaseSRWLockExclusive(&mutex->srw);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return SDL_SetError("mutex not owned by this thread");
|
SDL_assert(!"mutex not owned by this thread"); // undefined behavior...!
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const SDL_mutex_impl_t SDL_mutex_impl_srw = {
|
static const SDL_mutex_impl_t SDL_mutex_impl_srw = {
|
||||||
|
@ -147,16 +142,12 @@ static const SDL_mutex_impl_t SDL_mutex_impl_srw = {
|
||||||
* Fallback Mutex implementation using Critical Sections (before Win 7)
|
* Fallback Mutex implementation using Critical Sections (before Win 7)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Create a mutex */
|
|
||||||
static SDL_Mutex *SDL_CreateMutex_cs(void)
|
static SDL_Mutex *SDL_CreateMutex_cs(void)
|
||||||
{
|
{
|
||||||
SDL_mutex_cs *mutex;
|
SDL_mutex_cs *mutex = (SDL_mutex_cs *)SDL_malloc(sizeof(*mutex));
|
||||||
|
|
||||||
/* Allocate mutex memory */
|
|
||||||
mutex = (SDL_mutex_cs *)SDL_malloc(sizeof(*mutex));
|
|
||||||
if (mutex != NULL) {
|
if (mutex != NULL) {
|
||||||
/* Initialize */
|
// Initialize
|
||||||
/* On SMP systems, a non-zero spin count generally helps performance */
|
// On SMP systems, a non-zero spin count generally helps performance
|
||||||
#ifdef __WINRT__
|
#ifdef __WINRT__
|
||||||
InitializeCriticalSectionEx(&mutex->cs, 2000, 0);
|
InitializeCriticalSectionEx(&mutex->cs, 2000, 0);
|
||||||
#else
|
#else
|
||||||
|
@ -168,43 +159,29 @@ static SDL_Mutex *SDL_CreateMutex_cs(void)
|
||||||
return (SDL_Mutex *)mutex;
|
return (SDL_Mutex *)mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the mutex */
|
|
||||||
static void SDL_DestroyMutex_cs(SDL_Mutex *mutex_)
|
static void SDL_DestroyMutex_cs(SDL_Mutex *mutex_)
|
||||||
{
|
{
|
||||||
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
||||||
|
|
||||||
DeleteCriticalSection(&mutex->cs);
|
DeleteCriticalSection(&mutex->cs);
|
||||||
SDL_free(mutex);
|
SDL_free(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
static void SDL_LockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
static int SDL_LockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
||||||
|
|
||||||
EnterCriticalSection(&mutex->cs);
|
EnterCriticalSection(&mutex->cs);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TryLock the mutex */
|
|
||||||
static int SDL_TryLockMutex_cs(SDL_Mutex *mutex_)
|
static int SDL_TryLockMutex_cs(SDL_Mutex *mutex_)
|
||||||
{
|
{
|
||||||
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
||||||
int retval = 0;
|
return (TryEnterCriticalSection(&mutex->cs) == 0) ? SDL_MUTEX_TIMEDOUT : 0;
|
||||||
|
|
||||||
if (TryEnterCriticalSection(&mutex->cs) == 0) {
|
|
||||||
retval = SDL_MUTEX_TIMEDOUT;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
static void SDL_UnlockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
static int SDL_UnlockMutex_cs(SDL_Mutex *mutex_) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
|
||||||
{
|
{
|
||||||
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_;
|
||||||
|
|
||||||
LeaveCriticalSection(&mutex->cs);
|
LeaveCriticalSection(&mutex->cs);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const SDL_mutex_impl_t SDL_mutex_impl_cs = {
|
static const SDL_mutex_impl_t SDL_mutex_impl_cs = {
|
||||||
|
@ -223,22 +200,22 @@ static const SDL_mutex_impl_t SDL_mutex_impl_cs = {
|
||||||
SDL_Mutex *SDL_CreateMutex(void)
|
SDL_Mutex *SDL_CreateMutex(void)
|
||||||
{
|
{
|
||||||
if (SDL_mutex_impl_active.Create == NULL) {
|
if (SDL_mutex_impl_active.Create == NULL) {
|
||||||
/* Default to fallback implementation */
|
// Default to fallback implementation
|
||||||
const SDL_mutex_impl_t *impl = &SDL_mutex_impl_cs;
|
const SDL_mutex_impl_t *impl = &SDL_mutex_impl_cs;
|
||||||
|
|
||||||
if (!SDL_GetHintBoolean(SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS, SDL_FALSE)) {
|
if (!SDL_GetHintBoolean(SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS, SDL_FALSE)) {
|
||||||
#ifdef __WINRT__
|
#ifdef __WINRT__
|
||||||
/* Link statically on this platform */
|
// Link statically on this platform
|
||||||
impl = &SDL_mutex_impl_srw;
|
impl = &SDL_mutex_impl_srw;
|
||||||
#else
|
#else
|
||||||
/* Try faster implementation for Windows 7 and newer */
|
// Try faster implementation for Windows 7 and newer
|
||||||
HMODULE kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
|
HMODULE kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
|
||||||
if (kernel32) {
|
if (kernel32) {
|
||||||
/* Requires Vista: */
|
// Requires Vista:
|
||||||
pInitializeSRWLock = (pfnInitializeSRWLock)GetProcAddress(kernel32, "InitializeSRWLock");
|
pInitializeSRWLock = (pfnInitializeSRWLock)GetProcAddress(kernel32, "InitializeSRWLock");
|
||||||
pReleaseSRWLockExclusive = (pfnReleaseSRWLockExclusive)GetProcAddress(kernel32, "ReleaseSRWLockExclusive");
|
pReleaseSRWLockExclusive = (pfnReleaseSRWLockExclusive)GetProcAddress(kernel32, "ReleaseSRWLockExclusive");
|
||||||
pAcquireSRWLockExclusive = (pfnAcquireSRWLockExclusive)GetProcAddress(kernel32, "AcquireSRWLockExclusive");
|
pAcquireSRWLockExclusive = (pfnAcquireSRWLockExclusive)GetProcAddress(kernel32, "AcquireSRWLockExclusive");
|
||||||
/* Requires 7: */
|
// Requires 7:
|
||||||
pTryAcquireSRWLockExclusive = (pfnTryAcquireSRWLockExclusive)GetProcAddress(kernel32, "TryAcquireSRWLockExclusive");
|
pTryAcquireSRWLockExclusive = (pfnTryAcquireSRWLockExclusive)GetProcAddress(kernel32, "TryAcquireSRWLockExclusive");
|
||||||
if (pInitializeSRWLock && pReleaseSRWLockExclusive && pAcquireSRWLockExclusive && pTryAcquireSRWLockExclusive) {
|
if (pInitializeSRWLock && pReleaseSRWLockExclusive && pAcquireSRWLockExclusive && pTryAcquireSRWLockExclusive) {
|
||||||
impl = &SDL_mutex_impl_srw;
|
impl = &SDL_mutex_impl_srw;
|
||||||
|
@ -247,7 +224,7 @@ SDL_Mutex *SDL_CreateMutex(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy instead of using pointer to save one level of indirection */
|
// Copy instead of using pointer to save one level of indirection
|
||||||
SDL_copyp(&SDL_mutex_impl_active, impl);
|
SDL_copyp(&SDL_mutex_impl_active, impl);
|
||||||
}
|
}
|
||||||
return SDL_mutex_impl_active.Create();
|
return SDL_mutex_impl_active.Create();
|
||||||
|
@ -260,31 +237,23 @@ void SDL_DestroyMutex(SDL_Mutex *mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_LockMutex(SDL_Mutex *mutex)
|
void SDL_LockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
SDL_mutex_impl_active.Lock(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_mutex_impl_active.Lock(mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
int SDL_TryLockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
return mutex ? SDL_mutex_impl_active.TryLock(mutex) : 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_mutex_impl_active.TryLock(mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_UnlockMutex(SDL_Mutex *mutex)
|
void SDL_UnlockMutex(SDL_Mutex *mutex)
|
||||||
{
|
{
|
||||||
if (mutex == NULL) {
|
if (mutex != NULL) {
|
||||||
return 0;
|
SDL_mutex_impl_active.Unlock(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_mutex_impl_active.Unlock(mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_THREAD_WINDOWS */
|
#endif // SDL_THREAD_WINDOWS
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#include "../../core/windows/SDL_windows.h"
|
#include "../../core/windows/SDL_windows.h"
|
||||||
|
|
||||||
typedef SDL_Mutex *(*pfnSDL_CreateMutex)(void);
|
typedef SDL_Mutex *(*pfnSDL_CreateMutex)(void);
|
||||||
typedef int (*pfnSDL_LockMutex)(SDL_Mutex *);
|
typedef void (*pfnSDL_LockMutex)(SDL_Mutex *);
|
||||||
typedef int (*pfnSDL_TryLockMutex)(SDL_Mutex *);
|
typedef int (*pfnSDL_TryLockMutex)(SDL_Mutex *);
|
||||||
typedef int (*pfnSDL_UnlockMutex)(SDL_Mutex *);
|
typedef void (*pfnSDL_UnlockMutex)(SDL_Mutex *);
|
||||||
typedef void (*pfnSDL_DestroyMutex)(SDL_Mutex *);
|
typedef void (*pfnSDL_DestroyMutex)(SDL_Mutex *);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
|
@ -57,11 +57,11 @@ static pfnTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive = NULL;
|
||||||
|
|
||||||
typedef SDL_RWLock *(*pfnSDL_CreateRWLock)(void);
|
typedef SDL_RWLock *(*pfnSDL_CreateRWLock)(void);
|
||||||
typedef void (*pfnSDL_DestroyRWLock)(SDL_RWLock *);
|
typedef void (*pfnSDL_DestroyRWLock)(SDL_RWLock *);
|
||||||
typedef int (*pfnSDL_LockRWLockForReading)(SDL_RWLock *);
|
typedef void (*pfnSDL_LockRWLockForReading)(SDL_RWLock *);
|
||||||
typedef int (*pfnSDL_LockRWLockForWriting)(SDL_RWLock *);
|
typedef void (*pfnSDL_LockRWLockForWriting)(SDL_RWLock *);
|
||||||
typedef int (*pfnSDL_TryLockRWLockForReading)(SDL_RWLock *);
|
typedef int (*pfnSDL_TryLockRWLockForReading)(SDL_RWLock *);
|
||||||
typedef int (*pfnSDL_TryLockRWLockForWriting)(SDL_RWLock *);
|
typedef int (*pfnSDL_TryLockRWLockForWriting)(SDL_RWLock *);
|
||||||
typedef int (*pfnSDL_UnlockRWLock)(SDL_RWLock *);
|
typedef void (*pfnSDL_UnlockRWLock)(SDL_RWLock *);
|
||||||
|
|
||||||
typedef struct SDL_rwlock_impl_t
|
typedef struct SDL_rwlock_impl_t
|
||||||
{
|
{
|
||||||
|
@ -104,35 +104,28 @@ static void SDL_DestroyRWLock_srw(SDL_RWLock *_rwlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_LockRWLockForReading_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
static void SDL_LockRWLockForReading_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
||||||
if (rwlock == NULL) {
|
if (rwlock != NULL) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
pAcquireSRWLockShared(&rwlock->srw);
|
||||||
}
|
}
|
||||||
pAcquireSRWLockShared(&rwlock->srw);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_LockRWLockForWriting_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
static void SDL_LockRWLockForWriting_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
||||||
if (rwlock == NULL) {
|
if (rwlock != NULL) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
pAcquireSRWLockExclusive(&rwlock->srw);
|
||||||
|
rwlock->write_owner = SDL_ThreadID();
|
||||||
}
|
}
|
||||||
pAcquireSRWLockExclusive(&rwlock->srw);
|
|
||||||
rwlock->write_owner = SDL_ThreadID();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_TryLockRWLockForReading_srw(SDL_RWLock *_rwlock)
|
static int SDL_TryLockRWLockForReading_srw(SDL_RWLock *_rwlock)
|
||||||
{
|
{
|
||||||
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
if (rwlock != NULL) {
|
||||||
if (rwlock == NULL) {
|
|
||||||
retval = SDL_InvalidParamError("rwlock");
|
|
||||||
} else {
|
|
||||||
retval = pTryAcquireSRWLockShared(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT;
|
retval = pTryAcquireSRWLockShared(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -142,27 +135,23 @@ static int SDL_TryLockRWLockForWriting_srw(SDL_RWLock *_rwlock)
|
||||||
{
|
{
|
||||||
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
if (rwlock != NULL) {
|
||||||
if (rwlock == NULL) {
|
|
||||||
retval = SDL_InvalidParamError("rwlock");
|
|
||||||
} else {
|
|
||||||
retval = pTryAcquireSRWLockExclusive(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT;
|
retval = pTryAcquireSRWLockExclusive(&rwlock->srw) ? 0 : SDL_RWLOCK_TIMEDOUT;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDL_UnlockRWLock_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
|
static void SDL_UnlockRWLock_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes
|
||||||
{
|
{
|
||||||
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock;
|
||||||
if (rwlock == NULL) {
|
if (rwlock != NULL) {
|
||||||
return SDL_InvalidParamError("rwlock");
|
if (rwlock->write_owner == SDL_ThreadID()) {
|
||||||
} else if (rwlock->write_owner == SDL_ThreadID()) {
|
rwlock->write_owner = 0;
|
||||||
rwlock->write_owner = 0;
|
pReleaseSRWLockExclusive(&rwlock->srw);
|
||||||
pReleaseSRWLockExclusive(&rwlock->srw);
|
} else {
|
||||||
} else {
|
pReleaseSRWLockShared(&rwlock->srw);
|
||||||
pReleaseSRWLockShared(&rwlock->srw);
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const SDL_rwlock_impl_t SDL_rwlock_impl_srw = {
|
static const SDL_rwlock_impl_t SDL_rwlock_impl_srw = {
|
||||||
|
@ -234,47 +223,34 @@ 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) {
|
if (rwlock != NULL) {
|
||||||
return 0;
|
SDL_rwlock_impl_active.LockForReading(rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_rwlock_impl_active.LockForReading(rwlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if (rwlock != NULL) {
|
||||||
return 0;
|
SDL_rwlock_impl_active.LockForWriting(rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_rwlock_impl_active.LockForWriting(rwlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
int SDL_TryLockRWLockForReading(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
if (rwlock == NULL) {
|
return rwlock ? SDL_rwlock_impl_active.TryLockForReading(rwlock) : 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_rwlock_impl_active.TryLockForReading(rwlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
int SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock)
|
||||||
{
|
{
|
||||||
if (rwlock == NULL) {
|
return rwlock ? SDL_rwlock_impl_active.TryLockForWriting(rwlock) : 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_rwlock_impl_active.TryLockForWriting(rwlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if (rwlock != NULL) {
|
||||||
return 0;
|
SDL_rwlock_impl_active.Unlock(rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_rwlock_impl_active.Unlock(rwlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,17 +80,12 @@ Run(void *data)
|
||||||
SDL_Log("Thread %lu: starting up", SDL_ThreadID());
|
SDL_Log("Thread %lu: starting up", SDL_ThreadID());
|
||||||
while (!SDL_AtomicGet(&doterminate)) {
|
while (!SDL_AtomicGet(&doterminate)) {
|
||||||
SDL_Log("Thread %lu: ready to work\n", SDL_ThreadID());
|
SDL_Log("Thread %lu: ready to work\n", SDL_ThreadID());
|
||||||
if (SDL_LockMutex(mutex) < 0) {
|
SDL_LockMutex(mutex);
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
SDL_Log("Thread %lu: start work!\n", SDL_ThreadID());
|
SDL_Log("Thread %lu: start work!\n", SDL_ThreadID());
|
||||||
SDL_Delay(1 * worktime);
|
SDL_Delay(1 * worktime);
|
||||||
SDL_Log("Thread %lu: work done!\n", SDL_ThreadID());
|
SDL_Log("Thread %lu: work done!\n", SDL_ThreadID());
|
||||||
if (SDL_UnlockMutex(mutex) < 0) {
|
SDL_UnlockMutex(mutex);
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* If this sleep isn't done, then threads may starve */
|
/* If this sleep isn't done, then threads may starve */
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,22 +33,21 @@ static void DoWork(const int workticks) /* "Work" */
|
||||||
const SDL_threadID tid = SDL_ThreadID();
|
const SDL_threadID tid = SDL_ThreadID();
|
||||||
const SDL_bool is_reader = tid != mainthread;
|
const SDL_bool is_reader = tid != mainthread;
|
||||||
const char *typestr = is_reader ? "Reader" : "Writer";
|
const char *typestr = is_reader ? "Reader" : "Writer";
|
||||||
int rc;
|
|
||||||
|
|
||||||
SDL_Log("%s Thread %lu: ready to work\n", typestr, (unsigned long) tid);
|
SDL_Log("%s Thread %lu: ready to work\n", typestr, (unsigned long) tid);
|
||||||
rc = is_reader ? SDL_LockRWLockForReading(rwlock) : SDL_LockRWLockForWriting(rwlock);
|
if (is_reader) {
|
||||||
if (rc < 0) {
|
SDL_LockRWLockForReading(rwlock);
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s Thread %lu: Couldn't lock rwlock: %s", typestr, (unsigned long) tid, SDL_GetError());
|
|
||||||
} else {
|
} else {
|
||||||
SDL_Log("%s Thread %lu: start work!\n", typestr, (unsigned long) tid);
|
SDL_LockRWLockForWriting(rwlock);
|
||||||
SDL_Delay(workticks);
|
|
||||||
SDL_Log("%s Thread %lu: work done!\n", typestr, (unsigned long) tid);
|
|
||||||
if (SDL_UnlockRWLock(rwlock) < 0) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s Thread %lu: Couldn't unlock rwlock: %s", typestr, (unsigned long) tid, SDL_GetError());
|
|
||||||
}
|
|
||||||
/* If this sleep isn't done, then threads may starve */
|
|
||||||
SDL_Delay(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_Log("%s Thread %lu: start work!\n", typestr, (unsigned long) tid);
|
||||||
|
SDL_Delay(workticks);
|
||||||
|
SDL_Log("%s Thread %lu: work done!\n", typestr, (unsigned long) tid);
|
||||||
|
SDL_UnlockRWLock(rwlock);
|
||||||
|
|
||||||
|
/* If this sleep isn't done, then threads may starve */
|
||||||
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SDLCALL
|
static int SDLCALL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue