Commit b73703b9c616939ffd73fdc97da346ec4343a6e0

Sam Lantinga 2018-11-19T21:17:00

Fixed bug 4391 - hid_enumerate() sometimes causes game to freeze for a few seconds Daniel Gibson Even though my game (dhewm3) doesn't use SDL_INIT_JOYSTICK, SDL_PumpEvent() calls SDL_JoystickUpdate() which ends up calling hid_enumerate() every three seconds, and sometimes on my Win7 box hid_enumerate() takes about 5 seconds, which causes the whole game to freeze for that time.

diff --git a/include/SDL_bits.h b/include/SDL_bits.h
index eb8322f..b6b6683 100644
--- a/include/SDL_bits.h
+++ b/include/SDL_bits.h
@@ -101,6 +101,15 @@ SDL_MostSignificantBitIndex32(Uint32 x)
 #endif
 }
 
+SDL_FORCE_INLINE SDL_bool
+SDL_HasExactlyOneBitSet32(Uint32 x)
+{
+    if (x && !(x & (x - 1))) {
+        return SDL_TRUE;
+    }
+    return SDL_FALSE;
+}
+
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 }
diff --git a/src/SDL.c b/src/SDL.c
index 6d7e166..7a1c749 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -348,6 +348,12 @@ SDL_WasInit(Uint32 flags)
     int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
     Uint32 initialized = 0;
 
+    /* Fast path for checking one flag */
+    if (SDL_HasExactlyOneBitSet32(flags)) {
+        int subsystem_index = SDL_MostSignificantBitIndex32(flags);
+        return SDL_SubsystemRefCount[subsystem_index] ? flags : 0;
+    }
+
     if (!flags) {
         flags = SDL_INIT_EVERYTHING;
     }
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 8c784ae..12942a5 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1016,6 +1016,10 @@ SDL_JoystickUpdate(void)
     int i;
     SDL_Joystick *joystick;
 
+    if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
+        return;
+    }
+
     SDL_LockJoysticks();
 
     if (SDL_updating_joystick) {
diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c
index 5c7a990..945421f 100644
--- a/src/sensor/SDL_sensor.c
+++ b/src/sensor/SDL_sensor.c
@@ -505,6 +505,10 @@ SDL_SensorUpdate(void)
     int i;
     SDL_Sensor *sensor;
 
+    if (!SDL_WasInit(SDL_INIT_SENSOR)) {
+        return;
+    }
+
     SDL_LockSensors();
 
     if (SDL_updating_sensor) {