diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index 5fa2e754e..23cba8e22 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -44,6 +44,7 @@ #include #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -66,6 +67,9 @@ extern "C" { /** * The joystick structure used to identify an SDL joystick */ +#ifdef SDL_THREAD_SAFETY_ANALYSIS +extern SDL_mutex *SDL_joystick_lock; +#endif struct _SDL_Joystick; typedef struct _SDL_Joystick SDL_Joystick; @@ -131,7 +135,7 @@ typedef enum * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_LockJoysticks(void); +extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock); /** @@ -146,7 +150,7 @@ extern DECLSPEC void SDLCALL SDL_LockJoysticks(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void); +extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock); /** * Count the number of joysticks attached to the system. diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index de3546248..a3b2bc35b 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -31,6 +31,80 @@ #include #include +/******************************************************************************/ +/* Enable thread safety attributes only with clang. + * The attributes can be safely erased when compiling with other compilers. + */ +#if defined(SDL_THREAD_SAFETY_ANALYSIS) && \ + defined(__clang__) && (!defined(SWIG)) +#define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define SDL_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SDL_SCOPED_CAPABILITY \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define SDL_GUARDED_BY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define SDL_PT_GUARDED_BY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define SDL_ACQUIRED_BEFORE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define SDL_ACQUIRED_AFTER(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define SDL_REQUIRES(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define SDL_REQUIRES_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define SDL_ACQUIRE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define SDL_ACQUIRE_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define SDL_RELEASE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define SDL_RELEASE_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define SDL_RELEASE_GENERIC(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define SDL_TRY_ACQUIRE(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define SDL_TRY_ACQUIRE_SHARED(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define SDL_EXCLUDES(...) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define SDL_ASSERT_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define SDL_ASSERT_SHARED_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define SDL_RETURN_CAPABILITY(x) \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define SDL_NO_THREAD_SAFETY_ANALYSIS \ + SDL_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +/******************************************************************************/ + + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -96,7 +170,7 @@ extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex); +extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex) SDL_ACQUIRE(mutex); #define SDL_mutexP(m) SDL_LockMutex(m) /** @@ -119,7 +193,7 @@ extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex); * \sa SDL_LockMutex * \sa SDL_UnlockMutex */ -extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex); +extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex) SDL_TRY_ACQUIRE(0, mutex); /** * Unlock the mutex. @@ -138,7 +212,7 @@ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex); +extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex) SDL_RELEASE(mutex); #define SDL_mutexV(m) SDL_UnlockMutex(m) /** diff --git a/src/SDL_assert.c b/src/SDL_assert.c index ab360140c..9eb532d63 100644 --- a/src/SDL_assert.c +++ b/src/SDL_assert.c @@ -337,10 +337,8 @@ SDL_ReportAssertion(SDL_AssertData *data, const char *func, const char *file, } SDL_AtomicUnlock(&spinlock); - if (SDL_LockMutex(assertion_mutex) < 0) { - return SDL_ASSERTION_IGNORE; /* oh well, I guess. */ - } -#endif + SDL_LockMutex(assertion_mutex); +#endif /* !SDL_THREADS_DISABLED */ /* doing this because Visual C is upset over assigning in the macro. */ if (data->trigger_count == 0) { diff --git a/src/SDL_log.c b/src/SDL_log.c index 99d748954..bdba9a940 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -333,15 +333,9 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va } } - if (log_function_mutex) { - SDL_LockMutex(log_function_mutex); - } - + SDL_LockMutex(log_function_mutex); SDL_log_function(SDL_log_userdata, category, priority, message); - - if (log_function_mutex) { - SDL_UnlockMutex(log_function_mutex); - } + SDL_UnlockMutex(log_function_mutex); /* Free only if dynamically allocated */ if (message != stack_buf) { diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 2cc8fc5ce..83a92b5b2 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -269,14 +269,14 @@ static SDL_INLINE SDL_bool is_in_audio_device_thread(SDL_AudioDevice *device) return SDL_FALSE; } -static void SDL_AudioLockDevice_Default(SDL_AudioDevice *device) +static void SDL_AudioLockDevice_Default(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang assumes recursive locks */ { if (!is_in_audio_device_thread(device)) { SDL_LockMutex(device->mixer_lock); } } -static void SDL_AudioUnlockDevice_Default(SDL_AudioDevice *device) +static void SDL_AudioUnlockDevice_Default(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang assumes recursive locks */ { if (!is_in_audio_device_thread(device)) { SDL_UnlockMutex(device->mixer_lock); diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 18b27e76b..5c1bce506 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -57,7 +57,7 @@ #define SDL_DYNAMIC_API 0 #elif defined(__riscos__) && __riscos__ /* probably not useful on RISC OS, since dlopen() can't be used when using static linking. */ #define SDL_DYNAMIC_API 0 -#elif defined(__clang_analyzer__) +#elif defined(__clang_analyzer__) || defined(SDL_THREAD_SAFETY_ANALYSIS) #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ #elif defined(__VITA__) #define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 6c88cf3d1..46efed66e 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -517,9 +517,7 @@ void SDL_StopEventLoop(void) SDL_EventEntry *entry; SDL_SysWMEntry *wmmsg; - if (SDL_EventQ.lock) { - SDL_LockMutex(SDL_EventQ.lock); - } + SDL_LockMutex(SDL_EventQ.lock); SDL_EventQ.active = SDL_FALSE; @@ -576,8 +574,9 @@ void SDL_StopEventLoop(void) } SDL_zero(SDL_EventOK); + SDL_UnlockMutex(SDL_EventQ.lock); + if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); SDL_DestroyMutex(SDL_EventQ.lock); SDL_EventQ.lock = NULL; } @@ -621,9 +620,7 @@ int SDL_StartEventLoop(void) #endif SDL_EventQ.active = SDL_TRUE; - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } + SDL_UnlockMutex(SDL_EventQ.lock); return 0; } @@ -717,17 +714,18 @@ static int SDL_SendWakeupEvent() if (_this == NULL || !_this->SendWakeupEvent) { return 0; } - if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) { + + SDL_LockMutex(_this->wakeup_lock); + { if (_this->wakeup_window) { _this->SendWakeupEvent(_this, _this->wakeup_window); /* No more wakeup events needed until we enter a new wait */ _this->wakeup_window = NULL; } - if (_this->wakeup_lock) { - SDL_UnlockMutex(_this->wakeup_lock); - } } + SDL_UnlockMutex(_this->wakeup_lock); + return 0; } @@ -739,16 +737,16 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact /* Lock the event queue */ used = 0; - if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { + + SDL_LockMutex(SDL_EventQ.lock); + { /* Don't look after we've quit */ if (!SDL_EventQ.active) { - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } /* We get a few spurious events at shutdown, so don't warn then */ if (action == SDL_GETEVENT) { SDL_SetError("The event system has been shut down"); } + SDL_UnlockMutex(SDL_EventQ.lock); return -1; } if (action == SDL_ADDEVENT) { @@ -817,12 +815,8 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact } } } - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } - } else { - return SDL_SetError("Couldn't lock event queue"); } + SDL_UnlockMutex(SDL_EventQ.lock); if (used > 0 && action == SDL_ADDEVENT) { SDL_SendWakeupEvent(); @@ -836,14 +830,12 @@ int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, SDL_FALSE); } -SDL_bool -SDL_HasEvent(Uint32 type) +SDL_bool SDL_HasEvent(Uint32 type) { return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0; } -SDL_bool -SDL_HasEvents(Uint32 minType, Uint32 maxType) +SDL_bool SDL_HasEvents(Uint32 minType, Uint32 maxType) { return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0; } @@ -870,12 +862,11 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) #endif /* Lock the event queue */ - if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { + SDL_LockMutex(SDL_EventQ.lock); + { /* Don't look after we've quit */ if (!SDL_EventQ.active) { - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } + SDL_UnlockMutex(SDL_EventQ.lock); return; } for (entry = SDL_EventQ.head; entry; entry = next) { @@ -885,10 +876,8 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) SDL_CutEvent(entry); } } - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } } + SDL_UnlockMutex(SDL_EventQ.lock); } /* Run the system dependent event loops */ @@ -964,6 +953,7 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve SDL_bool need_periodic_poll = SDL_events_need_periodic_poll(); for (;;) { + int status; /* Pump events on entry and each time we wake to ensure: a) All pending events are batch processed after waking up from a wait b) Waiting can be completely skipped if events are already available to be pumped @@ -976,55 +966,55 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve SDL_bool add_sentinel = (SDL_AtomicGet(&SDL_sentinel_pending) == 0) ? SDL_TRUE : SDL_FALSE; SDL_PumpEventsInternal(add_sentinel); - if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) { - int status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); + SDL_LockMutex(_this->wakeup_lock); + { + status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); /* If status == 0 we are going to block so wakeup will be needed. */ if (status == 0) { _this->wakeup_window = wakeup_window; } else { _this->wakeup_window = NULL; } - if (_this->wakeup_lock) { - SDL_UnlockMutex(_this->wakeup_lock); - } - if (status < 0) { - /* Got an error: return */ - break; - } - if (status > 0) { - /* There is an event, we can return. */ - return 1; - } - /* No events found in the queue, call WaitEventTimeout to wait for an event. */ - if (timeoutNS > 0) { - Sint64 elapsed = SDL_GetTicksNS() - start; - if (elapsed >= timeoutNS) { - /* Set wakeup_window to NULL without holding the lock. */ - _this->wakeup_window = NULL; - return 0; - } - loop_timeoutNS = (timeoutNS - elapsed); - } - if (need_periodic_poll) { - if (loop_timeoutNS >= 0) { - loop_timeoutNS = SDL_min(loop_timeoutNS, PERIODIC_POLL_INTERVAL_NS); - } else { - loop_timeoutNS = PERIODIC_POLL_INTERVAL_NS; - } - } - status = _this->WaitEventTimeout(_this, loop_timeoutNS); - /* Set wakeup_window to NULL without holding the lock. */ - _this->wakeup_window = NULL; - if (status == 0 && need_periodic_poll && loop_timeoutNS == PERIODIC_POLL_INTERVAL_NS) { - /* We may have woken up to poll. Try again */ - continue; - } else if (status <= 0) { - /* There is either an error or the timeout is elapsed: return */ - return status; - } - /* An event was found and pumped into the SDL events queue. Continue the loop - to let SDL_PeepEvents pick it up .*/ } + SDL_UnlockMutex(_this->wakeup_lock); + + if (status < 0) { + /* Got an error: return */ + break; + } + if (status > 0) { + /* There is an event, we can return. */ + return 1; + } + /* No events found in the queue, call WaitEventTimeout to wait for an event. */ + if (timeoutNS > 0) { + Sint64 elapsed = SDL_GetTicksNS() - start; + if (elapsed >= timeoutNS) { + /* Set wakeup_window to NULL without holding the lock. */ + _this->wakeup_window = NULL; + return 0; + } + loop_timeoutNS = (timeoutNS - elapsed); + } + if (need_periodic_poll) { + if (loop_timeoutNS >= 0) { + loop_timeoutNS = SDL_min(loop_timeoutNS, PERIODIC_POLL_INTERVAL_NS); + } else { + loop_timeoutNS = PERIODIC_POLL_INTERVAL_NS; + } + } + status = _this->WaitEventTimeout(_this, loop_timeoutNS); + /* Set wakeup_window to NULL without holding the lock. */ + _this->wakeup_window = NULL; + if (status == 0 && need_periodic_poll && loop_timeoutNS == PERIODIC_POLL_INTERVAL_NS) { + /* We may have woken up to poll. Try again */ + continue; + } else if (status <= 0) { + /* There is either an error or the timeout is elapsed: return */ + return status; + } + /* An event was found and pumped into the SDL events queue. Continue the loop + to let SDL_PeepEvents pick it up .*/ } return 0; } @@ -1172,11 +1162,10 @@ int SDL_PushEvent(SDL_Event *event) } if (SDL_EventOK.callback || SDL_event_watchers_count > 0) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) { - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } + SDL_UnlockMutex(SDL_event_watchers_lock); return 0; } @@ -1204,11 +1193,8 @@ int SDL_PushEvent(SDL_Event *event) SDL_event_watchers_removed = SDL_FALSE; } } - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) { @@ -1220,32 +1206,25 @@ int SDL_PushEvent(SDL_Event *event) void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { /* Set filter and discard pending events */ SDL_EventOK.callback = filter; SDL_EventOK.userdata = userdata; SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } -SDL_bool -SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) +SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) { SDL_EventWatcher event_ok; - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { event_ok = SDL_EventOK; - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } - } else { - SDL_zero(event_ok); } + SDL_UnlockMutex(SDL_event_watchers_lock); if (filter) { *filter = event_ok.callback; @@ -1258,7 +1237,8 @@ SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { SDL_EventWatcher *event_watchers; event_watchers = SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers)); @@ -1272,16 +1252,14 @@ void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) watcher->removed = SDL_FALSE; ++SDL_event_watchers_count; } - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) { - if (SDL_event_watchers_lock == NULL || SDL_LockMutex(SDL_event_watchers_lock) == 0) { + SDL_LockMutex(SDL_event_watchers_lock); + { int i; for (i = 0; i < SDL_event_watchers_count; ++i) { @@ -1298,16 +1276,14 @@ void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) break; } } - - if (SDL_event_watchers_lock) { - SDL_UnlockMutex(SDL_event_watchers_lock); - } } + SDL_UnlockMutex(SDL_event_watchers_lock); } void SDL_FilterEvents(SDL_EventFilter filter, void *userdata) { - if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { + SDL_LockMutex(SDL_EventQ.lock); + { SDL_EventEntry *entry, *next; for (entry = SDL_EventQ.head; entry; entry = next) { next = entry->next; @@ -1315,10 +1291,8 @@ void SDL_FilterEvents(SDL_EventFilter filter, void *userdata) SDL_CutEvent(entry); } } - if (SDL_EventQ.lock) { - SDL_UnlockMutex(SDL_EventQ.lock); - } } + SDL_UnlockMutex(SDL_EventQ.lock); } Uint8 SDL_EventState(Uint32 type, int state) diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index 60d275356..69b8c14f5 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -233,12 +233,17 @@ int SDL_JoystickIsHaptic(SDL_Joystick *joystick) { int ret; - /* Must be a valid joystick */ - if (!SDL_PrivateJoystickValid(joystick)) { - return -1; - } + SDL_LockJoysticks(); + { + /* Must be a valid joystick */ + if (!SDL_PrivateJoystickValid(joystick)) { + SDL_UnlockJoysticks(); + return -1; + } - ret = SDL_SYS_JoystickIsHaptic(joystick); + ret = SDL_SYS_JoystickIsHaptic(joystick); + } + SDL_UnlockJoysticks(); if (ret > 0) { return SDL_TRUE; @@ -265,44 +270,53 @@ SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) return NULL; } - /* Must be a valid joystick */ - if (!SDL_PrivateJoystickValid(joystick)) { - SDL_SetError("Haptic: Joystick isn't valid."); - return NULL; - } - - /* Joystick must be haptic */ - if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) { - SDL_SetError("Haptic: Joystick isn't a haptic device."); - return NULL; - } - - hapticlist = SDL_haptics; - /* Check to see if joystick's haptic is already open */ - while (hapticlist) { - if (SDL_SYS_JoystickSameHaptic(hapticlist, joystick)) { - haptic = hapticlist; - ++haptic->ref_count; - return haptic; + SDL_LockJoysticks(); + { + /* Must be a valid joystick */ + if (!SDL_PrivateJoystickValid(joystick)) { + SDL_SetError("Haptic: Joystick isn't valid."); + SDL_UnlockJoysticks(); + return NULL; } - hapticlist = hapticlist->next; - } - /* Create the haptic device */ - haptic = (SDL_Haptic *)SDL_malloc((sizeof *haptic)); - if (haptic == NULL) { - SDL_OutOfMemory(); - return NULL; - } + /* Joystick must be haptic */ + if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) { + SDL_SetError("Haptic: Joystick isn't a haptic device."); + SDL_UnlockJoysticks(); + return NULL; + } - /* Initialize the haptic device */ - SDL_memset(haptic, 0, sizeof(SDL_Haptic)); - haptic->rumble_id = -1; - if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) { - SDL_SetError("Haptic: SDL_SYS_HapticOpenFromJoystick failed."); - SDL_free(haptic); - return NULL; + hapticlist = SDL_haptics; + /* Check to see if joystick's haptic is already open */ + while (hapticlist) { + if (SDL_SYS_JoystickSameHaptic(hapticlist, joystick)) { + haptic = hapticlist; + ++haptic->ref_count; + SDL_UnlockJoysticks(); + return haptic; + } + hapticlist = hapticlist->next; + } + + /* Create the haptic device */ + haptic = (SDL_Haptic *)SDL_malloc((sizeof *haptic)); + if (haptic == NULL) { + SDL_OutOfMemory(); + SDL_UnlockJoysticks(); + return NULL; + } + + /* Initialize the haptic device */ + SDL_memset(haptic, 0, sizeof(SDL_Haptic)); + haptic->rumble_id = -1; + if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) { + SDL_SetError("Haptic: SDL_SYS_HapticOpenFromJoystick failed."); + SDL_free(haptic); + SDL_UnlockJoysticks(); + return NULL; + } } + SDL_UnlockJoysticks(); /* Add haptic to list */ ++haptic->ref_count; diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 54aa5c043..774f5a12f 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -481,6 +481,8 @@ int SDL_SYS_HapticMouse(void) int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_LINUX + SDL_AssertJoysticksLocked(); + if (joystick->driver != &SDL_LINUX_JoystickDriver) { return SDL_FALSE; } @@ -497,6 +499,8 @@ int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_LINUX + SDL_AssertJoysticksLocked(); + if (joystick->driver != &SDL_LINUX_JoystickDriver) { return 0; } @@ -520,6 +524,8 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) int ret; SDL_hapticlist_item *item; + SDL_AssertJoysticksLocked(); + if (joystick->driver != &SDL_LINUX_JoystickDriver) { return -1; } diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index b54d7591a..fa9c600f0 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -51,7 +51,7 @@ #define SDL_CONTROLLER_SDKLE_FIELD_SIZE SDL_strlen(SDL_CONTROLLER_SDKLE_FIELD) /* a list of currently opened game controllers */ -static SDL_GameController *SDL_gamecontrollers = NULL; +static SDL_GameController *SDL_gamecontrollers SDL_GUARDED_BY(SDL_joystick_lock) = NULL; typedef struct { @@ -99,44 +99,53 @@ typedef enum SDL_CONTROLLER_MAPPING_PRIORITY_USER, } SDL_ControllerMappingPriority; +#define _guarded SDL_GUARDED_BY(SDL_joystick_lock) + typedef struct _ControllerMapping_t { - SDL_JoystickGUID guid; - char *name; - char *mapping; - SDL_ControllerMappingPriority priority; - struct _ControllerMapping_t *next; + SDL_JoystickGUID guid _guarded; + char *name _guarded; + char *mapping _guarded; + SDL_ControllerMappingPriority priority _guarded; + struct _ControllerMapping_t *next _guarded; } ControllerMapping_t; +#undef _guarded + static SDL_JoystickGUID s_zeroGUID; -static ControllerMapping_t *s_pSupportedControllers = NULL; -static ControllerMapping_t *s_pDefaultMapping = NULL; -static ControllerMapping_t *s_pXInputMapping = NULL; +static ControllerMapping_t *s_pSupportedControllers SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static ControllerMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static ControllerMapping_t *s_pXInputMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static char gamecontroller_magic; +#define _guarded SDL_GUARDED_BY(SDL_joystick_lock) + /* The SDL game controller structure */ struct _SDL_GameController { - const void *magic; + const void *magic _guarded; - SDL_Joystick *joystick; /* underlying joystick device */ - int ref_count; + SDL_Joystick *joystick _guarded; /* underlying joystick device */ + int ref_count _guarded; - const char *name; - ControllerMapping_t *mapping; - int num_bindings; - SDL_ExtendedGameControllerBind *bindings; - SDL_ExtendedGameControllerBind **last_match_axis; - Uint8 *last_hat_mask; - Uint64 guide_button_down; + const char *name _guarded; + ControllerMapping_t *mapping _guarded; + int num_bindings _guarded; + SDL_ExtendedGameControllerBind *bindings _guarded; + SDL_ExtendedGameControllerBind **last_match_axis _guarded; + Uint8 *last_hat_mask _guarded; + Uint64 guide_button_down _guarded; - struct _SDL_GameController *next; /* pointer to next game controller we have allocated */ + struct _SDL_GameController *next _guarded; /* pointer to next game controller we have allocated */ }; +#undef _guarded + #define CHECK_GAMECONTROLLER_MAGIC(gamecontroller, retval) \ if (!gamecontroller || gamecontroller->magic != &gamecontroller_magic || \ !SDL_PrivateJoystickValid(gamecontroller->joystick)) { \ SDL_InvalidParamError("gamecontroller"); \ + SDL_UnlockJoysticks(); \ return retval; \ } @@ -237,7 +246,7 @@ static void HandleJoystickAxis(Uint64 timestamp, SDL_GameController *gamecontrol SDL_ExtendedGameControllerBind *last_match; SDL_ExtendedGameControllerBind *match = NULL; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); last_match = gamecontroller->last_match_axis[axis]; for (i = 0; i < gamecontroller->num_bindings; ++i) { @@ -290,7 +299,7 @@ static void HandleJoystickButton(Uint64 timestamp, SDL_GameController *gamecontr { int i; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); for (i = 0; i < gamecontroller->num_bindings; ++i) { SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; @@ -312,7 +321,7 @@ static void HandleJoystickHat(Uint64 timestamp, SDL_GameController *gamecontroll int i; Uint8 last_mask, changed_mask; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); last_mask = gamecontroller->last_hat_mask[hat]; changed_mask = (last_mask ^ value); @@ -347,8 +356,6 @@ static void RecenterGameController(SDL_GameController *gamecontroller) SDL_GameControllerAxis axis; Uint64 timestamp = SDL_GetTicksNS(); - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); - for (button = (SDL_GameControllerButton)0; button < SDL_CONTROLLER_BUTTON_MAX; button++) { if (SDL_GameControllerGetButton(gamecontroller, button)) { SDL_PrivateGameControllerButton(timestamp, gamecontroller, button, SDL_RELEASED); @@ -367,39 +374,41 @@ static void RecenterGameController(SDL_GameController *gamecontroller) */ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *event) { + SDL_GameController *controller; + switch (event->type) { case SDL_JOYAXISMOTION: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jaxis.which) { - HandleJoystickAxis(event->common.timestamp, controllerlist, event->jaxis.axis, event->jaxis.value); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jaxis.which) { + HandleJoystickAxis(event->common.timestamp, controller, event->jaxis.axis, event->jaxis.value); break; } - controllerlist = controllerlist->next; } } break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jbutton.which) { - HandleJoystickButton(event->common.timestamp, controllerlist, event->jbutton.button, event->jbutton.state); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jbutton.which) { + HandleJoystickButton(event->common.timestamp, controller, event->jbutton.button, event->jbutton.state); break; } - controllerlist = controllerlist->next; } } break; case SDL_JOYHATMOTION: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jhat.which) { - HandleJoystickHat(event->common.timestamp, controllerlist, event->jhat.hat, event->jhat.value); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jhat.which) { + HandleJoystickHat(event->common.timestamp, controller, event->jhat.hat, event->jhat.value); break; } - controllerlist = controllerlist->next; } } break; case SDL_JOYDEVICEADDED: @@ -415,13 +424,13 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *eve } break; case SDL_JOYDEVICEREMOVED: { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick->instance_id == event->jdevice.which) { - RecenterGameController(controllerlist); + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick->instance_id == event->jdevice.which) { + RecenterGameController(controller); break; } - controllerlist = controllerlist->next; } /* We don't know if this was a game controller, so go ahead and send an event */ @@ -717,6 +726,8 @@ static ControllerMapping_t *SDL_PrivateMatchControllerMappingForGUID(SDL_Joystic ControllerMapping_t *mapping; Uint16 crc = 0; + SDL_AssertJoysticksLocked(); + if (match_crc) { SDL_GetJoystickGUIDInfo(guid, NULL, NULL, NULL, &crc); } @@ -829,8 +840,7 @@ static const char *map_StringForControllerAxis[] = { /* * convert a string to its enum equivalent */ -SDL_GameControllerAxis -SDL_GameControllerGetAxisFromString(const char *str) +SDL_GameControllerAxis SDL_GameControllerGetAxisFromString(const char *str) { int entry; @@ -889,8 +899,7 @@ static const char *map_StringForControllerButton[] = { /* * convert a string to its enum equivalent */ -SDL_GameControllerButton -SDL_GameControllerGetButtonFromString(const char *str) +SDL_GameControllerButton SDL_GameControllerGetButtonFromString(const char *str) { int entry; if (str == NULL || str[0] == '\0') { @@ -928,7 +937,7 @@ static void SDL_PrivateGameControllerParseElement(SDL_GameController *gamecontro char half_axis_input = 0; char half_axis_output = 0; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); if (*szGameButton == '+' || *szGameButton == '-') { half_axis_output = *szGameButton++; @@ -1023,8 +1032,6 @@ static void SDL_PrivateGameControllerParseControllerConfigString(SDL_GameControl int i = 0; const char *pchPos = pchString; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); - SDL_zeroa(szGameButton); SDL_zeroa(szJoystickButton); @@ -1072,7 +1079,7 @@ static void SDL_PrivateLoadButtonMapping(SDL_GameController *gamecontroller, Con { int i; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, ); + SDL_AssertJoysticksLocked(); gamecontroller->name = pControllerMapping->name; gamecontroller->num_bindings = 0; @@ -1189,23 +1196,25 @@ static char *SDL_PrivateGetControllerMappingFromMappingString(const char *pMappi */ static void SDL_PrivateGameControllerRefreshMapping(ControllerMapping_t *pControllerMapping) { - SDL_GameController *gamecontrollerlist = SDL_gamecontrollers; - while (gamecontrollerlist) { - if (gamecontrollerlist->mapping == pControllerMapping) { - /* Not really threadsafe. Should this lock access within SDL_GameControllerEventWatcher? */ - SDL_PrivateLoadButtonMapping(gamecontrollerlist, pControllerMapping); + SDL_GameController *controller; + + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->mapping == pControllerMapping) { + SDL_PrivateLoadButtonMapping(controller, pControllerMapping); { SDL_Event event; event.type = SDL_CONTROLLERDEVICEREMAPPED; event.common.timestamp = 0; - event.cdevice.which = gamecontrollerlist->joystick->instance_id; + event.cdevice.which = controller->joystick->instance_id; SDL_PushEvent(&event); } } - gamecontrollerlist = gamecontrollerlist->next; + controller = controller->next; } } @@ -1219,6 +1228,8 @@ static ControllerMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, ControllerMapping_t *pControllerMapping; Uint16 crc; + SDL_AssertJoysticksLocked(); + pchName = SDL_PrivateGetControllerNameFromMappingString(mappingString); if (pchName == NULL) { SDL_SetError("Couldn't parse name from %s", mappingString); @@ -1324,6 +1335,8 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForNameAndGUID(const { ControllerMapping_t *mapping; + SDL_AssertJoysticksLocked(); + mapping = SDL_PrivateGetControllerMappingForGUID(guid); #ifdef __LINUX__ if (mapping == NULL && name) { @@ -1430,11 +1443,10 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) SDL_JoystickGUID guid; ControllerMapping_t *mapping; - SDL_LockJoysticks(); + SDL_AssertJoysticksLocked(); if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); - SDL_UnlockJoysticks(); return NULL; } @@ -1450,7 +1462,6 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) } } - SDL_UnlockJoysticks(); return mapping; } @@ -1536,6 +1547,8 @@ static int SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_Co SDL_bool existing = SDL_FALSE; ControllerMapping_t *pControllerMapping; + SDL_AssertJoysticksLocked(); + if (mappingString == NULL) { return SDL_InvalidParamError("mappingString"); } @@ -1636,7 +1649,15 @@ static int SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_Co */ int SDL_GameControllerAddMapping(const char *mappingString) { - return SDL_PrivateGameControllerAddMapping(mappingString, SDL_CONTROLLER_MAPPING_PRIORITY_API); + int retval; + + SDL_LockJoysticks(); + { + retval = SDL_PrivateGameControllerAddMapping(mappingString, SDL_CONTROLLER_MAPPING_PRIORITY_API); + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -1645,14 +1666,20 @@ int SDL_GameControllerAddMapping(const char *mappingString) int SDL_GameControllerNumMappings(void) { int num_mappings = 0; - ControllerMapping_t *mapping; - for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { - if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { - continue; + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping; + + for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + ++num_mappings; } - ++num_mappings; } + SDL_UnlockJoysticks(); + return num_mappings; } @@ -1666,6 +1693,8 @@ static char *CreateMappingString(ControllerMapping_t *mapping, SDL_JoystickGUID size_t needed; const char *platform = SDL_GetPlatform(); + SDL_AssertJoysticksLocked(); + SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ @@ -1709,48 +1738,71 @@ static char *CreateMappingString(ControllerMapping_t *mapping, SDL_JoystickGUID /* * Get the mapping at a particular index. */ -char * -SDL_GameControllerMappingForIndex(int mapping_index) +char *SDL_GameControllerMappingForIndex(int mapping_index) { - ControllerMapping_t *mapping; + char *retval = NULL; - for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { - if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { - continue; + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping; + + for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + if (mapping_index == 0) { + retval = CreateMappingString(mapping, mapping->guid); + break; + } + --mapping_index; } - if (mapping_index == 0) { - return CreateMappingString(mapping, mapping->guid); - } - --mapping_index; } - SDL_SetError("Mapping not available"); - return NULL; + SDL_UnlockJoysticks(); + + if (retval == NULL) { + SDL_SetError("Mapping not available"); + } + return retval; } /* * Get the mapping string for this GUID */ -char * -SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid) +char *SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid) { - ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(guid); - if (mapping) { - return CreateMappingString(mapping, guid); - } else { - SDL_SetError("Mapping not available"); + char *retval; + + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(guid); + if (mapping) { + retval = CreateMappingString(mapping, guid); + } else { + SDL_SetError("Mapping not available"); + retval = NULL; + } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /* * Get the mapping string for this device */ -char * -SDL_GameControllerMapping(SDL_GameController *gamecontroller) +char *SDL_GameControllerMapping(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + char *retval; - return CreateMappingString(gamecontroller->mapping, gamecontroller->joystick->guid); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + + retval = CreateMappingString(gamecontroller->mapping, gamecontroller->joystick->guid); + } + SDL_UnlockJoysticks(); + + return retval; } static void SDL_GameControllerLoadHints() @@ -1809,6 +1861,9 @@ int SDL_GameControllerInitMappings(void) char szControllerMapPath[1024]; int i = 0; const char *pMappingString = NULL; + + SDL_AssertJoysticksLocked(); + pMappingString = s_ControllerMappings[i]; while (pMappingString) { SDL_PrivateGameControllerAddMapping(pMappingString, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT); @@ -1856,38 +1911,49 @@ int SDL_GameControllerInit(void) /* * Get the implementation dependent name of a controller */ -const char * -SDL_GameControllerNameForIndex(int joystick_index) +const char *SDL_GameControllerNameForIndex(int joystick_index) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(joystick_index); - if (pSupportedController != NULL) { - if (SDL_strcmp(pSupportedController->name, "*") == 0) { - return SDL_JoystickNameForIndex(joystick_index); - } else { - return pSupportedController->name; + const char *retval = NULL; + + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping != NULL) { + if (SDL_strcmp(mapping->name, "*") == 0) { + retval = SDL_JoystickNameForIndex(joystick_index); + } else { + retval = mapping->name; + } } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /* * Get the implementation dependent path of a controller */ -const char * -SDL_GameControllerPathForIndex(int joystick_index) +const char *SDL_GameControllerPathForIndex(int joystick_index) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(joystick_index); - if (pSupportedController != NULL) { - return SDL_JoystickPathForIndex(joystick_index); + const char *retval = NULL; + + SDL_LockJoysticks(); + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping != NULL) { + retval = SDL_JoystickPathForIndex(joystick_index); + } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /** * Get the type of a game controller. */ -SDL_GameControllerType -SDL_GameControllerTypeForIndex(int joystick_index) +SDL_GameControllerType SDL_GameControllerTypeForIndex(int joystick_index) { return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetDeviceGUID(joystick_index), SDL_JoystickNameForIndex(joystick_index)); } @@ -1897,58 +1963,71 @@ SDL_GameControllerTypeForIndex(int joystick_index) * This can be called before any controllers are opened. * If no mapping can be found, this function returns NULL. */ -char * -SDL_GameControllerMappingForDeviceIndex(int joystick_index) +char *SDL_GameControllerMappingForDeviceIndex(int joystick_index) { - char *pMappingString = NULL; - ControllerMapping_t *mapping; + char *retval = NULL; SDL_LockJoysticks(); - mapping = SDL_PrivateGetControllerMapping(joystick_index); - if (mapping) { - SDL_JoystickGUID guid; - char pchGUID[33]; - size_t needed; - guid = SDL_JoystickGetDeviceGUID(joystick_index); - SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); - /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ - needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; - pMappingString = SDL_malloc(needed); - if (pMappingString == NULL) { - SDL_OutOfMemory(); - SDL_UnlockJoysticks(); - return NULL; + { + ControllerMapping_t *mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping != NULL) { + SDL_JoystickGUID guid; + char pchGUID[33]; + size_t needed; + guid = SDL_JoystickGetDeviceGUID(joystick_index); + SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); + /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ + needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; + retval = (char *)SDL_malloc(needed); + if (retval != NULL) { + (void)SDL_snprintf(retval, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); + } else { + SDL_OutOfMemory(); + } } - (void)SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); } SDL_UnlockJoysticks(); - return pMappingString; + return retval; } /* * Return 1 if the joystick with this name and GUID is a supported controller */ -SDL_bool -SDL_IsGameControllerNameAndGUID(const char *name, SDL_JoystickGUID guid) +SDL_bool SDL_IsGameControllerNameAndGUID(const char *name, SDL_JoystickGUID guid) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMappingForNameAndGUID(name, guid); - if (pSupportedController) { - return SDL_TRUE; + SDL_bool retval; + + SDL_LockJoysticks(); + { + if (SDL_PrivateGetControllerMappingForNameAndGUID(name, guid) != NULL) { + retval = SDL_TRUE; + } else { + retval = SDL_FALSE; + } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } /* * Return 1 if the joystick at this device index is a supported controller */ -SDL_bool -SDL_IsGameController(int joystick_index) +SDL_bool SDL_IsGameController(int joystick_index) { - ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(joystick_index); - if (pSupportedController != NULL) { - return SDL_TRUE; + SDL_bool retval; + + SDL_LockJoysticks(); + { + if (SDL_PrivateGetControllerMapping(joystick_index) != NULL) { + retval = SDL_TRUE; + } else { + retval = SDL_FALSE; + } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } #if defined(__LINUX__) @@ -2050,8 +2129,7 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) * * This function returns a controller identifier, or NULL if an error occurred. */ -SDL_GameController * -SDL_GameControllerOpen(int joystick_index) +SDL_GameController *SDL_GameControllerOpen(int joystick_index) { SDL_JoystickID instance_id; SDL_GameController *gamecontroller; @@ -2144,86 +2222,101 @@ void SDL_GameControllerUpdate(void) /** * Return whether a game controller has a given axis */ -SDL_bool -SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) +SDL_bool SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { SDL_GameControllerButtonBind bind; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + + bind = SDL_GameControllerGetBindForAxis(gamecontroller, axis); + } + SDL_UnlockJoysticks(); - bind = SDL_GameControllerGetBindForAxis(gamecontroller, axis); return (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE; } /* * Get the current state of an axis control on a controller */ -Sint16 -SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) +Sint16 SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { - int i; + Sint16 retval = 0; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_LockJoysticks(); + { + int i; - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { - int value = 0; - SDL_bool valid_input_range; - SDL_bool valid_output_range; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); - if (binding->input.axis.axis_min < binding->input.axis.axis_max) { - valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); - } else { - valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); - } - if (valid_input_range) { - if (binding->input.axis.axis_min != binding->output.axis.axis_min || binding->input.axis.axis_max != binding->output.axis.axis_max) { - float normalized_value = (float)(value - binding->input.axis.axis_min) / (binding->input.axis.axis_max - binding->input.axis.axis_min); - value = binding->output.axis.axis_min + (int)(normalized_value * (binding->output.axis.axis_max - binding->output.axis.axis_min)); + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { + int value = 0; + SDL_bool valid_input_range; + SDL_bool valid_output_range; + + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); + if (binding->input.axis.axis_min < binding->input.axis.axis_max) { + valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); + } else { + valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); + } + if (valid_input_range) { + if (binding->input.axis.axis_min != binding->output.axis.axis_min || binding->input.axis.axis_max != binding->output.axis.axis_max) { + float normalized_value = (float)(value - binding->input.axis.axis_min) / (binding->input.axis.axis_max - binding->input.axis.axis_min); + value = binding->output.axis.axis_min + (int)(normalized_value * (binding->output.axis.axis_max - binding->output.axis.axis_min)); + } + } else { + value = 0; + } + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + value = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); + if (value == SDL_PRESSED) { + value = binding->output.axis.axis_max; + } + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); + if (hat_mask & binding->input.hat.hat_mask) { + value = binding->output.axis.axis_max; } - } else { - value = 0; } - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - value = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); - if (value == SDL_PRESSED) { - value = binding->output.axis.axis_max; - } - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); - if (hat_mask & binding->input.hat.hat_mask) { - value = binding->output.axis.axis_max; - } - } - if (binding->output.axis.axis_min < binding->output.axis.axis_max) { - valid_output_range = (value >= binding->output.axis.axis_min && value <= binding->output.axis.axis_max); - } else { - valid_output_range = (value >= binding->output.axis.axis_max && value <= binding->output.axis.axis_min); - } - /* If the value is zero, there might be another binding that makes it non-zero */ - if (value != 0 && valid_output_range) { - return (Sint16)value; + if (binding->output.axis.axis_min < binding->output.axis.axis_max) { + valid_output_range = (value >= binding->output.axis.axis_min && value <= binding->output.axis.axis_max); + } else { + valid_output_range = (value >= binding->output.axis.axis_max && value <= binding->output.axis.axis_min); + } + /* If the value is zero, there might be another binding that makes it non-zero */ + if (value != 0 && valid_output_range) { + retval = (Sint16)value; + break; + } } } } - return 0; + SDL_UnlockJoysticks(); + + return retval; } /** * Return whether a game controller has a given button */ -SDL_bool -SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) +SDL_bool SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { SDL_GameControllerButtonBind bind; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + + bind = SDL_GameControllerGetBindForButton(gamecontroller, button); + } + SDL_UnlockJoysticks(); - bind = SDL_GameControllerGetBindForButton(gamecontroller, button); return (bind.bindType != SDL_CONTROLLER_BINDTYPE_NONE) ? SDL_TRUE : SDL_FALSE; } @@ -2232,38 +2325,49 @@ SDL_GameControllerHasButton(SDL_GameController *gamecontroller, SDL_GameControll */ Uint8 SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { - int i; + Uint8 retval = SDL_RELEASED; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_LockJoysticks(); + { + int i; - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - SDL_bool valid_input_range; + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); - int value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); - int threshold = binding->input.axis.axis_min + (binding->input.axis.axis_max - binding->input.axis.axis_min) / 2; - if (binding->input.axis.axis_min < binding->input.axis.axis_max) { - valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); - if (valid_input_range) { - return (value >= threshold) ? SDL_PRESSED : SDL_RELEASED; - } - } else { - valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); - if (valid_input_range) { - return (value <= threshold) ? SDL_PRESSED : SDL_RELEASED; + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + SDL_bool valid_input_range; + + int value = SDL_JoystickGetAxis(gamecontroller->joystick, binding->input.axis.axis); + int threshold = binding->input.axis.axis_min + (binding->input.axis.axis_max - binding->input.axis.axis_min) / 2; + if (binding->input.axis.axis_min < binding->input.axis.axis_max) { + valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); + if (valid_input_range) { + retval = (value >= threshold) ? SDL_PRESSED : SDL_RELEASED; + break; + } + } else { + valid_input_range = (value >= binding->input.axis.axis_max && value <= binding->input.axis.axis_min); + if (valid_input_range) { + retval = (value <= threshold) ? SDL_PRESSED : SDL_RELEASED; + break; + } } + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + retval = SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); + break; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); + retval = (hat_mask & binding->input.hat.hat_mask) ? SDL_PRESSED : SDL_RELEASED; + break; } - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - return SDL_JoystickGetButton(gamecontroller->joystick, binding->input.button); - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - int hat_mask = SDL_JoystickGetHat(gamecontroller->joystick, binding->input.hat.hat); - return (hat_mask & binding->input.hat.hat_mask) ? SDL_PRESSED : SDL_RELEASED; } } } - return SDL_RELEASED; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -2271,12 +2375,18 @@ Uint8 SDL_GameControllerGetButton(SDL_GameController *gamecontroller, SDL_GameCo */ int SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + int retval = 0; - if (joystick) { - return joystick->ntouchpads; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + retval = joystick->ntouchpads; + } } - return 0; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -2284,12 +2394,22 @@ int SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller) */ int SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, int touchpad) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + int retval = 0; - if (joystick && touchpad >= 0 && touchpad < joystick->ntouchpads) { - return joystick->touchpads[touchpad].nfingers; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + if (touchpad >= 0 && touchpad < joystick->ntouchpads) { + retval = joystick->touchpads[touchpad].nfingers; + } else { + retval = SDL_InvalidParamError("touchpad"); + } + } } - return 0; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -2297,55 +2417,66 @@ int SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, */ int SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + int retval = -1; - if (joystick) { - if (touchpad >= 0 && touchpad < joystick->ntouchpads) { - SDL_JoystickTouchpadInfo *touchpad_info = &joystick->touchpads[touchpad]; - if (finger >= 0 && finger < touchpad_info->nfingers) { - SDL_JoystickTouchpadFingerInfo *info = &touchpad_info->fingers[finger]; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + if (touchpad >= 0 && touchpad < joystick->ntouchpads) { + SDL_JoystickTouchpadInfo *touchpad_info = &joystick->touchpads[touchpad]; + if (finger >= 0 && finger < touchpad_info->nfingers) { + SDL_JoystickTouchpadFingerInfo *info = &touchpad_info->fingers[finger]; - if (state) { - *state = info->state; + if (state) { + *state = info->state; + } + if (x) { + *x = info->x; + } + if (y) { + *y = info->y; + } + if (pressure) { + *pressure = info->pressure; + } + retval = 0; + } else { + retval = SDL_InvalidParamError("finger"); } - if (x) { - *x = info->x; - } - if (y) { - *y = info->y; - } - if (pressure) { - *pressure = info->pressure; - } - return 0; } else { - return SDL_InvalidParamError("finger"); + retval = SDL_InvalidParamError("touchpad"); } - } else { - return SDL_InvalidParamError("touchpad"); } - } else { - return SDL_InvalidParamError("gamecontroller"); } + SDL_UnlockJoysticks(); + + return retval; } /** * Return whether a game controller has a particular sensor. */ -SDL_bool -SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type) +SDL_bool SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_bool retval = SDL_FALSE; - if (joystick) { - for (i = 0; i < joystick->nsensors; ++i) { - if (joystick->sensors[i].type == type) { - return SDL_TRUE; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + if (joystick->sensors[i].type == type) { + retval = SDL_TRUE; + break; + } } } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2353,41 +2484,47 @@ SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType t */ int SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - if (joystick == NULL) { - return -1; - } - - for (i = 0; i < joystick->nsensors; ++i) { - SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - - if (sensor->type == type) { - if (sensor->enabled == enabled) { - return 0; - } - - if (enabled) { - if (joystick->nsensors_enabled == 0) { - if (joystick->driver->SetSensorsEnabled(joystick, SDL_TRUE) < 0) { - return -1; + if (sensor->type == type) { + if (sensor->enabled == enabled) { + SDL_UnlockJoysticks(); + return 0; } - } - ++joystick->nsensors_enabled; - } else { - if (joystick->nsensors_enabled == 1) { - if (joystick->driver->SetSensorsEnabled(joystick, SDL_FALSE) < 0) { - return -1; - } - } - --joystick->nsensors_enabled; - } - sensor->enabled = enabled; - return 0; + if (enabled) { + if (joystick->nsensors_enabled == 0) { + if (joystick->driver->SetSensorsEnabled(joystick, SDL_TRUE) < 0) { + SDL_UnlockJoysticks(); + return -1; + } + } + ++joystick->nsensors_enabled; + } else { + if (joystick->nsensors_enabled == 1) { + if (joystick->driver->SetSensorsEnabled(joystick, SDL_FALSE) < 0) { + SDL_UnlockJoysticks(); + return -1; + } + } + --joystick->nsensors_enabled; + } + + sensor->enabled = enabled; + SDL_UnlockJoysticks(); + return 0; + } + } } } + SDL_UnlockJoysticks(); + return SDL_Unsupported(); } @@ -2396,17 +2533,24 @@ int SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_S */ SDL_bool SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_bool retval = SDL_FALSE; - if (joystick) { - for (i = 0; i < joystick->nsensors; ++i) { - if (joystick->sensors[i].type == type) { - return joystick->sensors[i].enabled; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + if (joystick->sensors[i].type == type) { + retval = joystick->sensors[i].enabled; + break; + } } } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2414,21 +2558,26 @@ SDL_bool SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, S */ float SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_SensorType type) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + float retval = 0.0f; - if (joystick == NULL) { - return 0.0f; - } + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - for (i = 0; i < joystick->nsensors; ++i) { - SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - - if (sensor->type == type) { - return sensor->rate; + if (sensor->type == type) { + retval = sensor->rate; + break; + } + } } } - return 0.0f; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2436,39 +2585,48 @@ float SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SD */ int SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values) { - SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - int i; + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); + if (joystick) { + int i; + for (i = 0; i < joystick->nsensors; ++i) { + SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - if (joystick == NULL) { - return -1; - } - - for (i = 0; i < joystick->nsensors; ++i) { - SDL_JoystickSensorInfo *sensor = &joystick->sensors[i]; - - if (sensor->type == type) { - num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); - SDL_memcpy(data, sensor->data, num_values * sizeof(*data)); - return 0; + if (sensor->type == type) { + num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); + SDL_memcpy(data, sensor->data, num_values * sizeof(*data)); + SDL_UnlockJoysticks(); + return 0; + } + } } } + SDL_UnlockJoysticks(); + return SDL_Unsupported(); } -const char * -SDL_GameControllerName(SDL_GameController *gamecontroller) +const char *SDL_GameControllerName(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + const char *retval = NULL; - if (SDL_strcmp(gamecontroller->name, "*") == 0) { - return SDL_JoystickName(SDL_GameControllerGetJoystick(gamecontroller)); - } else { - return gamecontroller->name; + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + + if (SDL_strcmp(gamecontroller->name, "*") == 0) { + retval = SDL_JoystickName(gamecontroller->joystick); + } else { + retval = gamecontroller->name; + } } + SDL_UnlockJoysticks(); + + return retval; } -const char * -SDL_GameControllerPath(SDL_GameController *gamecontroller) +const char *SDL_GameControllerPath(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2478,8 +2636,7 @@ SDL_GameControllerPath(SDL_GameController *gamecontroller) return SDL_JoystickPath(joystick); } -SDL_GameControllerType -SDL_GameControllerGetType(SDL_GameController *gamecontroller) +SDL_GameControllerType SDL_GameControllerGetType(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2512,8 +2669,7 @@ void SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int pl SDL_JoystickSetPlayerIndex(joystick, player_index); } -Uint16 -SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2523,8 +2679,7 @@ SDL_GameControllerGetVendor(SDL_GameController *gamecontroller) return SDL_JoystickGetVendor(joystick); } -Uint16 -SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2534,8 +2689,7 @@ SDL_GameControllerGetProduct(SDL_GameController *gamecontroller) return SDL_JoystickGetProduct(joystick); } -Uint16 -SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2545,8 +2699,7 @@ SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller) return SDL_JoystickGetProductVersion(joystick); } -Uint16 -SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) +Uint16 SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2556,8 +2709,7 @@ SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller) return SDL_JoystickGetFirmwareVersion(joystick); } -const char * -SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) +const char * SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2571,30 +2723,38 @@ SDL_GameControllerGetSerial(SDL_GameController *gamecontroller) * Return if the controller in question is currently attached to the system, * \return 0 if not plugged in, 1 if still present. */ -SDL_bool -SDL_GameControllerGetAttached(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerGetAttached(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_FALSE); + SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); - return SDL_JoystickGetAttached(gamecontroller->joystick); + if (joystick == NULL) { + return SDL_FALSE; + } + return SDL_JoystickGetAttached(joystick); } /* * Get the joystick for this controller */ -SDL_Joystick * -SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller) +SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller) { - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + SDL_Joystick *joystick; - return gamecontroller->joystick; + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + + joystick = gamecontroller->joystick; + } + SDL_UnlockJoysticks(); + + return joystick; } /* * Return the SDL_GameController associated with an instance id. */ -SDL_GameController * -SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) +SDL_GameController *SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) { SDL_GameController *gamecontroller; @@ -2616,11 +2776,18 @@ SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) */ SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index) { - SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index); - if (joystick) { - return SDL_GameControllerFromInstanceID(joystick->instance_id); + SDL_GameController *retval = NULL; + + SDL_LockJoysticks(); + { + SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index); + if (joystick) { + retval = SDL_GameControllerFromInstanceID(joystick->instance_id); + } } - return NULL; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -2628,32 +2795,36 @@ SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index) */ SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { - int i; SDL_GameControllerButtonBind bind; + SDL_zero(bind); - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); - if (axis == SDL_CONTROLLER_AXIS_INVALID) { - return bind; - } - - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { - bind.bindType = binding->inputType; - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - /* FIXME: There might be multiple axes bound now that we have axis ranges... */ - bind.value.axis = binding->input.axis.axis; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - bind.value.button = binding->input.button; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - bind.value.hat.hat = binding->input.hat.hat; - bind.value.hat.hat_mask = binding->input.hat.hat_mask; + if (axis != SDL_CONTROLLER_AXIS_INVALID) { + int i; + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS && binding->output.axis.axis == axis) { + bind.bindType = binding->inputType; + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + /* FIXME: There might be multiple axes bound now that we have axis ranges... */ + bind.value.axis = binding->input.axis.axis; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + bind.value.button = binding->input.button; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + bind.value.hat.hat = binding->input.hat.hat; + bind.value.hat.hat_mask = binding->input.hat.hat_mask; + } + break; + } } - break; } } + SDL_UnlockJoysticks(); + return bind; } @@ -2662,31 +2833,35 @@ SDL_GameControllerButtonBind SDL_GameControllerGetBindForAxis(SDL_GameController */ SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { - int i; SDL_GameControllerButtonBind bind; + SDL_zero(bind); - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, bind); - if (button == SDL_CONTROLLER_BUTTON_INVALID) { - return bind; - } - - for (i = 0; i < gamecontroller->num_bindings; ++i) { - SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; - if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { - bind.bindType = binding->inputType; - if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { - bind.value.axis = binding->input.axis.axis; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { - bind.value.button = binding->input.button; - } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { - bind.value.hat.hat = binding->input.hat.hat; - bind.value.hat.hat_mask = binding->input.hat.hat_mask; + if (button != SDL_CONTROLLER_BUTTON_INVALID) { + int i; + for (i = 0; i < gamecontroller->num_bindings; ++i) { + SDL_ExtendedGameControllerBind *binding = &gamecontroller->bindings[i]; + if (binding->outputType == SDL_CONTROLLER_BINDTYPE_BUTTON && binding->output.button == button) { + bind.bindType = binding->inputType; + if (binding->inputType == SDL_CONTROLLER_BINDTYPE_AXIS) { + bind.value.axis = binding->input.axis.axis; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_BUTTON) { + bind.value.button = binding->input.button; + } else if (binding->inputType == SDL_CONTROLLER_BINDTYPE_HAT) { + bind.value.hat.hat = binding->input.hat.hat; + bind.value.hat.hat_mask = binding->input.hat.hat_mask; + } + break; + } } - break; } } + SDL_UnlockJoysticks(); + return bind; } @@ -2710,8 +2885,7 @@ int SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 return SDL_JoystickRumbleTriggers(joystick, left_rumble, right_rumble, duration_ms); } -SDL_bool -SDL_GameControllerHasLED(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerHasLED(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2721,8 +2895,7 @@ SDL_GameControllerHasLED(SDL_GameController *gamecontroller) return SDL_JoystickHasLED(joystick); } -SDL_bool -SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2732,8 +2905,7 @@ SDL_GameControllerHasRumble(SDL_GameController *gamecontroller) return SDL_JoystickHasRumble(joystick); } -SDL_bool -SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller) +SDL_bool SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); @@ -2767,12 +2939,13 @@ void SDL_GameControllerClose(SDL_GameController *gamecontroller) { SDL_GameController *gamecontrollerlist, *gamecontrollerlistprev; + SDL_LockJoysticks(); + if (gamecontroller == NULL || gamecontroller->magic != &gamecontroller_magic) { + SDL_UnlockJoysticks(); return; } - SDL_LockJoysticks(); - /* First decrement ref count */ if (--gamecontroller->ref_count > 0) { SDL_UnlockJoysticks(); @@ -2823,6 +2996,8 @@ void SDL_GameControllerQuitMappings(void) { ControllerMapping_t *pControllerMap; + SDL_AssertJoysticksLocked(); + while (s_pSupportedControllers) { pControllerMap = s_pSupportedControllers; s_pSupportedControllers = s_pSupportedControllers->next; @@ -2855,7 +3030,7 @@ static int SDL_PrivateGameControllerAxis(Uint64 timestamp, SDL_GameController *g { int posted; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_AssertJoysticksLocked(); /* translate the event, if desired */ posted = 0; @@ -2882,7 +3057,7 @@ static int SDL_PrivateGameControllerButton(Uint64 timestamp, SDL_GameController #if !SDL_EVENTS_DISABLED SDL_Event event; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0); + SDL_AssertJoysticksLocked(); if (button == SDL_CONTROLLER_BUTTON_INVALID) { return 0; @@ -2977,39 +3152,53 @@ int SDL_GameControllerEventState(int state) void SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick) { - SDL_GameController *controllerlist = SDL_gamecontrollers; - while (controllerlist) { - if (controllerlist->joystick == joystick) { - SDL_PrivateGameControllerButton(0, controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED); + SDL_GameController *controller; + + SDL_AssertJoysticksLocked(); + + for (controller = SDL_gamecontrollers; controller; controller = controller->next) { + if (controller->joystick == joystick) { + SDL_PrivateGameControllerButton(0, controller, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED); break; } - controllerlist = controllerlist->next; } } -const char * -SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) +const char *SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button) { #if defined(SDL_JOYSTICK_MFI) const char *IOS_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button); + const char *retval; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); - return IOS_GameControllerGetAppleSFSymbolsNameForButton(gamecontroller, button); + retval = IOS_GameControllerGetAppleSFSymbolsNameForButton(gamecontroller, button); + } + SDL_UnlockJoysticks(); + + return retval; #else return NULL; #endif } -const char * -SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) +const char *SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis) { #if defined(SDL_JOYSTICK_MFI) const char *IOS_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis); + const char *retval; - CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); + SDL_LockJoysticks(); + { + CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); - return IOS_GameControllerGetAppleSFSymbolsNameForAxis(gamecontroller, axis); + retval = IOS_GameControllerGetAppleSFSymbolsNameForAxis(gamecontroller, axis); + } + SDL_UnlockJoysticks(); + + return retval; #else return NULL; #endif diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index e8767f3cc..d93df6e5b 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -102,40 +102,37 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = { &SDL_DUMMY_JoystickDriver #endif }; +SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ +static int SDL_joysticks_locked; static SDL_bool SDL_joysticks_initialized; static SDL_bool SDL_joysticks_quitting = SDL_FALSE; -static SDL_Joystick *SDL_joysticks = NULL; -static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ -static int SDL_joysticks_locked; -static SDL_atomic_t SDL_next_joystick_instance_id; -static int SDL_joystick_player_count = 0; -static SDL_JoystickID *SDL_joystick_players = NULL; +static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static SDL_atomic_t SDL_next_joystick_instance_id SDL_GUARDED_BY(SDL_joystick_lock); +static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; +static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; static char joystick_magic; #define CHECK_JOYSTICK_MAGIC(joystick, retval) \ if (!joystick || joystick->magic != &joystick_magic) { \ SDL_InvalidParamError("joystick"); \ + SDL_UnlockJoysticks(); \ return retval; \ } -SDL_bool -SDL_JoysticksInitialized(void) +SDL_bool SDL_JoysticksInitialized(void) { return SDL_joysticks_initialized; } -SDL_bool -SDL_JoysticksQuitting(void) +SDL_bool SDL_JoysticksQuitting(void) { return SDL_joysticks_quitting; } void SDL_LockJoysticks(void) { - if (SDL_joystick_lock) { - SDL_LockMutex(SDL_joystick_lock); - } + SDL_LockMutex(SDL_joystick_lock); ++SDL_joysticks_locked; } @@ -144,22 +141,18 @@ void SDL_UnlockJoysticks(void) { --SDL_joysticks_locked; - if (SDL_joystick_lock) { - SDL_UnlockMutex(SDL_joystick_lock); + SDL_UnlockMutex(SDL_joystick_lock); - /* The last unlock after joysticks are uninitialized will cleanup the mutex, - * allowing applications to lock joysticks while reinitializing the system. - */ - if (!SDL_joysticks_locked && - !SDL_joysticks_initialized) { - SDL_DestroyMutex(SDL_joystick_lock); - SDL_joystick_lock = NULL; - } + /* The last unlock after joysticks are uninitialized will cleanup the mutex, + * allowing applications to lock joysticks while reinitializing the system. + */ + if (SDL_joystick_lock && !SDL_joysticks_locked && !SDL_joysticks_initialized) { + SDL_DestroyMutex(SDL_joystick_lock); + SDL_joystick_lock = NULL; } } -SDL_bool -SDL_JoysticksLocked(void) +SDL_bool SDL_JoysticksLocked(void) { return (SDL_joysticks_locked > 0) ? SDL_TRUE : SDL_FALSE; } @@ -359,8 +352,7 @@ SDL_JoystickID SDL_GetNextJoystickInstanceID() /* * Get the implementation dependent name of a joystick */ -const char * -SDL_JoystickNameForIndex(int device_index) +const char *SDL_JoystickNameForIndex(int device_index) { SDL_JoystickDriver *driver; const char *name = NULL; @@ -378,8 +370,7 @@ SDL_JoystickNameForIndex(int device_index) /* * Get the implementation dependent path of a joystick */ -const char * -SDL_JoystickPathForIndex(int device_index) +const char *SDL_JoystickPathForIndex(int device_index) { SDL_JoystickDriver *driver; const char *path = NULL; @@ -426,23 +417,30 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) MAKE_VIDPID(0x05a0, 0x3232), /* 8Bitdo Zero Gamepad */ }; + SDL_bool retval = SDL_FALSE; int i; Uint32 id = MAKE_VIDPID(SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick)); /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/ - if (joystick->naxes == 2) { - /* Assume D-pad or thumbstick style axes are centered at 0 */ - return SDL_TRUE; - } + SDL_LockJoysticks(); + { + if (joystick->naxes == 2) { + /* Assume D-pad or thumbstick style axes are centered at 0 */ + retval = SDL_TRUE; + } - for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) { - if (id == zero_centered_joysticks[i]) { - return SDL_TRUE; + for (i = 0; i < SDL_arraysize(zero_centered_joysticks); ++i) { + if (id == zero_centered_joysticks[i]) { + retval = SDL_TRUE; + break; + } } } - return SDL_FALSE; + SDL_UnlockJoysticks(); + + return retval; #endif /* __WINRT__ */ } @@ -453,8 +451,7 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) * * This function returns a joystick identifier, or NULL if an error occurred. */ -SDL_Joystick * -SDL_JoystickOpen(int device_index) +SDL_Joystick *SDL_JoystickOpen(int device_index) { SDL_JoystickDriver *driver; SDL_JoystickID instance_id; @@ -567,8 +564,7 @@ SDL_JoystickOpen(int device_index) return joystick; } -int SDL_JoystickAttachVirtual(SDL_JoystickType type, - int naxes, int nbuttons, int nhats) +int SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nbuttons, int nhats) { SDL_VirtualJoystickDesc desc; @@ -584,12 +580,12 @@ int SDL_JoystickAttachVirtual(SDL_JoystickType type, int SDL_JoystickAttachVirtualEx(const SDL_VirtualJoystickDesc *desc) { #if SDL_JOYSTICK_VIRTUAL - int result; + int retval; SDL_LockJoysticks(); - result = SDL_JoystickAttachVirtualInner(desc); + retval = SDL_JoystickAttachVirtualInner(desc); SDL_UnlockJoysticks(); - return result; + return retval; #else return SDL_SetError("SDL not built with virtual-joystick support"); #endif @@ -603,9 +599,9 @@ int SDL_JoystickDetachVirtual(int device_index) SDL_LockJoysticks(); if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { if (driver == &SDL_VIRTUAL_JoystickDriver) { - const int result = SDL_JoystickDetachVirtualInner(device_index); + const int retval = SDL_JoystickDetachVirtualInner(device_index); SDL_UnlockJoysticks(); - return result; + return retval; } } SDL_UnlockJoysticks(); @@ -616,8 +612,7 @@ int SDL_JoystickDetachVirtual(int device_index) #endif } -SDL_bool -SDL_JoystickIsVirtual(int device_index) +SDL_bool SDL_JoystickIsVirtual(int device_index) { #if SDL_JOYSTICK_VIRTUAL SDL_JoystickDriver *driver; @@ -640,49 +635,71 @@ SDL_JoystickIsVirtual(int device_index) int SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); #if SDL_JOYSTICK_VIRTUAL - return SDL_JoystickSetVirtualAxisInner(joystick, axis, value); + retval = SDL_JoystickSetVirtualAxisInner(joystick, axis, value); #else - return SDL_SetError("SDL not built with virtual-joystick support"); + retval = SDL_SetError("SDL not built with virtual-joystick support"); #endif + } + SDL_UnlockJoysticks(); + + return retval; } int SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); #if SDL_JOYSTICK_VIRTUAL - return SDL_JoystickSetVirtualButtonInner(joystick, button, value); + retval = SDL_JoystickSetVirtualButtonInner(joystick, button, value); #else - return SDL_SetError("SDL not built with virtual-joystick support"); + retval = SDL_SetError("SDL not built with virtual-joystick support"); #endif + } + SDL_UnlockJoysticks(); + + return retval; } int SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; + + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); #if SDL_JOYSTICK_VIRTUAL - return SDL_JoystickSetVirtualHatInner(joystick, hat, value); + retval = SDL_JoystickSetVirtualHatInner(joystick, hat, value); #else - return SDL_SetError("SDL not built with virtual-joystick support"); + retval = SDL_SetError("SDL not built with virtual-joystick support"); #endif + } + SDL_UnlockJoysticks(); + + return retval; } /* * Checks to make sure the joystick is valid. */ -SDL_bool -SDL_PrivateJoystickValid(SDL_Joystick *joystick) +SDL_bool SDL_PrivateJoystickValid(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - return SDL_TRUE; + SDL_AssertJoysticksLocked(); + return (joystick && joystick->magic == &joystick_magic); } -SDL_bool -SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *out) +SDL_bool SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *out) { SDL_JoystickDriver *driver; SDL_bool is_ok = SDL_FALSE; @@ -701,9 +718,17 @@ SDL_PrivateJoystickGetAutoGamepadMapping(int device_index, SDL_GamepadMapping *o */ int SDL_JoystickNumAxes(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->naxes; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->naxes; + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -711,9 +736,17 @@ int SDL_JoystickNumAxes(SDL_Joystick *joystick) */ int SDL_JoystickNumHats(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->nhats; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->nhats; + } + SDL_UnlockJoysticks(); + + return retval; } /* @@ -721,46 +754,66 @@ int SDL_JoystickNumHats(SDL_Joystick *joystick) */ int SDL_JoystickNumButtons(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; - return joystick->nbuttons; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->nbuttons; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Get the current state of an axis control on a joystick */ -Sint16 -SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) +Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) { Sint16 state; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - if (axis < joystick->naxes) { - state = joystick->axes[axis].value; - } else { - SDL_SetError("Joystick only has %d axes", joystick->naxes); - state = 0; + if (axis < joystick->naxes) { + state = joystick->axes[axis].value; + } else { + SDL_SetError("Joystick only has %d axes", joystick->naxes); + state = 0; + } } + SDL_UnlockJoysticks(); + return state; } /* * Get the initial state of an axis control on a joystick */ -SDL_bool -SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state) +SDL_bool SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; - if (axis >= joystick->naxes) { - SDL_SetError("Joystick only has %d axes", joystick->naxes); - return SDL_FALSE; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + + if (axis >= joystick->naxes) { + SDL_SetError("Joystick only has %d axes", joystick->naxes); + retval = SDL_FALSE; + } else { + if (state) { + *state = joystick->axes[axis].initial_value; + } + retval = joystick->axes[axis].has_initial_value; + } } - if (state) { - *state = joystick->axes[axis].initial_value; - } - return joystick->axes[axis].has_initial_value; + SDL_UnlockJoysticks(); + + return retval; } /* @@ -770,14 +823,19 @@ Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) { Uint8 state; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - if (hat < joystick->nhats) { - state = joystick->hats[hat]; - } else { - SDL_SetError("Joystick only has %d hats", joystick->nhats); - state = 0; + if (hat < joystick->nhats) { + state = joystick->hats[hat]; + } else { + SDL_SetError("Joystick only has %d hats", joystick->nhats); + state = 0; + } } + SDL_UnlockJoysticks(); + return state; } @@ -788,14 +846,19 @@ Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) { Uint8 state; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); - if (button < joystick->nbuttons) { - state = joystick->buttons[button]; - } else { - SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); - state = 0; + if (button < joystick->nbuttons) { + state = joystick->buttons[button]; + } else { + SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); + state = 0; + } } + SDL_UnlockJoysticks(); + return state; } @@ -803,30 +866,43 @@ Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) * Return if the joystick in question is currently attached to the system, * \return SDL_FALSE if not plugged in, SDL_TRUE if still present. */ -SDL_bool -SDL_JoystickGetAttached(SDL_Joystick *joystick) +SDL_bool SDL_JoystickGetAttached(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; - return joystick->attached; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + + retval = joystick->attached; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Get the instance id for this opened joystick */ -SDL_JoystickID -SDL_JoystickInstanceID(SDL_Joystick *joystick) +SDL_JoystickID SDL_JoystickInstanceID(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, -1); + SDL_JoystickID retval; - return joystick->instance_id; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = joystick->instance_id; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Return the SDL_Joystick associated with an instance id. */ -SDL_Joystick * -SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) +SDL_Joystick *SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) { SDL_Joystick *joystick; @@ -843,8 +919,7 @@ SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) /** * Return the SDL_Joystick associated with a player index. */ -SDL_Joystick * -SDL_JoystickFromPlayerIndex(int player_index) +SDL_Joystick *SDL_JoystickFromPlayerIndex(int player_index) { SDL_JoystickID instance_id; SDL_Joystick *joystick; @@ -863,27 +938,42 @@ SDL_JoystickFromPlayerIndex(int player_index) /* * Get the friendly name of this joystick */ -const char * -SDL_JoystickName(SDL_Joystick *joystick) +const char *SDL_JoystickName(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, NULL); + const char *retval; - return joystick->name; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + retval = joystick->name; + } + SDL_UnlockJoysticks(); + + return retval; } /* * Get the implementation dependent path of this joystick */ -const char * -SDL_JoystickPath(SDL_Joystick *joystick) +const char *SDL_JoystickPath(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, NULL); + const char *retval; - if (!joystick->path) { - SDL_Unsupported(); - return NULL; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + if (joystick->path) { + retval = joystick->path; + } else { + SDL_Unsupported(); + retval = NULL; + } } - return joystick->path; + SDL_UnlockJoysticks(); + + return retval; } /** @@ -891,15 +981,17 @@ SDL_JoystickPath(SDL_Joystick *joystick) */ int SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick) { - int player_index; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); - player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = SDL_GetPlayerIndexForJoystickID(joystick->instance_id); + } SDL_UnlockJoysticks(); - return player_index; + return retval; } /** @@ -907,166 +999,172 @@ int SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick) */ void SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index) { - CHECK_JOYSTICK_MAGIC(joystick, ); - SDL_LockJoysticks(); - SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id); + { + CHECK_JOYSTICK_MAGIC(joystick, ); + + SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id); + } SDL_UnlockJoysticks(); } int SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) { - int result; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); - if (low_frequency_rumble == joystick->low_frequency_rumble && - high_frequency_rumble == joystick->high_frequency_rumble) { - /* Just update the expiration */ - result = 0; - } else { - result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble); - joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS; - } + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - if (result == 0) { - joystick->low_frequency_rumble = low_frequency_rumble; - joystick->high_frequency_rumble = high_frequency_rumble; - - if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) { - joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); + if (low_frequency_rumble == joystick->low_frequency_rumble && + high_frequency_rumble == joystick->high_frequency_rumble) { + /* Just update the expiration */ + retval = 0; } else { - joystick->rumble_expiration = 0; - joystick->rumble_resend = 0; + retval = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble); + joystick->rumble_resend = SDL_GetTicks() + SDL_RUMBLE_RESEND_MS; + } + + if (retval == 0) { + joystick->low_frequency_rumble = low_frequency_rumble; + joystick->high_frequency_rumble = high_frequency_rumble; + + if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) { + joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); + if (!joystick->rumble_expiration) { + joystick->rumble_expiration = 1; + } + } else { + joystick->rumble_expiration = 0; + joystick->rumble_resend = 0; + } } } SDL_UnlockJoysticks(); - return result; + return retval; } int SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms) { - int result; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); - if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) { - /* Just update the expiration */ - result = 0; - } else { - result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble); - } + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - if (result == 0) { - joystick->left_trigger_rumble = left_rumble; - joystick->right_trigger_rumble = right_rumble; - - if ((left_rumble || right_rumble) && duration_ms) { - joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); + if (left_rumble == joystick->left_trigger_rumble && right_rumble == joystick->right_trigger_rumble) { + /* Just update the expiration */ + retval = 0; } else { - joystick->trigger_rumble_expiration = 0; + retval = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble); + } + + if (retval == 0) { + joystick->left_trigger_rumble = left_rumble; + joystick->right_trigger_rumble = right_rumble; + + if ((left_rumble || right_rumble) && duration_ms) { + joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS); + } else { + joystick->trigger_rumble_expiration = 0; + } } } SDL_UnlockJoysticks(); - return result; + return retval; } -SDL_bool -SDL_JoystickHasLED(SDL_Joystick *joystick) +SDL_bool SDL_JoystickHasLED(SDL_Joystick *joystick) { - SDL_bool result; - - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0; - + retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0; + } SDL_UnlockJoysticks(); - return result; + return retval; } -SDL_bool -SDL_JoystickHasRumble(SDL_Joystick *joystick) +SDL_bool SDL_JoystickHasRumble(SDL_Joystick *joystick) { - SDL_bool result; - - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0; - + retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0; + } SDL_UnlockJoysticks(); - return result; + return retval; } -SDL_bool -SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick) +SDL_bool SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick) { - SDL_bool result; - - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); + SDL_bool retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - result = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0; - + retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0; + } SDL_UnlockJoysticks(); - return result; + return retval; } int SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { - int result; + int retval; SDL_bool isfreshvalue; - CHECK_JOYSTICK_MAGIC(joystick, -1); - SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - isfreshvalue = red != joystick->led_red || - green != joystick->led_green || - blue != joystick->led_blue; + isfreshvalue = red != joystick->led_red || + green != joystick->led_green || + blue != joystick->led_blue; - if (isfreshvalue || SDL_GetTicks() >= joystick->led_expiration) { - result = joystick->driver->SetLED(joystick, red, green, blue); - joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS; - } else { - /* Avoid spamming the driver */ - result = 0; + if (isfreshvalue || SDL_GetTicks() >= joystick->led_expiration) { + retval = joystick->driver->SetLED(joystick, red, green, blue); + joystick->led_expiration = SDL_GetTicks() + SDL_LED_MIN_REPEAT_MS; + } else { + /* Avoid spamming the driver */ + retval = 0; + } + + /* Save the LED value regardless of success, so we don't spam the driver */ + joystick->led_red = red; + joystick->led_green = green; + joystick->led_blue = blue; } - - /* Save the LED value regardless of success, so we don't spam the driver */ - joystick->led_red = red; - joystick->led_green = green; - joystick->led_blue = blue; - SDL_UnlockJoysticks(); - return result; + return retval; } int SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) { - int result; - - CHECK_JOYSTICK_MAGIC(joystick, -1); + int retval; SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, -1); - result = joystick->driver->SendEffect(joystick, data, size); - + retval = joystick->driver->SendEffect(joystick, data, size); + } SDL_UnlockJoysticks(); - return result; + return retval; } /* @@ -1078,59 +1176,59 @@ void SDL_JoystickClose(SDL_Joystick *joystick) SDL_Joystick *joysticklistprev; int i; - CHECK_JOYSTICK_MAGIC(joystick, ); - SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, ); - /* First decrement ref count */ - if (--joystick->ref_count > 0) { - SDL_UnlockJoysticks(); - return; - } - - if (joystick->rumble_expiration) { - SDL_JoystickRumble(joystick, 0, 0, 0); - } - if (joystick->trigger_rumble_expiration) { - SDL_JoystickRumbleTriggers(joystick, 0, 0, 0); - } - - joystick->driver->Close(joystick); - joystick->hwdata = NULL; - joystick->magic = NULL; - - joysticklist = SDL_joysticks; - joysticklistprev = NULL; - while (joysticklist) { - if (joystick == joysticklist) { - if (joysticklistprev) { - /* unlink this entry */ - joysticklistprev->next = joysticklist->next; - } else { - SDL_joysticks = joystick->next; - } - break; + /* First decrement ref count */ + if (--joystick->ref_count > 0) { + SDL_UnlockJoysticks(); + return; } - joysticklistprev = joysticklist; - joysticklist = joysticklist->next; + + if (joystick->rumble_expiration) { + SDL_JoystickRumble(joystick, 0, 0, 0); + } + if (joystick->trigger_rumble_expiration) { + SDL_JoystickRumbleTriggers(joystick, 0, 0, 0); + } + + joystick->driver->Close(joystick); + joystick->hwdata = NULL; + joystick->magic = NULL; + + joysticklist = SDL_joysticks; + joysticklistprev = NULL; + while (joysticklist) { + if (joystick == joysticklist) { + if (joysticklistprev) { + /* unlink this entry */ + joysticklistprev->next = joysticklist->next; + } else { + SDL_joysticks = joystick->next; + } + break; + } + joysticklistprev = joysticklist; + joysticklist = joysticklist->next; + } + + SDL_free(joystick->name); + SDL_free(joystick->path); + SDL_free(joystick->serial); + + /* Free the data associated with this joystick */ + SDL_free(joystick->axes); + SDL_free(joystick->hats); + SDL_free(joystick->buttons); + for (i = 0; i < joystick->ntouchpads; i++) { + SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i]; + SDL_free(touchpad->fingers); + } + SDL_free(joystick->touchpads); + SDL_free(joystick->sensors); + SDL_free(joystick); } - - SDL_free(joystick->name); - SDL_free(joystick->path); - SDL_free(joystick->serial); - - /* Free the data associated with this joystick */ - SDL_free(joystick->axes); - SDL_free(joystick->hats); - SDL_free(joystick->buttons); - for (i = 0; i < joystick->ntouchpads; i++) { - SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i]; - SDL_free(touchpad->fingers); - } - SDL_free(joystick->touchpads); - SDL_free(joystick->sensors); - SDL_free(joystick); - SDL_UnlockJoysticks(); } @@ -1194,7 +1292,7 @@ void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers) int ntouchpads; SDL_JoystickTouchpadInfo *touchpads; - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); ntouchpads = joystick->ntouchpads + 1; touchpads = (SDL_JoystickTouchpadInfo *)SDL_realloc(joystick->touchpads, (ntouchpads * sizeof(SDL_JoystickTouchpadInfo))); @@ -1221,7 +1319,7 @@ void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, f int nsensors; SDL_JoystickSensorInfo *sensors; - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); nsensors = joystick->nsensors + 1; sensors = (SDL_JoystickSensorInfo *)SDL_realloc(joystick->sensors, (nsensors * sizeof(SDL_JoystickSensorInfo))); @@ -1343,7 +1441,7 @@ void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick) int i, j; Uint64 timestamp = SDL_GetTicksNS(); - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); /* Tell the app that everything is centered/unpressed... */ for (i = 0; i < joystick->naxes; i++) { @@ -1418,8 +1516,6 @@ int SDL_PrivateJoystickAxis(Uint64 timestamp, SDL_Joystick *joystick, Uint8 axis SDL_AssertJoysticksLocked(); - CHECK_JOYSTICK_MAGIC(joystick, 0); - /* Make sure we're not getting garbage or duplicate events */ if (axis >= joystick->naxes) { return 0; @@ -1486,8 +1582,6 @@ int SDL_PrivateJoystickHat(Uint64 timestamp, SDL_Joystick *joystick, Uint8 hat, SDL_AssertJoysticksLocked(); - CHECK_JOYSTICK_MAGIC(joystick, 0); - /* Make sure we're not getting garbage or duplicate events */ if (hat >= joystick->nhats) { return 0; @@ -1530,7 +1624,7 @@ int SDL_PrivateJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 bu #if !SDL_EVENTS_DISABLED SDL_Event event; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_AssertJoysticksLocked(); switch (state) { case SDL_PRESSED: @@ -1743,8 +1837,7 @@ static int PrefixMatch(const char *a, const char *b) return matchlen; } -char * -SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name) +char *SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name) { static struct { @@ -1883,8 +1976,7 @@ SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, c return name; } -SDL_JoystickGUID -SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data) +SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version, const char *name, Uint8 driver_signature, Uint8 driver_data) { SDL_JoystickGUID guid; Uint16 *guid16 = (Uint16 *)guid.data; @@ -1921,8 +2013,7 @@ SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version return guid; } -SDL_JoystickGUID -SDL_CreateJoystickGUIDForName(const char *name) +SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name) { return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, name, 0, 0); } @@ -1955,8 +2046,7 @@ void SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc) guid16[1] = SDL_SwapLE16(crc); } -SDL_GameControllerType -SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI) +SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI) { SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN; @@ -2051,8 +2141,7 @@ SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const return type; } -SDL_GameControllerType -SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name) +SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name) { SDL_GameControllerType type; Uint16 vendor, product; @@ -2076,15 +2165,13 @@ SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *nam return type; } -SDL_bool -SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_XBoxOneController; } -SDL_bool -SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_MICROSOFT) { if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 || @@ -2097,8 +2184,7 @@ SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_MICROSOFT) { if (product_id == USB_PRODUCT_XBOX_SERIES_X || @@ -2134,8 +2220,7 @@ SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_MICROSOFT) { if (product_id == USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH || @@ -2152,22 +2237,19 @@ SDL_IsJoystickBluetoothXboxOne(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickPS4(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_PS4Controller; } -SDL_bool -SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickPS5(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_PS5Controller; } -SDL_bool -SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id) { if (vendor_id == USB_VENDOR_SONY) { if (product_id == USB_PRODUCT_SONY_DS5_EDGE) { @@ -2177,86 +2259,73 @@ SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id) return SDL_FALSE; } -SDL_bool -SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchPro(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchProController || eType == k_eControllerType_SwitchInputOnlyController; } -SDL_bool -SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchProInputOnly(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchInputOnlyController; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyCon(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyCon(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchJoyConLeft || eType == k_eControllerType_SwitchJoyConRight; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConLeft(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConLeft(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchJoyConLeft; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConRight(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SwitchJoyConRight; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConGrip(Uint16 vendor_id, Uint16 product_id) { return vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP; } -SDL_bool -SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickNintendoSwitchJoyConPair(Uint16 vendor_id, Uint16 product_id) { return vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR; } -SDL_bool -SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) +SDL_bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id) { EControllerType eType = GuessControllerType(vendor_id, product_id); return eType == k_eControllerType_SteamController || eType == k_eControllerType_SteamControllerV2; } -SDL_bool -SDL_IsJoystickXInput(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickXInput(SDL_JoystickGUID guid) { return (guid.data[14] == 'x') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickWGI(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickWGI(SDL_JoystickGUID guid) { return (guid.data[14] == 'w') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickHIDAPI(SDL_JoystickGUID guid) { return (guid.data[14] == 'h') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickRAWINPUT(SDL_JoystickGUID guid) { return (guid.data[14] == 'r') ? SDL_TRUE : SDL_FALSE; } -SDL_bool -SDL_IsJoystickVirtual(SDL_JoystickGUID guid) +SDL_bool SDL_IsJoystickVirtual(SDL_JoystickGUID guid) { return (guid.data[14] == 'v') ? SDL_TRUE : SDL_FALSE; } @@ -2699,11 +2768,19 @@ int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id) SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick) { - static SDL_JoystickGUID emptyGUID; + SDL_JoystickGUID retval; - CHECK_JOYSTICK_MAGIC(joystick, emptyGUID); + SDL_LockJoysticks(); + { + static SDL_JoystickGUID emptyGUID; - return joystick->guid; + CHECK_JOYSTICK_MAGIC(joystick, emptyGUID); + + retval = joystick->guid; + } + SDL_UnlockJoysticks(); + + return retval; } Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick) @@ -2735,16 +2812,32 @@ Uint16 SDL_JoystickGetProductVersion(SDL_Joystick *joystick) Uint16 SDL_JoystickGetFirmwareVersion(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, 0); + Uint16 retval; - return joystick->firmware_version; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, 0); + + retval = joystick->firmware_version; + } + SDL_UnlockJoysticks(); + + return retval; } const char *SDL_JoystickGetSerial(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, NULL); + const char *retval; - return joystick->serial; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, NULL); + + retval = joystick->serial; + } + SDL_UnlockJoysticks(); + + return retval; } SDL_JoystickType SDL_JoystickGetType(SDL_Joystick *joystick) @@ -2754,9 +2847,15 @@ SDL_JoystickType SDL_JoystickGetType(SDL_Joystick *joystick) type = SDL_GetJoystickGUIDType(guid); if (type == SDL_JOYSTICK_TYPE_UNKNOWN) { - if (joystick && joystick->is_game_controller) { - type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_TYPE_UNKNOWN); + + if (joystick->is_game_controller) { + type = SDL_JOYSTICK_TYPE_GAMECONTROLLER; + } } + SDL_UnlockJoysticks(); } return type; } @@ -2776,7 +2875,7 @@ SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID) /* update the power level for this joystick */ void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel) { - CHECK_JOYSTICK_MAGIC(joystick, ); + SDL_AssertJoysticksLocked(); SDL_assert(joystick->ref_count); /* make sure we are calling this only for update, not for initialization */ if (ePowerLevel != joystick->epowerlevel) { @@ -2797,9 +2896,17 @@ void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLe /* return its power level */ SDL_JoystickPowerLevel SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick) { - CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_POWER_UNKNOWN); + SDL_JoystickPowerLevel retval; - return joystick->epowerlevel; + SDL_LockJoysticks(); + { + CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_POWER_UNKNOWN); + + retval = joystick->epowerlevel; + } + SDL_UnlockJoysticks(); + + return retval; } int SDL_PrivateJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure) @@ -2809,7 +2916,7 @@ int SDL_PrivateJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, int to int posted; Uint32 event_type; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_AssertJoysticksLocked(); if (touchpad < 0 || touchpad >= joystick->ntouchpads) { return 0; @@ -2898,7 +3005,7 @@ int SDL_PrivateJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_Sens int i; int posted = 0; - CHECK_JOYSTICK_MAGIC(joystick, 0); + SDL_AssertJoysticksLocked(); /* We ignore events if we don't have keyboard focus */ if (SDL_PrivateJoystickShouldIgnoreEvent()) { diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 76ad2a473..1127de84d 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -47,7 +47,7 @@ extern SDL_bool SDL_JoysticksQuitting(void); extern SDL_bool SDL_JoysticksLocked(void); /* Make sure we currently have the joysticks locked */ -extern void SDL_AssertJoysticksLocked(void); +extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_lock); /* Function to get the next available joystick instance ID */ extern SDL_JoystickID SDL_GetNextJoystickInstanceID(void); diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 5c0be7b23..db2209ffe 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -65,61 +65,65 @@ typedef struct _SDL_JoystickSensorInfo float data[3]; /* If this needs to expand, update SDL_ControllerSensorEvent */ } SDL_JoystickSensorInfo; +#define _guarded SDL_GUARDED_BY(SDL_joystick_lock) + struct _SDL_Joystick { - const void *magic; + const void *magic _guarded; - SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */ - char *name; /* Joystick name - system dependent */ - char *path; /* Joystick path - system dependent */ - char *serial; /* Joystick serial */ - SDL_JoystickGUID guid; /* Joystick guid */ - Uint16 firmware_version; /* Firmware version, if available */ + SDL_JoystickID instance_id _guarded; /* Device instance, monotonically increasing from 0 */ + char *name _guarded; /* Joystick name - system dependent */ + char *path _guarded; /* Joystick path - system dependent */ + char *serial _guarded; /* Joystick serial */ + SDL_JoystickGUID guid _guarded; /* Joystick guid */ + Uint16 firmware_version _guarded; /* Firmware version, if available */ - int naxes; /* Number of axis controls on the joystick */ - SDL_JoystickAxisInfo *axes; + int naxes _guarded; /* Number of axis controls on the joystick */ + SDL_JoystickAxisInfo *axes _guarded; - int nhats; /* Number of hats on the joystick */ - Uint8 *hats; /* Current hat states */ + int nhats _guarded; /* Number of hats on the joystick */ + Uint8 *hats _guarded; /* Current hat states */ - int nbuttons; /* Number of buttons on the joystick */ - Uint8 *buttons; /* Current button states */ + int nbuttons _guarded; /* Number of buttons on the joystick */ + Uint8 *buttons _guarded; /* Current button states */ - int ntouchpads; /* Number of touchpads on the joystick */ - SDL_JoystickTouchpadInfo *touchpads; /* Current touchpad states */ + int ntouchpads _guarded; /* Number of touchpads on the joystick */ + SDL_JoystickTouchpadInfo *touchpads _guarded; /* Current touchpad states */ - int nsensors; /* Number of sensors on the joystick */ - int nsensors_enabled; - SDL_JoystickSensorInfo *sensors; + int nsensors _guarded; /* Number of sensors on the joystick */ + int nsensors_enabled _guarded; + SDL_JoystickSensorInfo *sensors _guarded; - Uint16 low_frequency_rumble; - Uint16 high_frequency_rumble; - Uint64 rumble_expiration; - Uint64 rumble_resend; + Uint16 low_frequency_rumble _guarded; + Uint16 high_frequency_rumble _guarded; + Uint64 rumble_expiration _guarded; + Uint64 rumble_resend _guarded; - Uint16 left_trigger_rumble; - Uint16 right_trigger_rumble; - Uint64 trigger_rumble_expiration; + Uint16 left_trigger_rumble _guarded; + Uint16 right_trigger_rumble _guarded; + Uint64 trigger_rumble_expiration _guarded; - Uint8 led_red; - Uint8 led_green; - Uint8 led_blue; - Uint64 led_expiration; + Uint8 led_red _guarded; + Uint8 led_green _guarded; + Uint8 led_blue _guarded; + Uint64 led_expiration _guarded; - SDL_bool attached; - SDL_bool is_game_controller; - SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */ - SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */ + SDL_bool attached _guarded; + SDL_bool is_game_controller _guarded; + SDL_bool delayed_guide_button _guarded; /* SDL_TRUE if this device has the guide button event delayed */ + SDL_JoystickPowerLevel epowerlevel _guarded; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */ - struct _SDL_JoystickDriver *driver; + struct _SDL_JoystickDriver *driver _guarded; - struct joystick_hwdata *hwdata; /* Driver dependent information */ + struct joystick_hwdata *hwdata _guarded; /* Driver dependent information */ - int ref_count; /* Reference count for multiple opens */ + int ref_count _guarded; /* Reference count for multiple opens */ - struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */ + struct _SDL_Joystick *next _guarded; /* pointer to next joystick we have allocated */ }; +#undef _guarded + /* Device bus definitions */ #define SDL_HARDWARE_BUS_UNKNOWN 0x00 #define SDL_HARDWARE_BUS_USB 0x03 diff --git a/src/joystick/hidapi/SDL_hidapi_combined.c b/src/joystick/hidapi/SDL_hidapi_combined.c index eee0e0b33..9e70622a0 100644 --- a/src/joystick/hidapi/SDL_hidapi_combined.c +++ b/src/joystick/hidapi/SDL_hidapi_combined.c @@ -65,6 +65,8 @@ static SDL_bool HIDAPI_DriverCombined_OpenJoystick(SDL_HIDAPI_Device *device, SD char *serial = NULL, *new_serial; size_t serial_length = 0, new_length; + SDL_AssertJoysticksLocked(); + for (i = 0; i < device->num_children; ++i) { SDL_HIDAPI_Device *child = device->children[i]; if (!child->driver->OpenJoystick(child, joystick)) { diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 29f7f4321..eec0cf1a8 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -409,6 +409,9 @@ static SDL_bool HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_Device *device, SD { SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context; Uint8 i; + + SDL_AssertJoysticksLocked(); + for (i = 0; i < MAX_CONTROLLERS; i += 1) { if (joystick->instance_id == ctx->joysticks[i]) { joystick->nbuttons = 12; @@ -425,6 +428,8 @@ static int HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_J SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context; Uint8 i, val; + SDL_AssertJoysticksLocked(); + if (ctx->pc_mode) { return SDL_Unsupported(); } @@ -470,6 +475,8 @@ static Uint32 HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *d SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context; Uint32 result = 0; + SDL_AssertJoysticksLocked(); + if (!ctx->pc_mode) { Uint8 i; diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index 66cc7ab4a..f33cc0302 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -97,6 +97,8 @@ static SDL_bool HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Jo { SDL_DriverLuna_Context *ctx = (SDL_DriverLuna_Context *)device->context; + SDL_AssertJoysticksLocked(); + SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index 188231c4e..7a2d16ef4 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -229,6 +229,8 @@ static SDL_bool HIDAPI_DriverPS3_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy { SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; ctx->effects_updated = SDL_FALSE; ctx->rumble_left = 0; @@ -627,6 +629,8 @@ static SDL_bool HIDAPI_DriverPS3ThirdParty_OpenJoystick(SDL_HIDAPI_Device *devic { SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; SDL_zeroa(ctx->last_state); diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index facb6ff0c..d580b25f4 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -664,6 +664,8 @@ static SDL_bool HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy { SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; ctx->last_packet = SDL_GetTicks(); ctx->report_sensors = SDL_FALSE; diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 651ea5270..a87b8a16d 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -818,6 +818,8 @@ static SDL_bool HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy { SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; ctx->last_packet = SDL_GetTicks(); ctx->report_sensors = SDL_FALSE; @@ -957,7 +959,7 @@ static int HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Jo SDL_memcpy(&data[report_size - sizeof(unCRC)], &unCRC, sizeof(unCRC)); } - if (SDL_HIDAPI_LockRumble() < 0) { + if (SDL_HIDAPI_LockRumble() != 0) { return -1; } diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c index 2c9edbc26..086efc035 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.c +++ b/src/joystick/hidapi/SDL_hidapi_rumble.c @@ -44,13 +44,13 @@ typedef struct SDL_HIDAPI_RumbleContext SDL_atomic_t initialized; SDL_atomic_t running; SDL_Thread *thread; - SDL_mutex *lock; SDL_sem *request_sem; SDL_HIDAPI_RumbleRequest *requests_head; SDL_HIDAPI_RumbleRequest *requests_tail; } SDL_HIDAPI_RumbleContext; -static SDL_HIDAPI_RumbleContext rumble_context; +SDL_mutex *SDL_HIDAPI_rumble_lock; +static SDL_HIDAPI_RumbleContext rumble_context SDL_GUARDED_BY(SDL_HIDAPI_rumble_lock); static int SDLCALL SDL_HIDAPI_RumbleThread(void *data) { @@ -63,7 +63,7 @@ static int SDLCALL SDL_HIDAPI_RumbleThread(void *data) SDL_SemWait(ctx->request_sem); - SDL_LockMutex(ctx->lock); + SDL_LockMutex(SDL_HIDAPI_rumble_lock); request = ctx->requests_tail; if (request) { if (request == ctx->requests_head) { @@ -71,7 +71,7 @@ static int SDLCALL SDL_HIDAPI_RumbleThread(void *data) } ctx->requests_tail = request->prev; } - SDL_UnlockMutex(ctx->lock); + SDL_UnlockMutex(SDL_HIDAPI_rumble_lock); if (request) { SDL_LockMutex(request->device->dev_lock); @@ -109,7 +109,7 @@ static void SDL_HIDAPI_StopRumbleThread(SDL_HIDAPI_RumbleContext *ctx) ctx->thread = NULL; } - SDL_LockMutex(ctx->lock); + SDL_LockMutex(SDL_HIDAPI_rumble_lock); while (ctx->requests_tail) { request = ctx->requests_tail; if (request == ctx->requests_head) { @@ -123,16 +123,16 @@ static void SDL_HIDAPI_StopRumbleThread(SDL_HIDAPI_RumbleContext *ctx) (void)SDL_AtomicDecRef(&request->device->rumble_pending); SDL_free(request); } - SDL_UnlockMutex(ctx->lock); + SDL_UnlockMutex(SDL_HIDAPI_rumble_lock); if (ctx->request_sem) { SDL_DestroySemaphore(ctx->request_sem); ctx->request_sem = NULL; } - if (ctx->lock) { - SDL_DestroyMutex(ctx->lock); - ctx->lock = NULL; + if (SDL_HIDAPI_rumble_lock) { + SDL_DestroyMutex(SDL_HIDAPI_rumble_lock); + SDL_HIDAPI_rumble_lock = NULL; } SDL_AtomicSet(&ctx->initialized, SDL_FALSE); @@ -140,8 +140,8 @@ static void SDL_HIDAPI_StopRumbleThread(SDL_HIDAPI_RumbleContext *ctx) static int SDL_HIDAPI_StartRumbleThread(SDL_HIDAPI_RumbleContext *ctx) { - ctx->lock = SDL_CreateMutex(); - if (!ctx->lock) { + SDL_HIDAPI_rumble_lock = SDL_CreateMutex(); + if (!SDL_HIDAPI_rumble_lock) { SDL_HIDAPI_StopRumbleThread(ctx); return -1; } @@ -171,7 +171,8 @@ int SDL_HIDAPI_LockRumble(void) } } - return SDL_LockMutex(ctx->lock); + SDL_LockMutex(SDL_HIDAPI_rumble_lock); + return 0; } SDL_bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size) @@ -239,9 +240,7 @@ int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const void SDL_HIDAPI_UnlockRumble(void) { - SDL_HIDAPI_RumbleContext *ctx = &rumble_context; - - SDL_UnlockMutex(ctx->lock); + SDL_UnlockMutex(SDL_HIDAPI_rumble_lock); } int SDL_HIDAPI_SendRumble(SDL_HIDAPI_Device *device, const Uint8 *data, int size) @@ -254,7 +253,7 @@ int SDL_HIDAPI_SendRumble(SDL_HIDAPI_Device *device, const Uint8 *data, int size return SDL_SetError("Tried to send rumble with invalid size"); } - if (SDL_HIDAPI_LockRumble() < 0) { + if (SDL_HIDAPI_LockRumble() != 0) { return -1; } diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.h b/src/joystick/hidapi/SDL_hidapi_rumble.h index d6fae94e0..a2ffd5220 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.h +++ b/src/joystick/hidapi/SDL_hidapi_rumble.h @@ -25,12 +25,15 @@ /* Handle rumble on a separate thread so it doesn't block the application */ /* Advanced API */ -int SDL_HIDAPI_LockRumble(void); +#ifdef SDL_THREAD_SAFETY_ANALYSIS +extern SDL_mutex *SDL_HIDAPI_rumble_lock; +#endif +int SDL_HIDAPI_LockRumble(void) SDL_TRY_ACQUIRE(0, SDL_HIDAPI_rumble_lock); SDL_bool SDL_HIDAPI_GetPendingRumbleLocked(SDL_HIDAPI_Device *device, Uint8 **data, int **size, int *maximum_size); -int SDL_HIDAPI_SendRumbleAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size); +int SDL_HIDAPI_SendRumbleAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size) SDL_RELEASE(SDL_HIDAPI_rumble_lock); typedef void (*SDL_HIDAPI_RumbleSentCallback)(void *userdata); -int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size, SDL_HIDAPI_RumbleSentCallback callback, void *userdata); -void SDL_HIDAPI_UnlockRumble(void); +int SDL_HIDAPI_SendRumbleWithCallbackAndUnlock(SDL_HIDAPI_Device *device, const Uint8 *data, int size, SDL_HIDAPI_RumbleSentCallback callback, void *userdata) SDL_RELEASE(SDL_HIDAPI_rumble_lock); +void SDL_HIDAPI_UnlockRumble(void) SDL_RELEASE(SDL_HIDAPI_rumble_lock); /* Simple API, will replace any pending rumble with the new data */ int SDL_HIDAPI_SendRumble(SDL_HIDAPI_Device *device, const Uint8 *data, int size); diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 3a9becb71..e440639f4 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -144,7 +144,7 @@ static int HIDAPI_DriverShield_SendCommand(SDL_HIDAPI_Device *device, Uint8 cmd, return SDL_SetError("Command data exceeds HID report size"); } - if (SDL_HIDAPI_LockRumble() < 0) { + if (SDL_HIDAPI_LockRumble() != 0) { return -1; } @@ -171,6 +171,8 @@ static SDL_bool HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ { SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->rumble_report_pending = SDL_FALSE; ctx->rumble_update_pending = SDL_FALSE; ctx->left_motor_amplitude = 0; diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index f7209160a..1330370c3 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -93,6 +93,8 @@ static SDL_bool HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ { SDL_DriverStadia_Context *ctx = (SDL_DriverStadia_Context *)device->context; + SDL_AssertJoysticksLocked(); + SDL_zeroa(ctx->last_state); /* Initialize the joystick capabilities */ diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index d5175c091..7bb088964 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1008,6 +1008,8 @@ static SDL_bool HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_J SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context; float update_rate_in_hz = 0.0f; + SDL_AssertJoysticksLocked(); + ctx->report_sensors = SDL_FALSE; SDL_zero(ctx->m_assembler); SDL_zero(ctx->m_state); diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index feea3f999..9749d57cb 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -319,7 +319,7 @@ static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int siz return SDL_hid_write(ctx->device->dev, data, size); #else /* Use the rumble thread for general asynchronous writes */ - if (SDL_HIDAPI_LockRumble() < 0) { + if (SDL_HIDAPI_LockRumble() != 0) { return -1; } return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size); @@ -1247,6 +1247,8 @@ static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; Uint8 input_mode; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; ctx->m_bSyncWrite = SDL_TRUE; @@ -1887,7 +1889,7 @@ static void HandleMiniControllerStateR(Uint64 timestamp, SDL_Joystick *joystick, SDL_PrivateJoystickAxis(timestamp, joystick, SDL_CONTROLLER_AXIS_LEFTX, axis); } -static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet) +static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet) SDL_NO_THREAD_SAFETY_ANALYSIS /* We unlock and lock the device lock to be able to change IMU state */ { Uint64 timestamp = SDL_GetTicksNS(); diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 9e8bafb13..903dab660 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -217,7 +217,7 @@ static SDL_bool WriteOutput(SDL_DriverWii_Context *ctx, const Uint8 *data, int s return SDL_hid_write(ctx->device->dev, data, size) >= 0; } else { /* Use the rumble thread for general asynchronous writes */ - if (SDL_HIDAPI_LockRumble() < 0) { + if (SDL_HIDAPI_LockRumble() != 0) { return SDL_FALSE; } return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size) >= 0; @@ -762,6 +762,8 @@ static SDL_bool HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy { SDL_DriverWii_Context *ctx = (SDL_DriverWii_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; InitializeExtension(ctx); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index 2098dd7c3..f85739674 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -172,6 +172,8 @@ static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL { SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->joystick = joystick; SDL_zeroa(ctx->last_state); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 8e8f31c49..80400409f 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -171,6 +171,8 @@ static SDL_bool HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SD { SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context; + SDL_AssertJoysticksLocked(); + SDL_zeroa(ctx->last_state); /* Initialize player index (needed for setting LEDs) */ diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index d95454a23..a1af5a5ed 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -230,7 +230,7 @@ static void SendAckIfNeeded(SDL_HIDAPI_Device *device, const Uint8 *data, int si #ifdef DEBUG_XBOX_PROTOCOL HIDAPI_DumpPacket("Xbox One sending ACK packet: size = %d", ack_packet, sizeof(ack_packet)); #endif - if (SDL_HIDAPI_LockRumble() < 0 || + if (SDL_HIDAPI_LockRumble() != 0 || SDL_HIDAPI_SendRumbleAndUnlock(device, ack_packet, sizeof(ack_packet)) != sizeof(ack_packet)) { SDL_SetError("Couldn't send ack packet"); } @@ -250,7 +250,7 @@ static SDL_bool SendSerialRequest(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_C * It will cancel the announce packet if sent before that, and will be * ignored if sent during the negotiation. */ - if (SDL_HIDAPI_LockRumble() < 0 || + if (SDL_HIDAPI_LockRumble() != 0 || SDL_HIDAPI_SendRumbleAndUnlock(device, serial_packet, sizeof(serial_packet)) != sizeof(serial_packet)) { SDL_SetError("Couldn't send serial packet"); return SDL_FALSE; @@ -308,7 +308,7 @@ static SDL_bool SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_ #endif ctx->send_time = SDL_GetTicks(); - if (SDL_HIDAPI_LockRumble() < 0 || + if (SDL_HIDAPI_LockRumble() != 0 || SDL_HIDAPI_SendRumbleAndUnlock(device, init_packet, packet->size) != packet->size) { SDL_SetError("Couldn't write Xbox One initialization packet"); return SDL_FALSE; @@ -411,6 +411,8 @@ static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL { SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context; + SDL_AssertJoysticksLocked(); + ctx->low_frequency_rumble = 0; ctx->high_frequency_rumble = 0; ctx->left_trigger_rumble = 0; @@ -474,7 +476,7 @@ static int HIDAPI_DriverXboxOne_UpdateRumble(SDL_HIDAPI_Device *device) /* We're no longer pending, even if we fail to send the rumble below */ ctx->rumble_pending = SDL_FALSE; - if (SDL_HIDAPI_LockRumble() < 0) { + if (SDL_HIDAPI_LockRumble() != 0) { return -1; } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 8cf17e2ea..f46def18a 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -86,7 +86,7 @@ static int SDL_HIDAPI_numdrivers = 0; static SDL_SpinLock SDL_HIDAPI_spinlock; static SDL_bool SDL_HIDAPI_hints_changed = SDL_FALSE; static Uint32 SDL_HIDAPI_change_count = 0; -static SDL_HIDAPI_Device *SDL_HIDAPI_devices; +static SDL_HIDAPI_Device *SDL_HIDAPI_devices SDL_GUARDED_BY(SDL_joystick_lock); static int SDL_HIDAPI_numjoysticks = 0; static SDL_bool SDL_HIDAPI_combine_joycons = SDL_TRUE; static SDL_bool initialized = SDL_FALSE; @@ -259,6 +259,8 @@ static SDL_HIDAPI_Device *HIDAPI_GetDeviceByIndex(int device_index, SDL_Joystick { SDL_HIDAPI_Device *device; + SDL_AssertJoysticksLocked(); + for (device = SDL_HIDAPI_devices; device; device = device->next) { if (device->parent) { continue; @@ -280,6 +282,8 @@ static SDL_HIDAPI_Device *HIDAPI_GetJoystickByInfo(const char *path, Uint16 vend { SDL_HIDAPI_Device *device; + SDL_AssertJoysticksLocked(); + for (device = SDL_HIDAPI_devices; device; device = device->next) { if (device->vendor_id == vendor_id && device->product_id == product_id && SDL_strcmp(device->path, path) == 0) { @@ -318,7 +322,7 @@ static void HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device) SDL_UnlockMutex(device->dev_lock); } -static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *removed) +static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *removed) SDL_NO_THREAD_SAFETY_ANALYSIS /* We unlock the joystick lock to be able to open the HID device on Android */ { *removed = SDL_FALSE; @@ -421,6 +425,8 @@ static void SDL_HIDAPI_UpdateDrivers(void) SDL_HIDAPI_Device *device; SDL_bool removed; + SDL_AssertJoysticksLocked(); + SDL_HIDAPI_numdrivers = 0; for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) { SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i]; @@ -566,6 +572,8 @@ HIDAPI_HasConnectedUSBDevice(const char *serial) { SDL_HIDAPI_Device *device; + SDL_AssertJoysticksLocked(); + if (serial == NULL) { return SDL_FALSE; } @@ -590,6 +598,8 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial) { SDL_HIDAPI_Device *device; + SDL_AssertJoysticksLocked(); + if (serial == NULL) { return; } @@ -617,6 +627,8 @@ HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID) int i, j; SDL_JoystickID joystickID; + SDL_AssertJoysticksLocked(); + for (i = 0; i < device->num_children; ++i) { SDL_HIDAPI_Device *child = device->children[i]; for (j = child->num_joysticks; j--;) { @@ -712,6 +724,8 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf SDL_HIDAPI_Device *curr, *last = NULL; SDL_bool removed; + SDL_AssertJoysticksLocked(); + for (curr = SDL_HIDAPI_devices, last = NULL; curr; last = curr, curr = curr->next) { } @@ -805,6 +819,8 @@ static void HIDAPI_DelDevice(SDL_HIDAPI_Device *device) SDL_HIDAPI_Device *curr, *last; int i; + SDL_AssertJoysticksLocked(); + #ifdef DEBUG_HIDAPI SDL_Log("Removing HIDAPI device '%s' VID 0x%.4x, PID 0x%.4x, version %d, serial %s, interface %d, interface_class %d, interface_subclass %d, interface_protocol %d, usage page 0x%.4x, usage 0x%.4x, path = %s, driver = %s (%s)\n", device->name, device->vendor_id, device->product_id, device->version, device->serial ? device->serial : "NONE", device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol, device->usage_page, device->usage, device->path, device->driver ? device->driver->name : "NONE", device->driver && device->driver->enabled ? "ENABLED" : "DISABLED"); #endif @@ -844,6 +860,8 @@ static SDL_bool HIDAPI_CreateCombinedJoyCons() SDL_HIDAPI_Device *device, *combined; SDL_HIDAPI_Device *joycons[2] = { NULL, NULL }; + SDL_AssertJoysticksLocked(); + if (!SDL_HIDAPI_combine_joycons) { return SDL_FALSE; } @@ -1155,6 +1173,8 @@ void HIDAPI_UpdateDevices(void) { SDL_HIDAPI_Device *device; + SDL_AssertJoysticksLocked(); + /* Update the devices, which may change connected joysticks and send events */ /* Prepare the existing device list */ @@ -1257,6 +1277,8 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_HIDAPI_Device *device = HIDAPI_GetDeviceByIndex(device_index, &joystickID); struct joystick_hwdata *hwdata; + SDL_AssertJoysticksLocked(); + if (device == NULL || !device->driver) { /* This should never happen - validated before being called */ return SDL_SetError("Couldn't find HIDAPI device at index %d\n", device_index); @@ -1294,6 +1316,8 @@ static int HIDAPI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_ru { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; @@ -1309,6 +1333,8 @@ static int HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rum { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; @@ -1324,6 +1350,8 @@ static Uint32 HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick) { Uint32 result = 0; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; @@ -1337,6 +1365,8 @@ static int HIDAPI_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; @@ -1352,6 +1382,8 @@ static int HIDAPI_JoystickSendEffect(SDL_Joystick *joystick, const void *data, i { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; @@ -1367,6 +1399,8 @@ static int HIDAPI_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool ena { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; @@ -1383,8 +1417,10 @@ static void HIDAPI_JoystickUpdate(SDL_Joystick *joystick) /* This is handled in SDL_HIDAPI_UpdateDevices() */ } -static void HIDAPI_JoystickClose(SDL_Joystick *joystick) +static void HIDAPI_JoystickClose(SDL_Joystick *joystick) SDL_NO_THREAD_SAFETY_ANALYSIS /* We unlock the device lock so rumble can complete */ { + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { SDL_HIDAPI_Device *device = joystick->hwdata->device; int i; @@ -1415,6 +1451,8 @@ static void HIDAPI_JoystickQuit(void) { int i; + SDL_AssertJoysticksLocked(); + shutting_down = SDL_TRUE; SDL_HIDAPI_QuitRumble(); diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 8df434b58..caf5fc1b8 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -848,6 +848,8 @@ static int allocate_hatdata(SDL_Joystick *joystick) { int i; + SDL_AssertJoysticksLocked(); + joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(joystick->nhats * sizeof(struct hwdata_hat)); @@ -904,6 +906,8 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd) SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE); SDL_bool use_hat_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_HAT_DEADZONES, SDL_TRUE); + SDL_AssertJoysticksLocked(); + /* See if this device uses the new unified event API */ if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && @@ -1103,6 +1107,8 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd) on error. Returns -1 on error, 0 on success. */ static int PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item) { + SDL_AssertJoysticksLocked(); + joystick->hwdata->item = item; joystick->hwdata->guid = item->guid; joystick->hwdata->effect.id = -1; @@ -1151,6 +1157,8 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) { SDL_joylist_item *item = JoystickByDevIndex(device_index); + SDL_AssertJoysticksLocked(); + if (item == NULL) { return SDL_SetError("No such device"); } @@ -1181,6 +1189,8 @@ static int LINUX_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rum { struct input_event event; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->ff_rumble) { struct ff_effect *effect = &joystick->hwdata->effect; @@ -1227,6 +1237,8 @@ static Uint32 LINUX_JoystickGetCapabilities(SDL_Joystick *joystick) { Uint32 result = 0; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) { result |= SDL_JOYCAP_RUMBLE; } @@ -1251,7 +1263,7 @@ static int LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enab static void HandleHat(Uint64 timestamp, SDL_Joystick *stick, int hatidx, int axis, int value) { - const int hatnum = stick->hwdata->hats_indices[hatidx]; + int hatnum; struct hwdata_hat *the_hat; struct hat_axis_correct *correct; const Uint8 position_map[3][3] = { @@ -1260,6 +1272,9 @@ static void HandleHat(Uint64 timestamp, SDL_Joystick *stick, int hatidx, int axi { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } }; + SDL_AssertJoysticksLocked(); + + hatnum = stick->hwdata->hats_indices[hatidx]; the_hat = &stick->hwdata->hats[hatnum]; correct = &stick->hwdata->hat_correct[hatidx]; /* Hopefully we detected any analog axes and left them as is rather than trying @@ -1299,6 +1314,8 @@ static int AxisCorrect(SDL_Joystick *joystick, int which, int value) { struct axis_correct *correct; + SDL_AssertJoysticksLocked(); + correct = &joystick->hwdata->abs_correct[which]; if (correct->minimum != correct->maximum) { if (correct->use_deadzones) { @@ -1334,6 +1351,8 @@ static void PollAllValues(Uint64 timestamp, SDL_Joystick *joystick) unsigned long keyinfo[NBITS(KEY_MAX)]; int i; + SDL_AssertJoysticksLocked(); + /* Poll all axis */ for (i = ABS_X; i < ABS_MAX; i++) { /* We don't need to test for digital hats here, they won't have has_abs[] set */ @@ -1388,6 +1407,8 @@ static void HandleInputEvents(SDL_Joystick *joystick) struct input_event events[32]; int i, len, code, hat_index; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->fresh) { PollAllValues(SDL_GetTicksNS(), joystick); joystick->hwdata->fresh = SDL_FALSE; @@ -1471,6 +1492,8 @@ static void HandleClassicEvents(SDL_Joystick *joystick) int i, len, code, hat_index; Uint64 timestamp = SDL_GetTicksNS(); + SDL_AssertJoysticksLocked(); + joystick->hwdata->fresh = SDL_FALSE; while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) { len /= sizeof(events[0]); @@ -1511,6 +1534,8 @@ static void HandleClassicEvents(SDL_Joystick *joystick) static void LINUX_JoystickUpdate(SDL_Joystick *joystick) { + SDL_AssertJoysticksLocked(); + if (joystick->hwdata->m_bSteamController) { SDL_UpdateSteamController(joystick); return; @@ -1526,6 +1551,8 @@ static void LINUX_JoystickUpdate(SDL_Joystick *joystick) /* Function to close a joystick after use */ static void LINUX_JoystickClose(SDL_Joystick *joystick) { + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { if (joystick->hwdata->effect.id >= 0) { ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id); @@ -1585,6 +1612,8 @@ static SDL_bool LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap SDL_joylist_item *item = JoystickByDevIndex(device_index); unsigned int mapped; + SDL_AssertJoysticksLocked(); + if (item->checked_mapping) { if (item->mapping) { SDL_memcpy(out, item->mapping, sizeof(*out)); diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index 595b663ad..fba56048d 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -28,32 +28,36 @@ #include "../SDL_sysjoystick.h" #include "../SDL_joystick_c.h" -static joystick_hwdata *g_VJoys = NULL; +static joystick_hwdata *g_VJoys SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static joystick_hwdata *VIRTUAL_HWDataForIndex(int device_index) { - joystick_hwdata *vjoy = g_VJoys; - while (vjoy) { + joystick_hwdata *vjoy; + + SDL_AssertJoysticksLocked(); + + for (vjoy = g_VJoys; vjoy; vjoy = vjoy->next) { if (device_index == 0) { break; } --device_index; - vjoy = vjoy->next; } return vjoy; } static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata) { - joystick_hwdata *cur = g_VJoys; + joystick_hwdata *cur; joystick_hwdata *prev = NULL; + SDL_AssertJoysticksLocked(); + if (hwdata == NULL) { return; } /* Remove hwdata from SDL-global list */ - while (cur) { + for (cur = g_VJoys; cur; prev = cur, cur = cur->next) { if (hwdata == cur) { if (prev) { prev->next = cur->next; @@ -62,8 +66,6 @@ static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata) } break; } - prev = cur; - cur = cur->next; } if (hwdata->joystick) { @@ -97,6 +99,8 @@ int SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *desc) int axis_triggerleft = -1; int axis_triggerright = -1; + SDL_AssertJoysticksLocked(); + if (desc == NULL) { return SDL_InvalidParamError("desc"); } @@ -328,11 +332,13 @@ static int VIRTUAL_JoystickInit(void) static int VIRTUAL_JoystickGetCount(void) { + joystick_hwdata *cur; int count = 0; - joystick_hwdata *cur = g_VJoys; - while (cur) { + + SDL_AssertJoysticksLocked(); + + for (cur = g_VJoys; cur; cur = cur->next) { ++count; - cur = cur->next; } return count; } @@ -391,7 +397,11 @@ static SDL_JoystickID VIRTUAL_JoystickGetDeviceInstanceID(int device_index) static int VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) { - joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); + joystick_hwdata *hwdata; + + SDL_AssertJoysticksLocked(); + + hwdata = VIRTUAL_HWDataForIndex(device_index); if (hwdata == NULL) { return SDL_SetError("No such device"); } @@ -408,6 +418,8 @@ static int VIRTUAL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_r { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.Rumble) { @@ -426,6 +438,8 @@ static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.RumbleTriggers) { @@ -442,9 +456,12 @@ static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru static Uint32 VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick) { - joystick_hwdata *hwdata = joystick->hwdata; + joystick_hwdata *hwdata; Uint32 caps = 0; + SDL_AssertJoysticksLocked(); + + hwdata = joystick->hwdata; if (hwdata) { if (hwdata->desc.Rumble) { caps |= SDL_JOYCAP_RUMBLE; @@ -463,6 +480,8 @@ static int VIRTUAL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.SetLED) { @@ -481,6 +500,8 @@ static int VIRTUAL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, { int result; + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; if (hwdata->desc.SendEffect) { @@ -506,6 +527,8 @@ static void VIRTUAL_JoystickUpdate(SDL_Joystick *joystick) int i; Uint64 timestamp = SDL_GetTicksNS(); + SDL_AssertJoysticksLocked(); + if (joystick == NULL) { return; } @@ -532,6 +555,8 @@ static void VIRTUAL_JoystickUpdate(SDL_Joystick *joystick) static void VIRTUAL_JoystickClose(SDL_Joystick *joystick) { + SDL_AssertJoysticksLocked(); + if (joystick->hwdata) { joystick_hwdata *hwdata = joystick->hwdata; hwdata->joystick = NULL; @@ -541,6 +566,8 @@ static void VIRTUAL_JoystickClose(SDL_Joystick *joystick) static void VIRTUAL_JoystickQuit(void) { + SDL_AssertJoysticksLocked(); + while (g_VJoys) { VIRTUAL_FreeHWData(g_VJoys); } diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 32b93f7c0..d17dd914c 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -48,23 +48,19 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = { &SDL_DUMMY_SensorDriver #endif }; -static SDL_Sensor *SDL_sensors = NULL; -static SDL_bool SDL_updating_sensor = SDL_FALSE; static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */ -static SDL_atomic_t SDL_next_sensor_instance_id; +static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL; +static SDL_atomic_t SDL_next_sensor_instance_id SDL_GUARDED_BY(SDL_sensor_lock); +static SDL_bool SDL_updating_sensor SDL_GUARDED_BY(SDL_sensor_lock) = SDL_FALSE; -void SDL_LockSensors(void) +void SDL_LockSensors(void) SDL_ACQUIRE(SDL_sensor_lock) { - if (SDL_sensor_lock) { - SDL_LockMutex(SDL_sensor_lock); - } + SDL_LockMutex(SDL_sensor_lock); } -void SDL_UnlockSensors(void) +void SDL_UnlockSensors(void) SDL_RELEASE(SDL_sensor_lock) { - if (SDL_sensor_lock) { - SDL_UnlockMutex(SDL_sensor_lock); - } + SDL_UnlockMutex(SDL_sensor_lock); } int SDL_SensorInit(void) @@ -142,8 +138,7 @@ static SDL_bool SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver * /* * Get the implementation dependent name of a sensor */ -const char * -SDL_SensorGetDeviceName(int device_index) +const char *SDL_SensorGetDeviceName(int device_index) { SDL_SensorDriver *driver; const char *name = NULL; @@ -158,8 +153,7 @@ SDL_SensorGetDeviceName(int device_index) return name; } -SDL_SensorType -SDL_SensorGetDeviceType(int device_index) +SDL_SensorType SDL_SensorGetDeviceType(int device_index) { SDL_SensorDriver *driver; SDL_SensorType type = SDL_SENSOR_INVALID; @@ -187,8 +181,7 @@ int SDL_SensorGetDeviceNonPortableType(int device_index) return type; } -SDL_SensorID -SDL_SensorGetDeviceInstanceID(int device_index) +SDL_SensorID SDL_SensorGetDeviceInstanceID(int device_index) { SDL_SensorDriver *driver; SDL_SensorID instance_id = -1; @@ -209,8 +202,7 @@ SDL_SensorGetDeviceInstanceID(int device_index) * * This function returns a sensor identifier, or NULL if an error occurred. */ -SDL_Sensor * -SDL_SensorOpen(int device_index) +SDL_Sensor *SDL_SensorOpen(int device_index) { SDL_SensorDriver *driver; SDL_SensorID instance_id; @@ -281,8 +273,7 @@ SDL_SensorOpen(int device_index) /* * Find the SDL_Sensor that owns this instance id */ -SDL_Sensor * -SDL_SensorFromInstanceID(SDL_SensorID instance_id) +SDL_Sensor *SDL_SensorFromInstanceID(SDL_SensorID instance_id) { SDL_Sensor *sensor; @@ -316,8 +307,7 @@ static int SDL_PrivateSensorValid(SDL_Sensor *sensor) /* * Get the friendly name of this sensor */ -const char * -SDL_SensorGetName(SDL_Sensor *sensor) +const char *SDL_SensorGetName(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return NULL; @@ -329,8 +319,7 @@ SDL_SensorGetName(SDL_Sensor *sensor) /* * Get the type of this sensor */ -SDL_SensorType -SDL_SensorGetType(SDL_Sensor *sensor) +SDL_SensorType SDL_SensorGetType(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return SDL_SENSOR_INVALID; @@ -354,8 +343,7 @@ int SDL_SensorGetNonPortableType(SDL_Sensor *sensor) /* * Get the instance id for this opened sensor */ -SDL_SensorID -SDL_SensorGetInstanceID(SDL_Sensor *sensor) +SDL_SensorID SDL_SensorGetInstanceID(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return -1; @@ -434,11 +422,11 @@ void SDL_SensorQuit(void) { int i; + SDL_LockSensors(); + /* Make sure we're not getting called in the middle of updating sensors */ SDL_assert(!SDL_updating_sensor); - SDL_LockSensors(); - /* Stop the event polling */ while (SDL_sensors) { SDL_sensors->ref_count = 1; @@ -511,15 +499,10 @@ void SDL_SensorUpdate(void) SDL_updating_sensor = SDL_TRUE; - /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */ - SDL_UnlockSensors(); - for (sensor = SDL_sensors; sensor; sensor = sensor->next) { sensor->driver->Update(sensor); } - SDL_LockSensors(); - SDL_updating_sensor = SDL_FALSE; /* If any sensors were closed while updating, free them here */ diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index 47bf7cb38..db55cb00f 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -70,7 +70,7 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; @@ -78,7 +78,7 @@ int SDL_LockMutex(SDL_mutex *mutex) SDL_threadID this_thread; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = SDL_ThreadID(); @@ -108,7 +108,7 @@ int SDL_TryLockMutex(SDL_mutex *mutex) SDL_threadID this_thread; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = SDL_ThreadID(); @@ -131,13 +131,13 @@ int SDL_TryLockMutex(SDL_mutex *mutex) } /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; #else if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } /* If we don't own the mutex, we can't unlock it */ diff --git a/src/thread/n3ds/SDL_sysmutex.c b/src/thread/n3ds/SDL_sysmutex.c index 1dd0819a0..3d2150407 100644 --- a/src/thread/n3ds/SDL_sysmutex.c +++ b/src/thread/n3ds/SDL_sysmutex.c @@ -51,10 +51,10 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } RecursiveLock_Lock(&mutex->lock); @@ -66,17 +66,17 @@ int SDL_LockMutex(SDL_mutex *mutex) int SDL_TryLockMutex(SDL_mutex *mutex) { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } return RecursiveLock_TryLock(&mutex->lock); } /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } RecursiveLock_Unlock(&mutex->lock); diff --git a/src/thread/ngage/SDL_sysmutex.cpp b/src/thread/ngage/SDL_sysmutex.cpp index fdbb3b3d9..27891d3fd 100644 --- a/src/thread/ngage/SDL_sysmutex.cpp +++ b/src/thread/ngage/SDL_sysmutex.cpp @@ -67,26 +67,11 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } } -/* Try to lock the mutex */ -#if 0 -int -SDL_TryLockMutex(SDL_mutex * mutex) -{ - if (mutex == NULL) - { - return SDL_InvalidParamError("mutex"); - } - - // Not yet implemented. - return 0; -} -#endif - /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } RMutex rmutex; @@ -96,11 +81,26 @@ int SDL_LockMutex(SDL_mutex *mutex) return 0; } +/* Try to lock the mutex */ +#if 0 +int +SDL_TryLockMutex(SDL_mutex *mutex) +{ + if (mutex == NULL) + { + return 0; + } + + // Not yet implemented. + return 0; +} +#endif + /* Unlock the mutex */ -int SDL_UnlockMutex(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } RMutex rmutex; diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index 2effd1f14..bee7ceea9 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -72,6 +72,27 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } } +/* Lock the mutex */ +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +{ +#if SDL_THREADS_DISABLED + return 0; +#else + SceInt32 res = 0; + + if (mutex == NULL) { + return 0; + } + + 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) { @@ -79,8 +100,9 @@ int SDL_TryLockMutex(SDL_mutex *mutex) return 0; #else SceInt32 res = 0; + if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelTryLockLwMutex(&mutex->lock, 1); @@ -100,28 +122,8 @@ int SDL_TryLockMutex(SDL_mutex *mutex) #endif /* SDL_THREADS_DISABLED */ } -/* Lock the mutex */ -int SDL_mutexP(SDL_mutex *mutex) -{ -#if SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); - } - - 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 */ -} - /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; @@ -129,7 +131,7 @@ int SDL_mutexV(SDL_mutex *mutex) SceInt32 res = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelUnlockLwMutex(&mutex->lock, 1); @@ -140,6 +142,7 @@ int SDL_mutexV(SDL_mutex *mutex) return 0; #endif /* SDL_THREADS_DISABLED */ } + #endif /* SDL_THREAD_PSP */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index 527b68dc6..1714d6111 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -74,14 +74,14 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } /* Lock the mutex */ -int SDL_LockMutex(SDL_mutex *mutex) +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if FAKE_RECURSIVE_MUTEX pthread_t this_thread; #endif if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } #if FAKE_RECURSIVE_MUTEX @@ -117,7 +117,7 @@ int SDL_TryLockMutex(SDL_mutex *mutex) #endif if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } retval = 0; @@ -153,10 +153,10 @@ int SDL_TryLockMutex(SDL_mutex *mutex) return retval; } -int SDL_UnlockMutex(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } #if FAKE_RECURSIVE_MUTEX diff --git a/src/thread/stdcpp/SDL_sysmutex.cpp b/src/thread/stdcpp/SDL_sysmutex.cpp index 43f987a62..d590fc947 100644 --- a/src/thread/stdcpp/SDL_sysmutex.cpp +++ b/src/thread/stdcpp/SDL_sysmutex.cpp @@ -55,12 +55,12 @@ SDL_DestroyMutex(SDL_mutex *mutex) } } -/* Lock the semaphore */ +/* Lock the mutex */ extern "C" int -SDL_mutexP(SDL_mutex *mutex) +SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } try { @@ -75,8 +75,9 @@ SDL_mutexP(SDL_mutex *mutex) int SDL_TryLockMutex(SDL_mutex *mutex) { int retval = 0; + if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } if (mutex->cpp_mutex.try_lock() == false) { @@ -87,10 +88,10 @@ int SDL_TryLockMutex(SDL_mutex *mutex) /* Unlock the mutex */ extern "C" int -SDL_mutexV(SDL_mutex *mutex) +SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } mutex->cpp_mutex.unlock(); diff --git a/src/thread/vita/SDL_sysmutex.c b/src/thread/vita/SDL_sysmutex.c index 97e97b1cf..20e9d4639 100644 --- a/src/thread/vita/SDL_sysmutex.c +++ b/src/thread/vita/SDL_sysmutex.c @@ -68,6 +68,27 @@ void SDL_DestroyMutex(SDL_mutex *mutex) } } +/* Lock the mutex */ +int SDL_LockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ +{ +#if SDL_THREADS_DISABLED + return 0; +#else + SceInt32 res = 0; + + if (mutex == NULL) { + return 0; + } + + 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) { @@ -75,8 +96,9 @@ int SDL_TryLockMutex(SDL_mutex *mutex) return 0; #else SceInt32 res = 0; + if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelTryLockLwMutex(&mutex->lock, 1); @@ -96,28 +118,8 @@ int SDL_TryLockMutex(SDL_mutex *mutex) #endif /* SDL_THREADS_DISABLED */ } -/* Lock the mutex */ -int SDL_mutexP(SDL_mutex *mutex) -{ -#if SDL_THREADS_DISABLED - return 0; -#else - SceInt32 res = 0; - if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); - } - - 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 */ -} - /* Unlock the mutex */ -int SDL_mutexV(SDL_mutex *mutex) +int SDL_UnlockMutex(SDL_mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */ { #if SDL_THREADS_DISABLED return 0; @@ -125,7 +127,7 @@ int SDL_mutexV(SDL_mutex *mutex) SceInt32 res = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } res = sceKernelUnlockLwMutex(&mutex->lock, 1); diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index ba18b8eef..f8737a7e7 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -74,13 +74,13 @@ static void SDL_DestroyMutex_srw(SDL_mutex *mutex) } } -static int SDL_LockMutex_srw(SDL_mutex *_mutex) +static int 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; DWORD this_thread; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = GetCurrentThreadId(); @@ -106,7 +106,7 @@ static int SDL_TryLockMutex_srw(SDL_mutex *_mutex) int retval = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } this_thread = GetCurrentThreadId(); @@ -124,12 +124,12 @@ static int SDL_TryLockMutex_srw(SDL_mutex *_mutex) return retval; } -static int SDL_UnlockMutex_srw(SDL_mutex *_mutex) +static int 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; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } if (mutex->owner == GetCurrentThreadId()) { @@ -189,11 +189,11 @@ static void SDL_DestroyMutex_cs(SDL_mutex *mutex_) } /* Lock the mutex */ -static int SDL_LockMutex_cs(SDL_mutex *mutex_) +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_; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } EnterCriticalSection(&mutex->cs); @@ -206,7 +206,7 @@ static int SDL_TryLockMutex_cs(SDL_mutex *mutex_) SDL_mutex_cs *mutex = (SDL_mutex_cs *)mutex_; int retval = 0; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } if (TryEnterCriticalSection(&mutex->cs) == 0) { @@ -216,11 +216,11 @@ static int SDL_TryLockMutex_cs(SDL_mutex *mutex_) } /* Unlock the mutex */ -static int SDL_UnlockMutex_cs(SDL_mutex *mutex_) +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_; if (mutex == NULL) { - return SDL_InvalidParamError("mutex"); + return 0; } LeaveCriticalSection(&mutex->cs);