Kaynağa Gözat

hle: kernel: Add KSpinLock implementation.

bunnei 5 yıl önce
ebeveyn
işleme
6da91da08e

+ 2 - 0
src/core/CMakeLists.txt

@@ -177,6 +177,8 @@ add_library(core STATIC
     hle/kernel/k_scoped_scheduler_lock_and_sleep.h
     hle/kernel/k_shared_memory.cpp
     hle/kernel/k_shared_memory.h
+    hle/kernel/k_spin_lock.cpp
+    hle/kernel/k_spin_lock.h
     hle/kernel/k_synchronization_object.cpp
     hle/kernel/k_synchronization_object.h
     hle/kernel/k_thread.cpp

+ 54 - 0
src/core/hle/kernel/k_spin_lock.cpp

@@ -0,0 +1,54 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/k_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 ThreadPause() {
+#if __x86_64__
+    _mm_pause();
+#elif __aarch64__ && _MSC_VER
+    __yield();
+#elif __aarch64__
+    asm("yield");
+#endif
+}
+
+} // namespace
+
+namespace Kernel {
+
+void KSpinLock::Lock() {
+    while (lck.test_and_set(std::memory_order_acquire)) {
+        ThreadPause();
+    }
+}
+
+void KSpinLock::Unlock() {
+    lck.clear(std::memory_order_release);
+}
+
+bool KSpinLock::TryLock() {
+    if (lck.test_and_set(std::memory_order_acquire)) {
+        return false;
+    }
+    return true;
+}
+
+} // namespace Kernel

+ 33 - 0
src/core/hle/kernel/k_spin_lock.h

@@ -0,0 +1,33 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+
+#include "core/hle/kernel/k_scoped_lock.h"
+
+namespace Kernel {
+
+class KSpinLock {
+public:
+    KSpinLock() = default;
+
+    KSpinLock(const KSpinLock&) = delete;
+    KSpinLock& operator=(const KSpinLock&) = delete;
+
+    KSpinLock(KSpinLock&&) = delete;
+    KSpinLock& operator=(KSpinLock&&) = delete;
+
+    void Lock();
+    void Unlock();
+    [[nodiscard]] bool TryLock();
+
+private:
+    std::atomic_flag lck = ATOMIC_FLAG_INIT;
+};
+
+using KScopedSpinLock = KScopedLock<KSpinLock>;
+
+} // namespace Kernel