mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-04 19:55:19 +00:00
Create a global event lock for hardware that generates events
This prevents ABBA deadlocks caused by taking a hardware resource lock then delivering events at the same time another thread is taking a hardware resource lock from an event watch callback. Fixes https://github.com/libsdl-org/SDL/issues/15709
This commit is contained in:
parent
75270a4264
commit
f9d49358d2
18 changed files with 99 additions and 172 deletions
|
|
@ -81,7 +81,7 @@ extern "C" {
|
|||
* help Clang's thread safety analysis tools to function. Do not attempt
|
||||
* to access this symbol from your app, it will not work!
|
||||
*/
|
||||
extern SDL_Mutex *SDL_joystick_lock;
|
||||
extern SDL_Mutex *SDL_event_lock;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -186,7 +186,7 @@ typedef enum SDL_JoystickConnectionState
|
|||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock);
|
||||
extern SDL_DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_event_lock);
|
||||
|
||||
/**
|
||||
* Locking for atomic access to the joystick API.
|
||||
|
|
@ -201,7 +201,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystic
|
|||
*
|
||||
* \since This function is available since SDL 3.6.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_TryLockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock);
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_TryLockJoysticks(void) SDL_TRY_ACQUIRE(true, SDL_event_lock);
|
||||
|
||||
/**
|
||||
* Unlocking for atomic access to the joystick API.
|
||||
|
|
@ -211,7 +211,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TryLockJoysticks(void) SDL_ACQUIRE(SDL_joys
|
|||
*
|
||||
* \since This function is available since SDL 3.2.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock);
|
||||
extern SDL_DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_event_lock);
|
||||
|
||||
/**
|
||||
* Return whether a joystick is currently connected.
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ void SDL_InitMainThread(void)
|
|||
SDL_InitEnvironment();
|
||||
SDL_InitTicks();
|
||||
SDL_InitFilesystem();
|
||||
SDL_CreateEventLock();
|
||||
|
||||
if (!done_info) {
|
||||
const char *value;
|
||||
|
|
@ -316,6 +317,7 @@ void SDL_InitMainThread(void)
|
|||
|
||||
static void SDL_QuitMainThread(void)
|
||||
{
|
||||
SDL_DestroyEventLock();
|
||||
SDL_QuitFilesystem();
|
||||
SDL_QuitTicks();
|
||||
SDL_QuitEnvironment();
|
||||
|
|
|
|||
|
|
@ -161,6 +161,23 @@ static struct
|
|||
} SDL_EventQ = { NULL, false, { 0 }, 0, NULL, NULL, NULL };
|
||||
|
||||
|
||||
SDL_Mutex *SDL_event_lock = NULL; // This needs to support recursive locks
|
||||
|
||||
void SDL_CreateEventLock(void)
|
||||
{
|
||||
if (!SDL_event_lock) {
|
||||
SDL_event_lock = SDL_CreateMutex();
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_DestroyEventLock(void)
|
||||
{
|
||||
if (SDL_event_lock) {
|
||||
SDL_DestroyMutex(SDL_event_lock);
|
||||
SDL_event_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_CleanupTemporaryMemory(void *data)
|
||||
{
|
||||
SDL_TemporaryMemoryState *state = (SDL_TemporaryMemoryState *)data;
|
||||
|
|
@ -965,8 +982,9 @@ void SDL_StopEventLoop(void)
|
|||
const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
|
||||
int i;
|
||||
SDL_EventEntry *entry;
|
||||
SDL_Mutex *lock = SDL_EventQ.lock;
|
||||
|
||||
SDL_LockMutex(SDL_EventQ.lock);
|
||||
SDL_LockMutex(lock);
|
||||
|
||||
SDL_EventQ.active = false;
|
||||
|
||||
|
|
@ -1004,17 +1022,10 @@ void SDL_StopEventLoop(void)
|
|||
SDL_QuitEventWatchList(&SDL_event_watchers);
|
||||
SDL_QuitWindowEventWatch();
|
||||
|
||||
SDL_Mutex *lock = NULL;
|
||||
if (SDL_EventQ.lock) {
|
||||
lock = SDL_EventQ.lock;
|
||||
SDL_EventQ.lock = NULL;
|
||||
}
|
||||
SDL_EventQ.lock = NULL;
|
||||
|
||||
SDL_UnlockMutex(lock);
|
||||
|
||||
if (lock) {
|
||||
SDL_DestroyMutex(lock);
|
||||
}
|
||||
SDL_DestroyMutex(lock);
|
||||
}
|
||||
|
||||
// This function (and associated calls) may be called more than once
|
||||
|
|
@ -1833,7 +1844,7 @@ bool SDL_PushEvent(SDL_Event *event)
|
|||
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_EventEntry *event, *next;
|
||||
SDL_LockMutex(SDL_event_watchers.lock);
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
{
|
||||
// Set filter and discard pending events
|
||||
SDL_event_watchers.filter.callback = filter;
|
||||
|
|
@ -1852,18 +1863,18 @@ void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
|
|||
SDL_UnlockMutex(SDL_EventQ.lock);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(SDL_event_watchers.lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
}
|
||||
|
||||
bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
|
||||
{
|
||||
SDL_EventWatcher event_ok;
|
||||
|
||||
SDL_LockMutex(SDL_event_watchers.lock);
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
{
|
||||
event_ok = SDL_event_watchers.filter;
|
||||
}
|
||||
SDL_UnlockMutex(SDL_event_watchers.lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
|
||||
if (filter) {
|
||||
*filter = event_ok.callback;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@
|
|||
#include "SDL_pen_c.h"
|
||||
#include "SDL_windowevents_c.h"
|
||||
|
||||
// The event mutex
|
||||
//
|
||||
// This mutex prevents multiple threads from watching multiple events
|
||||
// simultaneously and also protects resources like joysticks that may
|
||||
// be accessed from multiple threads and also generate events.
|
||||
extern SDL_Mutex *SDL_event_lock;
|
||||
extern void SDL_CreateEventLock(void);
|
||||
extern void SDL_DestroyEventLock(void);
|
||||
|
||||
// Start and stop the event processing loop
|
||||
extern bool SDL_StartEventLoop(void);
|
||||
extern void SDL_StopEventLoop(void);
|
||||
|
|
|
|||
|
|
@ -21,25 +21,16 @@
|
|||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_eventwatch_c.h"
|
||||
#include "SDL_events_c.h"
|
||||
|
||||
|
||||
bool SDL_InitEventWatchList(SDL_EventWatchList *list)
|
||||
{
|
||||
if (list->lock == NULL) {
|
||||
list->lock = SDL_CreateMutex();
|
||||
if (list->lock == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDL_QuitEventWatchList(SDL_EventWatchList *list)
|
||||
{
|
||||
if (list->lock) {
|
||||
SDL_DestroyMutex(list->lock);
|
||||
list->lock = NULL;
|
||||
}
|
||||
if (list->watchers) {
|
||||
SDL_free(list->watchers);
|
||||
list->watchers = NULL;
|
||||
|
|
@ -56,13 +47,13 @@ bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event)
|
|||
return true;
|
||||
}
|
||||
|
||||
SDL_LockMutex(list->lock);
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
{
|
||||
// Make sure we only dispatch the current watcher list
|
||||
int i, count = list->count;
|
||||
|
||||
if (filter->callback && !filter->callback(filter->userdata, event)) {
|
||||
SDL_UnlockMutex(list->lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +77,7 @@ bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event)
|
|||
list->removed = false;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(list->lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -95,7 +86,7 @@ bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, voi
|
|||
{
|
||||
bool result = true;
|
||||
|
||||
SDL_LockMutex(list->lock);
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
{
|
||||
SDL_EventWatcher *watchers;
|
||||
|
||||
|
|
@ -113,14 +104,14 @@ bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, voi
|
|||
result = false;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(list->lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_LockMutex(list->lock);
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -139,5 +130,5 @@ void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter,
|
|||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(list->lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ typedef struct SDL_EventWatcher
|
|||
|
||||
typedef struct SDL_EventWatchList
|
||||
{
|
||||
SDL_Mutex *lock;
|
||||
SDL_EventWatcher filter;
|
||||
SDL_EventWatcher *watchers;
|
||||
int count;
|
||||
|
|
|
|||
|
|
@ -25,21 +25,20 @@
|
|||
#include "SDL_events_c.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
static SDL_Mutex *SDL_touch_lock = NULL; // This needs to support recursive locks
|
||||
static int SDL_touch_locked = 0;
|
||||
|
||||
struct SDL_Touch
|
||||
{
|
||||
SDL_TouchID id SDL_GUARDED_BY(SDL_touch_lock);
|
||||
SDL_TouchDeviceType type SDL_GUARDED_BY(SDL_touch_lock);
|
||||
int num_fingers SDL_GUARDED_BY(SDL_touch_lock);
|
||||
int max_fingers SDL_GUARDED_BY(SDL_touch_lock);
|
||||
SDL_Finger **fingers SDL_GUARDED_BY(SDL_touch_lock);
|
||||
char *name SDL_GUARDED_BY(SDL_touch_lock);
|
||||
SDL_TouchID id SDL_GUARDED_BY(SDL_event_lock);
|
||||
SDL_TouchDeviceType type SDL_GUARDED_BY(SDL_event_lock);
|
||||
int num_fingers SDL_GUARDED_BY(SDL_event_lock);
|
||||
int max_fingers SDL_GUARDED_BY(SDL_event_lock);
|
||||
SDL_Finger **fingers SDL_GUARDED_BY(SDL_event_lock);
|
||||
char *name SDL_GUARDED_BY(SDL_event_lock);
|
||||
};
|
||||
|
||||
static int SDL_num_touch SDL_GUARDED_BY(SDL_touch_lock) = 0;
|
||||
static SDL_Touch **SDL_touchDevices SDL_GUARDED_BY(SDL_touch_lock) = NULL;
|
||||
static int SDL_num_touch SDL_GUARDED_BY(SDL_event_lock) = 0;
|
||||
static SDL_Touch **SDL_touchDevices SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
|
||||
// for mapping touch events to mice
|
||||
static bool finger_touching = false;
|
||||
|
|
@ -49,23 +48,22 @@ static SDL_TouchID track_touchid;
|
|||
// Public functions
|
||||
bool SDL_InitTouch(void)
|
||||
{
|
||||
SDL_touch_lock = SDL_CreateMutex();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SDL_LockTouch(void) SDL_ACQUIRE(SDL_touch_lock)
|
||||
static void SDL_LockTouch(void) SDL_ACQUIRE(SDL_event_lock)
|
||||
{
|
||||
SDL_LockMutex(SDL_touch_lock);
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
++SDL_touch_locked;
|
||||
}
|
||||
|
||||
static void SDL_UnlockTouch(void) SDL_RELEASE(SDL_touch_lock)
|
||||
static void SDL_UnlockTouch(void) SDL_RELEASE(SDL_event_lock)
|
||||
{
|
||||
--SDL_touch_locked;
|
||||
SDL_UnlockMutex(SDL_touch_lock);
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
}
|
||||
|
||||
static void SDL_AssertTouchLocked(void) SDL_ASSERT_CAPABILITY(SDL_touch_lock)
|
||||
static void SDL_AssertTouchLocked(void) SDL_ASSERT_CAPABILITY(SDL_event_lock)
|
||||
{
|
||||
SDL_assert(SDL_touch_locked > 0);
|
||||
}
|
||||
|
|
@ -614,9 +612,6 @@ void SDL_QuitTouch(void)
|
|||
SDL_touchDevices = NULL;
|
||||
}
|
||||
SDL_UnlockTouch();
|
||||
|
||||
SDL_DestroyMutex(SDL_touch_lock);
|
||||
SDL_touch_lock = NULL;
|
||||
}
|
||||
|
||||
int SDL_SendPinch(SDL_EventType type, Uint64 timestamp, SDL_Window *window, float scale)
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@
|
|||
} while (0)
|
||||
|
||||
static bool SDL_gamepads_initialized;
|
||||
static SDL_Gamepad *SDL_gamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static SDL_HashTable *SDL_gamepad_names SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static SDL_Gamepad *SDL_gamepads SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static SDL_HashTable *SDL_gamepad_names SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
|
||||
// The face button style of a gamepad
|
||||
typedef enum
|
||||
|
|
@ -96,7 +96,7 @@ typedef enum
|
|||
SDL_GAMEPAD_MAPPING_PRIORITY_USER,
|
||||
} SDL_GamepadMappingPriority;
|
||||
|
||||
#define _guarded SDL_GUARDED_BY(SDL_joystick_lock)
|
||||
#define _guarded SDL_GUARDED_BY(SDL_event_lock)
|
||||
|
||||
typedef struct GamepadMapping_t
|
||||
{
|
||||
|
|
@ -121,13 +121,13 @@ typedef struct
|
|||
#undef _guarded
|
||||
|
||||
static SDL_GUID s_zeroGUID;
|
||||
static GamepadMapping_t *s_pSupportedGamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static GamepadMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static GamepadMapping_t *s_pXInputMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static MappingChangeTracker *s_mappingChangeTracker SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static SDL_HashTable *s_gamepadInstanceIDs SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static GamepadMapping_t *s_pSupportedGamepads SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static GamepadMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static GamepadMapping_t *s_pXInputMapping SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static MappingChangeTracker *s_mappingChangeTracker SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static SDL_HashTable *s_gamepadInstanceIDs SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
|
||||
#define _guarded SDL_GUARDED_BY(SDL_joystick_lock)
|
||||
#define _guarded SDL_GUARDED_BY(SDL_event_lock)
|
||||
|
||||
// The SDL gamepad structure
|
||||
struct SDL_Gamepad
|
||||
|
|
|
|||
|
|
@ -114,19 +114,14 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifndef SDL_THREAD_SAFETY_ANALYSIS
|
||||
static
|
||||
#endif
|
||||
SDL_Mutex *SDL_joystick_lock = NULL; // This needs to support recursive locks
|
||||
static SDL_AtomicInt SDL_joystick_lock_pending;
|
||||
static int SDL_joysticks_locked;
|
||||
static bool SDL_joysticks_initialized;
|
||||
static bool SDL_joysticks_quitting;
|
||||
static bool SDL_joystick_being_added;
|
||||
static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
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_HashTable *SDL_joystick_names SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_event_lock) = 0;
|
||||
static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static SDL_HashTable *SDL_joystick_names SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static bool SDL_joystick_allows_background_events = false;
|
||||
|
||||
static Uint32 initial_old_xboxone_controllers[] = {
|
||||
|
|
@ -706,16 +701,13 @@ bool SDL_JoysticksQuitting(void)
|
|||
|
||||
void SDL_LockJoysticks(void)
|
||||
{
|
||||
(void)SDL_AtomicIncRef(&SDL_joystick_lock_pending);
|
||||
SDL_LockMutex(SDL_joystick_lock);
|
||||
(void)SDL_AtomicDecRef(&SDL_joystick_lock_pending);
|
||||
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
++SDL_joysticks_locked;
|
||||
}
|
||||
|
||||
bool SDL_TryLockJoysticks(void)
|
||||
{
|
||||
if (SDL_TryLockMutex(SDL_joystick_lock)) {
|
||||
if (SDL_TryLockMutex(SDL_event_lock)) {
|
||||
++SDL_joysticks_locked;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -724,34 +716,8 @@ bool SDL_TryLockJoysticks(void)
|
|||
|
||||
void SDL_UnlockJoysticks(void)
|
||||
{
|
||||
bool last_unlock = false;
|
||||
|
||||
--SDL_joysticks_locked;
|
||||
|
||||
if (!SDL_joysticks_initialized) {
|
||||
// NOTE: There's a small window here where another thread could lock the mutex after we've checked for pending locks
|
||||
if (!SDL_joysticks_locked && SDL_GetAtomicInt(&SDL_joystick_lock_pending) == 0) {
|
||||
last_unlock = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* The last unlock after joysticks are uninitialized will cleanup the mutex,
|
||||
* allowing applications to lock joysticks while reinitializing the system.
|
||||
*/
|
||||
if (last_unlock) {
|
||||
SDL_Mutex *joystick_lock = SDL_joystick_lock;
|
||||
|
||||
SDL_LockMutex(joystick_lock);
|
||||
{
|
||||
SDL_UnlockMutex(SDL_joystick_lock);
|
||||
|
||||
SDL_joystick_lock = NULL;
|
||||
}
|
||||
SDL_UnlockMutex(joystick_lock);
|
||||
SDL_DestroyMutex(joystick_lock);
|
||||
} else {
|
||||
SDL_UnlockMutex(SDL_joystick_lock);
|
||||
}
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
}
|
||||
|
||||
bool SDL_JoysticksLocked(void)
|
||||
|
|
@ -892,11 +858,6 @@ bool SDL_InitJoysticks(void)
|
|||
int i;
|
||||
bool result = false;
|
||||
|
||||
// Create the joystick list lock
|
||||
if (SDL_joystick_lock == NULL) {
|
||||
SDL_joystick_lock = SDL_CreateMutex();
|
||||
}
|
||||
|
||||
if (!SDL_InitSubSystem(SDL_INIT_EVENTS)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ extern bool SDL_JoysticksQuitting(void);
|
|||
extern bool SDL_JoysticksLocked(void);
|
||||
|
||||
// Make sure we currently have the joysticks locked
|
||||
extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_lock);
|
||||
extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_event_lock);
|
||||
|
||||
// Function to return whether there are any joysticks opened by the application
|
||||
extern bool SDL_JoysticksOpened(void);
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@
|
|||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_joystick_lock) = 0;
|
||||
static Uint64 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_joystick_lock) = 0;
|
||||
static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_joystick_lock) = 0;
|
||||
static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_event_lock) = 0;
|
||||
static Uint64 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_event_lock) = 0;
|
||||
static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_event_lock) = 0;
|
||||
|
||||
|
||||
static Uint64 GetFileModificationTime(const char *file)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
// This is the system specific header for the SDL joystick API
|
||||
#include "SDL_joystick_c.h"
|
||||
#include "../events/SDL_events_c.h"
|
||||
|
||||
// Set up for C function definitions, even when using C++
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -78,7 +79,7 @@ typedef struct SDL_JoystickCapSenseInfo
|
|||
bool down;
|
||||
} SDL_JoystickCapSenseInfo;
|
||||
|
||||
#define _guarded SDL_GUARDED_BY(SDL_joystick_lock)
|
||||
#define _guarded SDL_GUARDED_BY(SDL_event_lock)
|
||||
|
||||
struct SDL_Joystick
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ static int SDL_HIDAPI_numdrivers = 0;
|
|||
static SDL_AtomicInt SDL_HIDAPI_updating_devices;
|
||||
static bool SDL_HIDAPI_hints_changed = false;
|
||||
static Uint32 SDL_HIDAPI_change_count = 0;
|
||||
static SDL_HIDAPI_Device *SDL_HIDAPI_devices SDL_GUARDED_BY(SDL_joystick_lock);
|
||||
static SDL_HIDAPI_Device *SDL_HIDAPI_devices SDL_GUARDED_BY(SDL_event_lock);
|
||||
static int SDL_HIDAPI_numjoysticks = 0;
|
||||
static bool SDL_HIDAPI_combine_joycons = true;
|
||||
static bool initialized = false;
|
||||
|
|
|
|||
|
|
@ -186,10 +186,10 @@ typedef struct SDL_sensorlist_item
|
|||
} SDL_sensorlist_item;
|
||||
|
||||
static bool SDL_classic_joysticks = false;
|
||||
static SDL_joylist_item *SDL_joylist SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static SDL_joylist_item *SDL_joylist_tail SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static int numjoysticks SDL_GUARDED_BY(SDL_joystick_lock) = 0;
|
||||
static SDL_sensorlist_item *SDL_sensorlist SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static SDL_joylist_item *SDL_joylist SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static SDL_joylist_item *SDL_joylist_tail SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static int numjoysticks SDL_GUARDED_BY(SDL_event_lock) = 0;
|
||||
static SDL_sensorlist_item *SDL_sensorlist SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
static int inotify_fd = -1;
|
||||
|
||||
static Uint64 last_joy_detect_time;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
static joystick_hwdata *g_VJoys SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
||||
static joystick_hwdata *g_VJoys SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
|
||||
static joystick_hwdata *VIRTUAL_HWDataForInstance(SDL_JoystickID instance_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,14 +51,9 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifndef SDL_THREAD_SAFETY_ANALYSIS
|
||||
static
|
||||
#endif
|
||||
SDL_Mutex *SDL_sensor_lock = NULL; // This needs to support recursive locks
|
||||
static SDL_AtomicInt SDL_sensor_lock_pending;
|
||||
static int SDL_sensors_locked;
|
||||
static bool SDL_sensors_initialized;
|
||||
static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL;
|
||||
static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_event_lock) = NULL;
|
||||
|
||||
#define CHECK_SENSOR_MAGIC(sensor, result) \
|
||||
CHECK_PARAM(!SDL_ObjectValid(sensor, SDL_OBJECT_TYPE_SENSOR)) { \
|
||||
|
|
@ -74,43 +69,14 @@ bool SDL_SensorsInitialized(void)
|
|||
|
||||
void SDL_LockSensors(void)
|
||||
{
|
||||
(void)SDL_AtomicIncRef(&SDL_sensor_lock_pending);
|
||||
SDL_LockMutex(SDL_sensor_lock);
|
||||
(void)SDL_AtomicDecRef(&SDL_sensor_lock_pending);
|
||||
|
||||
SDL_LockMutex(SDL_event_lock);
|
||||
++SDL_sensors_locked;
|
||||
}
|
||||
|
||||
void SDL_UnlockSensors(void)
|
||||
{
|
||||
bool last_unlock = false;
|
||||
|
||||
--SDL_sensors_locked;
|
||||
|
||||
if (!SDL_sensors_initialized) {
|
||||
// NOTE: There's a small window here where another thread could lock the mutex after we've checked for pending locks
|
||||
if (!SDL_sensors_locked && SDL_GetAtomicInt(&SDL_sensor_lock_pending) == 0) {
|
||||
last_unlock = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* The last unlock after sensors are uninitialized will cleanup the mutex,
|
||||
* allowing applications to lock sensors while reinitializing the system.
|
||||
*/
|
||||
if (last_unlock) {
|
||||
SDL_Mutex *sensor_lock = SDL_sensor_lock;
|
||||
|
||||
SDL_LockMutex(sensor_lock);
|
||||
{
|
||||
SDL_UnlockMutex(SDL_sensor_lock);
|
||||
|
||||
SDL_sensor_lock = NULL;
|
||||
}
|
||||
SDL_UnlockMutex(sensor_lock);
|
||||
SDL_DestroyMutex(sensor_lock);
|
||||
} else {
|
||||
SDL_UnlockMutex(SDL_sensor_lock);
|
||||
}
|
||||
SDL_UnlockMutex(SDL_event_lock);
|
||||
}
|
||||
|
||||
bool SDL_SensorsLocked(void)
|
||||
|
|
@ -128,11 +94,6 @@ bool SDL_InitSensors(void)
|
|||
int i;
|
||||
bool status;
|
||||
|
||||
// Create the sensor list lock
|
||||
if (SDL_sensor_lock == NULL) {
|
||||
SDL_sensor_lock = SDL_CreateMutex();
|
||||
}
|
||||
|
||||
if (!SDL_InitSubSystem(SDL_INIT_EVENTS)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,6 @@
|
|||
#ifndef SDL_sensor_c_h_
|
||||
#define SDL_sensor_c_h_
|
||||
|
||||
#ifdef SDL_THREAD_SAFETY_ANALYSIS
|
||||
extern SDL_Mutex *SDL_sensor_lock;
|
||||
#endif
|
||||
|
||||
struct SDL_SensorDriver;
|
||||
|
||||
// Useful functions and variables from SDL_sensor.c
|
||||
|
|
@ -42,10 +38,10 @@ extern bool SDL_SensorsInitialized(void);
|
|||
extern bool SDL_SensorsLocked(void);
|
||||
|
||||
// Make sure we currently have the sensors locked
|
||||
extern void SDL_AssertSensorsLocked(void) SDL_ASSERT_CAPABILITY(SDL_sensor_lock);
|
||||
extern void SDL_AssertSensorsLocked(void) SDL_ASSERT_CAPABILITY(SDL_event_lock);
|
||||
|
||||
extern void SDL_LockSensors(void) SDL_ACQUIRE(SDL_sensor_lock);
|
||||
extern void SDL_UnlockSensors(void) SDL_RELEASE(SDL_sensor_lock);
|
||||
extern void SDL_LockSensors(void) SDL_ACQUIRE(SDL_event_lock);
|
||||
extern void SDL_UnlockSensors(void) SDL_RELEASE(SDL_event_lock);
|
||||
|
||||
// Function to return whether there are any sensors opened by the application
|
||||
extern bool SDL_SensorsOpened(void);
|
||||
|
|
|
|||
|
|
@ -26,8 +26,9 @@
|
|||
// This is the system specific header for the SDL sensor API
|
||||
|
||||
#include "SDL_sensor_c.h"
|
||||
#include "../events/SDL_events_c.h"
|
||||
|
||||
#define _guarded SDL_GUARDED_BY(SDL_sensor_lock)
|
||||
#define _guarded SDL_GUARDED_BY(SDL_event_lock)
|
||||
|
||||
// The SDL sensor structure
|
||||
struct SDL_Sensor
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue