Przeglądaj źródła

Common: Implement a basic SpinLock class

Fernando Sahmkow 6 lat temu
rodzic
commit
13ed9438fb
3 zmienionych plików z 68 dodań i 0 usunięć
  1. 2 0
      src/common/CMakeLists.txt
  2. 46 0
      src/common/spin_lock.cpp
  3. 20 0
      src/common/spin_lock.h

+ 2 - 0
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

+ 46 - 0
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

+ 20 - 0
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