Added support for clang thread-safety analysis

The annotations have been added to SDL_mutex.h and have been made public so applications can enable this for their own code.

Clang assumes that locking and unlocking can't fail, but SDL has the concept of a NULL mutex, so the mutex functions have been changed not to report errors if a mutex hasn't been initialized. We do have mutexes that might be accessed when they are NULL, notably in the event system, so this is an important change.

This commit cleans up a bunch of rare race conditions in the joystick and game controller code so now everything should be completely protected by the joystick lock.

To test this, change the compiler to "clang -Wthread-safety -Werror=thread-safety -DSDL_THREAD_SAFETY_ANALYSIS"
This commit is contained in:
Sam Lantinga 2022-12-13 14:03:40 -08:00
parent 582fb3901a
commit d59caffe2c
42 changed files with 1667 additions and 1174 deletions

View file

@ -44,6 +44,7 @@
#include "SDL_stdinc.h"
#include "SDL_error.h"
#include "SDL_guid.h"
#include "SDL_mutex.h"
#include "begin_code.h"
/* 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 2.0.7.
*/
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 2.0.7.
*/
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.

View file

@ -31,6 +31,80 @@
#include "SDL_stdinc.h"
#include "SDL_error.h"
/******************************************************************************/
/* 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 "begin_code.h"
/* 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 2.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 2.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)
/**

View file

@ -345,10 +345,8 @@ SDL_ReportAssertion(SDL_assert_data *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) {

View file

@ -336,15 +336,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) {

View file

@ -301,14 +301,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);

View file

@ -59,7 +59,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 */

View file

@ -546,9 +546,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;
@ -605,8 +603,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;
}
@ -650,9 +649,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;
}
@ -746,17 +743,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;
}
@ -768,16 +766,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) {
@ -846,12 +844,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();
@ -865,14 +859,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;
}
@ -899,12 +891,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) {
@ -914,10 +905,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 */
@ -1002,58 +991,59 @@ static int SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Eve
/* We only want a single sentinel in the queue. We could get more than one if event is NULL,
* since the SDL_PeepEvents() call below won't remove it in that case.
*/
int status;
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 (timeout > 0) {
Uint32 elapsed = SDL_GetTicks() - start;
if (elapsed >= (Uint32)timeout) {
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
return 0;
}
loop_timeout = (int)((Uint32)timeout - elapsed);
}
if (need_periodic_poll) {
if (loop_timeout >= 0) {
loop_timeout = SDL_min(loop_timeout, PERIODIC_POLL_INTERVAL_MS);
} else {
loop_timeout = PERIODIC_POLL_INTERVAL_MS;
}
}
status = _this->WaitEventTimeout(_this, loop_timeout);
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
if (status == 0 && need_periodic_poll && loop_timeout == PERIODIC_POLL_INTERVAL_MS) {
/* 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 (timeout > 0) {
Uint32 elapsed = SDL_GetTicks() - start;
if (elapsed >= (Uint32)timeout) {
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
return 0;
}
loop_timeout = (int)((Uint32)timeout - elapsed);
}
if (need_periodic_poll) {
if (loop_timeout >= 0) {
loop_timeout = SDL_min(loop_timeout, PERIODIC_POLL_INTERVAL_MS);
} else {
loop_timeout = PERIODIC_POLL_INTERVAL_MS;
}
}
status = _this->WaitEventTimeout(_this, loop_timeout);
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
if (status == 0 && need_periodic_poll && loop_timeout == PERIODIC_POLL_INTERVAL_MS) {
/* 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;
}
@ -1187,11 +1177,10 @@ int SDL_PushEvent(SDL_Event *event)
event->common.timestamp = SDL_GetTicks();
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;
}
@ -1219,11 +1208,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) {
@ -1237,32 +1223,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;
@ -1275,7 +1254,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));
@ -1289,16 +1269,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) {
@ -1315,16 +1293,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;
@ -1332,10 +1308,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)
@ -1384,8 +1358,7 @@ Uint8 SDL_EventState(Uint32 type, int state)
return current_state;
}
Uint32
SDL_RegisterEvents(int numevents)
Uint32 SDL_RegisterEvents(int numevents)
{
Uint32 event_base;

View file

@ -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;

View file

@ -489,6 +489,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;
}
@ -505,6 +507,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;
}
@ -528,6 +532,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;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -49,7 +49,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);

View file

@ -67,68 +67,72 @@ typedef struct _SDL_JoystickSensorInfo
Uint64 timestamp_us;
} 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 nballs; /* Number of trackballs on the joystick */
int nballs _guarded; /* Number of trackballs on the joystick */
struct balldelta
{
int dx;
int dy;
} *balls; /* Current ball motion deltas */
} *balls _guarded; /* Current ball motion deltas */
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;
Uint32 rumble_expiration;
Uint32 rumble_resend;
Uint16 low_frequency_rumble _guarded;
Uint16 high_frequency_rumble _guarded;
Uint32 rumble_expiration _guarded;
Uint32 rumble_resend _guarded;
Uint16 left_trigger_rumble;
Uint16 right_trigger_rumble;
Uint32 trigger_rumble_expiration;
Uint16 left_trigger_rumble _guarded;
Uint16 right_trigger_rumble _guarded;
Uint32 trigger_rumble_expiration _guarded;
Uint8 led_red;
Uint8 led_green;
Uint8 led_blue;
Uint32 led_expiration;
Uint8 led_red _guarded;
Uint8 led_green _guarded;
Uint8 led_blue _guarded;
Uint32 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

View file

@ -67,6 +67,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)) {

View file

@ -408,6 +408,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;
@ -424,6 +427,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();
}
@ -469,6 +474,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;

View file

@ -100,6 +100,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 */

View file

@ -234,6 +234,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;
@ -630,6 +632,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);

View file

@ -668,6 +668,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;

View file

@ -822,6 +822,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;
@ -961,7 +963,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;
}

View file

@ -46,13 +46,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)
{
@ -65,7 +65,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) {
@ -73,7 +73,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);
@ -111,7 +111,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) {
@ -125,16 +125,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);
@ -142,8 +142,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;
}
@ -173,7 +173,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)
@ -241,9 +242,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)
@ -256,7 +255,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;
}

View file

@ -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);

View file

@ -148,7 +148,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;
}
@ -175,6 +175,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;

View file

@ -96,6 +96,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 */

View file

@ -1012,6 +1012,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);

View file

@ -323,7 +323,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);
@ -1253,6 +1253,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;
@ -1891,7 +1893,7 @@ static void HandleMiniControllerStateR(SDL_Joystick *joystick, SDL_DriverSwitch_
SDL_PrivateJoystickAxis(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 */
{
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
if (ctx->device->parent || ctx->m_bVerticalMode) {

View file

@ -221,7 +221,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;
@ -770,6 +770,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);

View file

@ -176,6 +176,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);

View file

@ -175,6 +175,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) */

View file

@ -234,7 +234,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");
}
@ -254,7 +254,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;
@ -312,7 +312,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;
@ -415,6 +415,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;
@ -478,7 +480,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;
}

View file

@ -91,7 +91,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;
@ -264,6 +264,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;
@ -285,6 +287,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) {
@ -323,7 +327,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;
@ -426,6 +430,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];
@ -571,6 +577,8 @@ HIDAPI_HasConnectedUSBDevice(const char *serial)
{
SDL_HIDAPI_Device *device;
SDL_AssertJoysticksLocked();
if (serial == NULL) {
return SDL_FALSE;
}
@ -595,6 +603,8 @@ void HIDAPI_DisconnectBluetoothDevice(const char *serial)
{
SDL_HIDAPI_Device *device;
SDL_AssertJoysticksLocked();
if (serial == NULL) {
return;
}
@ -622,6 +632,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--;) {
@ -717,6 +729,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) {
}
@ -810,6 +824,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
@ -849,6 +865,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;
}
@ -1160,6 +1178,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 */
@ -1262,6 +1282,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);
@ -1299,6 +1321,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;
@ -1314,6 +1338,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;
@ -1329,6 +1355,8 @@ static Uint32 HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick)
{
Uint32 result = 0;
SDL_AssertJoysticksLocked();
if (joystick->hwdata) {
SDL_HIDAPI_Device *device = joystick->hwdata->device;
@ -1342,6 +1370,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;
@ -1357,6 +1387,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;
@ -1372,6 +1404,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;
@ -1388,8 +1422,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;
@ -1420,6 +1456,8 @@ static void HIDAPI_JoystickQuit(void)
{
int i;
SDL_AssertJoysticksLocked();
shutting_down = SDL_TRUE;
SDL_HIDAPI_QuitRumble();

View file

@ -852,6 +852,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));
@ -869,6 +871,8 @@ static int allocate_balldata(SDL_Joystick *joystick)
{
int i;
SDL_AssertJoysticksLocked();
joystick->hwdata->balls =
(struct hwdata_ball *)SDL_malloc(joystick->nballs *
sizeof(struct hwdata_ball));
@ -925,6 +929,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) &&
@ -1132,6 +1138,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;
@ -1180,6 +1188,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");
}
@ -1210,6 +1220,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;
@ -1256,6 +1268,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;
}
@ -1280,7 +1294,7 @@ static int LINUX_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enab
static void HandleHat(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] = {
@ -1289,6 +1303,9 @@ static void HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value)
{ 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
@ -1326,6 +1343,8 @@ static void HandleHat(SDL_Joystick *stick, int hatidx, int axis, int value)
static void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
{
SDL_AssertJoysticksLocked();
stick->hwdata->balls[ball].axis[axis] += value;
}
@ -1333,6 +1352,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) {
@ -1368,6 +1389,8 @@ static void PollAllValues(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 */
@ -1424,6 +1447,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(joystick);
joystick->hwdata->fresh = SDL_FALSE;
@ -1515,6 +1540,8 @@ static void HandleClassicEvents(SDL_Joystick *joystick)
struct js_event events[32];
int i, len, code, hat_index;
SDL_AssertJoysticksLocked();
joystick->hwdata->fresh = SDL_FALSE;
while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
len /= sizeof(events[0]);
@ -1557,6 +1584,8 @@ static void LINUX_JoystickUpdate(SDL_Joystick *joystick)
{
int i;
SDL_AssertJoysticksLocked();
if (joystick->hwdata->m_bSteamController) {
SDL_UpdateSteamController(joystick);
return;
@ -1585,6 +1614,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);
@ -1645,6 +1676,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));

View file

@ -29,32 +29,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;
@ -63,8 +67,6 @@ static void VIRTUAL_FreeHWData(joystick_hwdata *hwdata)
}
break;
}
prev = cur;
cur = cur->next;
}
if (hwdata->joystick) {
@ -98,6 +100,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");
}
@ -329,11 +333,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;
}
@ -392,7 +398,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");
}
@ -409,6 +419,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) {
@ -427,6 +439,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) {
@ -443,9 +457,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;
@ -464,6 +481,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) {
@ -482,6 +501,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)
joystick_hwdata *hwdata;
int i;
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);
}

View file

@ -51,23 +51,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)
@ -145,8 +141,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;
@ -161,8 +156,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;
@ -190,8 +184,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;
@ -212,8 +205,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;
@ -284,8 +276,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;
@ -319,8 +310,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;
@ -332,8 +322,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;
@ -357,8 +346,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;
@ -448,11 +436,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;
@ -525,15 +513,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 */

View file

@ -71,7 +71,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;
@ -79,7 +79,7 @@ int SDL_LockMutex(SDL_mutex *mutex)
SDL_threadID this_thread;
if (mutex == NULL) {
return SDL_InvalidParamError("mutex");
return 0;
}
this_thread = SDL_ThreadID();
@ -109,7 +109,7 @@ int SDL_TryLockMutex(SDL_mutex *mutex)
SDL_threadID this_thread;
if (mutex == NULL) {
return SDL_InvalidParamError("mutex");
return 0;
}
this_thread = SDL_ThreadID();
@ -132,13 +132,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 */

View file

@ -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_SetError("Passed a NULL 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_SetError("Passed a NULL 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_SetError("Passed a NULL mutex");
return 0;
}
RecursiveLock_Unlock(&mutex->lock);

View file

@ -68,27 +68,11 @@ void SDL_DestroyMutex(SDL_mutex *mutex)
}
}
/* Try to lock the mutex */
#if 0
int
SDL_TryLockMutex(SDL_mutex * mutex)
{
if (mutex == NULL)
{
SDL_SetError("Passed a NULL mutex.");
return -1;
}
// 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;
@ -98,11 +82,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;

View file

@ -67,13 +67,13 @@ SDL_DestroyMutex(SDL_mutex * mutex)
/* Lock the mutex */
int
SDL_LockMutex(SDL_mutex * mutex)
SDL_LockMutex(SDL_mutex * mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
{
ULONG ulRC;
HMTX hMtx = (HMTX)mutex;
if (hMtx == NULLHANDLE)
return SDL_InvalidParamError("mutex");
return 0;
ulRC = DosRequestMutexSem(hMtx, SEM_INDEFINITE_WAIT);
if (ulRC != NO_ERROR) {
@ -92,7 +92,7 @@ SDL_TryLockMutex(SDL_mutex * mutex)
HMTX hMtx = (HMTX)mutex;
if (hMtx == NULLHANDLE)
return SDL_InvalidParamError("mutex");
return 0;
ulRC = DosRequestMutexSem(hMtx, SEM_IMMEDIATE_RETURN);
@ -109,13 +109,13 @@ SDL_TryLockMutex(SDL_mutex * mutex)
/* Unlock the mutex */
int
SDL_UnlockMutex(SDL_mutex * mutex)
SDL_UnlockMutex(SDL_mutex * mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
{
ULONG ulRC;
HMTX hMtx = (HMTX)mutex;
if (hMtx == NULLHANDLE)
return SDL_InvalidParamError("mutex");
return 0;
ulRC = DosReleaseMutexSem(hMtx);
if (ulRC != NO_ERROR)

View file

@ -73,6 +73,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)
{
@ -80,8 +101,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);
@ -101,28 +123,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;
@ -130,7 +132,7 @@ int SDL_mutexV(SDL_mutex *mutex)
SceInt32 res = 0;
if (mutex == NULL) {
return SDL_InvalidParamError("mutex");
return 0;
}
res = sceKernelUnlockLwMutex(&mutex->lock, 1);
@ -141,6 +143,7 @@ int SDL_mutexV(SDL_mutex *mutex)
return 0;
#endif /* SDL_THREADS_DISABLED */
}
#endif /* SDL_THREAD_PSP */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -76,14 +76,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
@ -119,7 +119,7 @@ int SDL_TryLockMutex(SDL_mutex *mutex)
#endif
if (mutex == NULL) {
return SDL_InvalidParamError("mutex");
return 0;
}
retval = 0;
@ -155,10 +155,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

View file

@ -56,12 +56,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 {
@ -76,8 +76,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) {
@ -88,10 +89,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();

View file

@ -69,6 +69,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)
{
@ -76,8 +97,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);
@ -97,28 +119,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;
@ -126,7 +128,7 @@ int SDL_mutexV(SDL_mutex *mutex)
SceInt32 res = 0;
if (mutex == NULL) {
return SDL_InvalidParamError("mutex");
return 0;
}
res = sceKernelUnlockLwMutex(&mutex->lock, 1);

View file

@ -77,13 +77,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();
@ -109,7 +109,7 @@ static int SDL_TryLockMutex_srw(SDL_mutex *_mutex)
int retval = 0;
if (mutex == NULL) {
return SDL_InvalidParamError("mutex");
return 0;
}
this_thread = GetCurrentThreadId();
@ -127,12 +127,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()) {
@ -192,11 +192,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);
@ -209,7 +209,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) {
@ -219,11 +219,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);