Browse Source

Use stat() to minimize input device opens when not using udev

Calling open() on input devices can generate device I/O which blocks
the main thread and causes dropped frames. Using stat() we can avoid
opening anything unless /dev/input has changed since we last polled.

We could have used something fancy like inotify, but it didn't seem
worth the added complexity for this uncommon non-udev case.
Cameron Gutman 5 năm trước cách đây
mục cha
commit
55eb76218d
1 tập tin đã thay đổi với 25 bổ sung13 xóa
  1. 25 13
      src/joystick/linux/SDL_sysjoystick.c

+ 25 - 13
src/joystick/linux/SDL_sysjoystick.c

@@ -80,7 +80,8 @@ static SDL_joylist_item *SDL_joylist_tail = NULL;
 static int numjoysticks = 0;
 
 #if !SDL_USE_LIBUDEV
-static Uint32 last_joy_detect_time = 0;
+static Uint32 last_joy_detect_time;
+static time_t last_input_dir_mtime;
 #endif
 
 #define test_bit(nr, addr) \
@@ -421,21 +422,28 @@ LINUX_JoystickDetect(void)
     Uint32 now = SDL_GetTicks();
 
     if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
-        DIR *folder;
-        struct dirent *dent;
-
-        folder = opendir("/dev/input");
-        if (folder) {
-            while ((dent = readdir(folder))) {
-                int len = SDL_strlen(dent->d_name);
-                if (len > 5 && SDL_strncmp(dent->d_name, "event", 5) == 0) {
-                    char path[PATH_MAX];
-                    SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", dent->d_name);
-                    MaybeAddDevice(path);
+        struct stat sb;
+
+        /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
+        if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
+            DIR *folder;
+            struct dirent *dent;
+
+            folder = opendir("/dev/input");
+            if (folder) {
+                while ((dent = readdir(folder))) {
+                    int len = SDL_strlen(dent->d_name);
+                    if (len > 5 && SDL_strncmp(dent->d_name, "event", 5) == 0) {
+                        char path[PATH_MAX];
+                        SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", dent->d_name);
+                        MaybeAddDevice(path);
+                    }
                 }
+
+                closedir(folder);
             }
 
-            closedir(folder);
+            last_input_dir_mtime = sb.st_mtime;
         }
 
         last_joy_detect_time = now;
@@ -483,6 +491,10 @@ LINUX_JoystickInit(void)
     /* Force a scan to build the initial device list */
     SDL_UDEV_Scan();
 #else
+    /* Force immediate joystick detection */
+    last_joy_detect_time = 0;
+    last_input_dir_mtime = 0;
+
     /* Report all devices currently present */
     LINUX_JoystickDetect();
 #endif