summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon
diff options
context:
space:
mode:
authorMarkus Wick <degasus@users.noreply.github.com>2016-05-19 22:58:06 +0200
committerMarkus Wick <degasus@users.noreply.github.com>2016-05-19 22:58:06 +0200
commitbb6604df767212affdbd1087d305709d9d83dc13 (patch)
tree4e2c2ca2621eecdf94b52cfb6d9c5b954760d91e /Source/Core/InputCommon
parentf1f8bf4d80e95bdb4f84c01c15f7bd27f0c9d8fb (diff)
parent1bbbe92cd203d39f0aa0da80d5bd41ae641c3e5c (diff)
Merge pull request #3805 from mathieui/gcadapter-unplug-crash
GCAdapter: improve thread safety
Diffstat (limited to 'Source/Core/InputCommon')
-rw-r--r--Source/Core/InputCommon/GCAdapter.cpp31
-rw-r--r--Source/Core/InputCommon/GCAdapter.h2
-rw-r--r--Source/Core/InputCommon/GCAdapter_Android.cpp7
-rw-r--r--Source/Core/InputCommon/GCAdapter_Null.cpp2
4 files changed, 31 insertions, 11 deletions
diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp
index df71a8d846..a5ccb771cc 100644
--- a/Source/Core/InputCommon/GCAdapter.cpp
+++ b/Source/Core/InputCommon/GCAdapter.cpp
@@ -23,6 +23,9 @@ namespace GCAdapter
{
static bool CheckDeviceAccess(libusb_device* device);
static void AddGCAdapter(libusb_device* device);
+static void ResetRumbleLockNeeded();
+static void Reset();
+static void Setup();
static bool s_detected = false;
static libusb_device_handle* s_handle = nullptr;
@@ -38,6 +41,7 @@ static std::atomic<int> s_controller_payload_size = {0};
static std::thread s_adapter_thread;
static Common::Flag s_adapter_thread_running;
+static std::mutex s_init_mutex;
static std::thread s_adapter_detect_thread;
static Common::Flag s_adapter_detect_thread_running;
@@ -78,7 +82,10 @@ static int HotplugCallback(libusb_context* ctx, libusb_device* dev, libusb_hotpl
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
{
if (s_handle == nullptr && CheckDeviceAccess(dev))
+ {
+ std::lock_guard<std::mutex> lk(s_init_mutex);
AddGCAdapter(dev);
+ }
}
else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
{
@@ -116,6 +123,7 @@ static void ScanThreadFunc()
{
if (s_handle == nullptr)
{
+ std::lock_guard<std::mutex> lk(s_init_mutex);
Setup();
if (s_detected && s_detect_callback != nullptr)
s_detect_callback();
@@ -178,7 +186,7 @@ void StopScanThread()
}
}
-void Setup()
+static void Setup()
{
libusb_device** list;
ssize_t cnt = libusb_get_device_list(s_libusb_context, &list);
@@ -307,7 +315,7 @@ static void AddGCAdapter(libusb_device* device)
s_detected = true;
if (s_detect_callback != nullptr)
s_detect_callback();
- ResetRumble();
+ ResetRumbleLockNeeded();
}
void Shutdown()
@@ -328,8 +336,11 @@ void Shutdown()
s_libusb_driver_not_supported = false;
}
-void Reset()
+static void Reset()
{
+ std::unique_lock<std::mutex> lock(s_init_mutex, std::defer_lock);
+ if (!lock.try_lock())
+ return;
if (!s_detected)
return;
@@ -443,10 +454,20 @@ bool UseAdapter()
void ResetRumble()
{
- if (!UseAdapter())
+ std::unique_lock<std::mutex> lock(s_init_mutex, std::defer_lock);
+ if (!lock.try_lock())
return;
- if (s_handle == nullptr || !s_detected)
+ ResetRumbleLockNeeded();
+}
+
+// Needs to be called when s_init_mutex is locked in order to avoid
+// being called while the libusb state is being reset
+static void ResetRumbleLockNeeded()
+{
+ if (!UseAdapter() || (s_handle == nullptr || !s_detected))
+ {
return;
+ }
std::fill(std::begin(s_controller_rumble), std::end(s_controller_rumble), 0);
diff --git a/Source/Core/InputCommon/GCAdapter.h b/Source/Core/InputCommon/GCAdapter.h
index a1780cdf1e..5568b0ae9d 100644
--- a/Source/Core/InputCommon/GCAdapter.h
+++ b/Source/Core/InputCommon/GCAdapter.h
@@ -19,9 +19,7 @@ enum ControllerTypes
CONTROLLER_WIRELESS = 2
};
void Init();
-void Reset();
void ResetRumble();
-void Setup();
void Shutdown();
void SetAdapterCallback(std::function<void(void)> func);
void StartScanThread();
diff --git a/Source/Core/InputCommon/GCAdapter_Android.cpp b/Source/Core/InputCommon/GCAdapter_Android.cpp
index 46ec417f2b..b05a066478 100644
--- a/Source/Core/InputCommon/GCAdapter_Android.cpp
+++ b/Source/Core/InputCommon/GCAdapter_Android.cpp
@@ -24,6 +24,9 @@ extern JavaVM* g_java_vm;
namespace GCAdapter
{
+static void Setup();
+static void Reset();
+
// Java classes
static jclass s_adapter_class;
@@ -207,7 +210,7 @@ void Init()
StartScanThread();
}
-void Setup()
+static void Setup()
{
s_fd = 0;
s_detected = true;
@@ -220,7 +223,7 @@ void Setup()
s_read_adapter_thread = std::thread(Read);
}
-void Reset()
+static void Reset()
{
if (!s_detected)
return;
diff --git a/Source/Core/InputCommon/GCAdapter_Null.cpp b/Source/Core/InputCommon/GCAdapter_Null.cpp
index b7bc81dfa7..d7f13c2917 100644
--- a/Source/Core/InputCommon/GCAdapter_Null.cpp
+++ b/Source/Core/InputCommon/GCAdapter_Null.cpp
@@ -9,9 +9,7 @@ namespace GCAdapter
{
void Init() {}
-void Reset() {}
void ResetRumble() {}
-void Setup() {}
void Shutdown() {}
void SetAdapterCallback(std::function<void(void)> func) {}
void StartScanThread() {}