Przeglądaj źródła

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
Sam Lantinga 17 godzin temu
rodzic
commit
f9d49358d2

+ 4 - 4
include/SDL3/SDL_joystick.h

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

+ 2 - 0
src/SDL.c

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

+ 25 - 14
src/events/SDL_events.c

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

+ 9 - 0
src/events/SDL_events_c.h

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

+ 8 - 17
src/events/SDL_eventwatch.c

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

+ 0 - 1
src/events/SDL_eventwatch_c.h

@@ -29,7 +29,6 @@ typedef struct SDL_EventWatcher
 
 typedef struct SDL_EventWatchList
 {
-    SDL_Mutex *lock;
     SDL_EventWatcher filter;
     SDL_EventWatcher *watchers;
     int count;

+ 13 - 18
src/events/SDL_touch.c

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

+ 9 - 9
src/joystick/SDL_gamepad.c

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

+ 7 - 46
src/joystick/SDL_joystick.c

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

+ 1 - 1
src/joystick/SDL_joystick_c.h

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

+ 5 - 5
src/joystick/SDL_steam_virtual_gamepad.c

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

+ 2 - 1
src/joystick/SDL_sysjoystick.h

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

+ 1 - 1
src/joystick/hidapi/SDL_hidapijoystick.c

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

+ 4 - 4
src/joystick/linux/SDL_sysjoystick.c

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

+ 1 - 1
src/joystick/virtual/SDL_virtualjoystick.c

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

+ 3 - 42
src/sensor/SDL_sensor.c

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

+ 3 - 7
src/sensor/SDL_sensor_c.h

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

+ 2 - 1
src/sensor/SDL_syssensor.h

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