summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/spin_lock.cpp46
-rw-r--r--src/common/spin_lock.h20
3 files changed, 68 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 0a3e2f4d1..c8bf80372 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -143,6 +143,8 @@ add_library(common STATIC
scm_rev.cpp
scm_rev.h
scope_exit.h
+ spin_lock.cpp
+ spin_lock.h
string_util.cpp
string_util.h
swap.h
diff --git a/src/common/spin_lock.cpp b/src/common/spin_lock.cpp
new file mode 100644
index 000000000..8077b78d2
--- /dev/null
+++ b/src/common/spin_lock.cpp
@@ -0,0 +1,46 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/spin_lock.h"
+
+#if _MSC_VER
+#include <intrin.h>
+#if _M_AMD64
+#define __x86_64__ 1
+#endif
+#if _M_ARM64
+#define __aarch64__ 1
+#endif
+#else
+#if __x86_64__
+#include <xmmintrin.h>
+#endif
+#endif
+
+namespace {
+
+void thread_pause() {
+#if __x86_64__
+ _mm_pause();
+#elif __aarch64__ && _MSC_VER
+ __yield();
+#elif __aarch64__
+ asm("yield");
+#endif
+}
+
+} // namespace
+
+namespace Common {
+
+void SpinLock::lock() {
+ while (lck.test_and_set(std::memory_order_acquire))
+ thread_pause();
+}
+
+void SpinLock::unlock() {
+ lck.clear(std::memory_order_release);
+}
+
+} // namespace Common
diff --git a/src/common/spin_lock.h b/src/common/spin_lock.h
new file mode 100644
index 000000000..cbc67b6c8
--- /dev/null
+++ b/src/common/spin_lock.h
@@ -0,0 +1,20 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+
+namespace Common {
+
+class SpinLock {
+public:
+ void lock();
+ void unlock();
+
+private:
+ std::atomic_flag lck = ATOMIC_FLAG_INIT;
+};
+
+} // namespace Common