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.
This commit is contained in:
Cameron Gutman 2019-11-20 20:27:45 -08:00
parent 7a3ae59037
commit 55eb76218d
1 changed files with 24 additions and 12 deletions

View File

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