summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
diff options
context:
space:
mode:
authorTillmann Karras <tilkax@gmail.com>2023-11-28 13:25:59 +0000
committerTillmann Karras <tilkax@gmail.com>2024-04-06 20:58:17 +0100
commitd1db347c8af0a0c609736a4db05d62304c3f3220 (patch)
tree1d30dddbf94faae82fdb2760c9870a73c9782549 /Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
parent116da3ab956ed02043cd944a76ea05f828965fef (diff)
evdev: close file descriptors in a separate thread
For some reason Linux is surprisingly slow at closing file descriptors of event devices. This commit improves GUI startup times on my computer by about 1.5 seconds.
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp15
1 files changed, 12 insertions, 3 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
index 6e9764fda9..e9f4f21980 100644
--- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
@@ -21,6 +21,7 @@
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/Thread.h"
+#include "Common/WorkQueueThread.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
namespace ciface::evdev
@@ -34,6 +35,12 @@ public:
void RemoveDevnodeObject(const std::string&);
+ // Linux has the strange behavior that closing file descriptors of event devices can be
+ // surprisingly slow, in the range of 20-70 milliseconds. For modern systems that have maybe 30
+ // event devices this can quickly add up, leading to visibly slow startup. So we close FDs on a
+ // separate thread *shrug*
+ void CloseDescriptor(int fd) { m_cleanup_thread.Push(fd); }
+
private:
std::shared_ptr<evdevDevice>
FindDeviceWithUniqueIDAndPhysicalLocation(const char* unique_id, const char* physical_location);
@@ -55,6 +62,8 @@ private:
// as devices can be destroyed by any thread at any time. As of now it's protected
// by ControllerInterface::m_devices_population_mutex.
std::map<std::string, std::weak_ptr<evdevDevice>> m_devnode_objects;
+
+ Common::WorkQueueThread<int> m_cleanup_thread;
};
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
@@ -273,7 +282,7 @@ void InputBackend::AddDeviceNode(const char* devnode)
if (libevdev_new_from_fd(fd, &dev) != 0)
{
// This usually fails because the device node isn't an evdev device, such as /dev/input/js0
- close(fd);
+ CloseDescriptor(fd);
return;
}
@@ -415,7 +424,7 @@ void InputBackend::StopHotplugThread()
}
InputBackend::InputBackend(ControllerInterface* controller_interface)
- : ciface::InputBackend(controller_interface)
+ : ciface::InputBackend(controller_interface), m_cleanup_thread("evdev cleanup", close)
{
StartHotplugThread();
}
@@ -665,7 +674,7 @@ evdevDevice::~evdevDevice()
{
m_input_backend.RemoveDevnodeObject(node.devnode);
libevdev_free(node.device);
- close(node.fd);
+ m_input_backend.CloseDescriptor(node.fd);
}
}