summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-02-09 03:02:36 +0100
committerbunnei <bunneidev@gmail.com>2021-02-19 01:16:24 +0100
commit6da91da08e54d02a4087eaddcbe192bd53eeaa9f (patch)
treea78c199089f4589bed446a9994eba216e0622e0c
parentcore: memory: Add templated GetPointer methods. (diff)
downloadyuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.tar
yuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.tar.gz
yuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.tar.bz2
yuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.tar.lz
yuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.tar.xz
yuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.tar.zst
yuzu-6da91da08e54d02a4087eaddcbe192bd53eeaa9f.zip
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/k_spin_lock.cpp54
-rw-r--r--src/core/hle/kernel/k_spin_lock.h33
3 files changed, 89 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8d4823f93..a6b5fef56 100644
--- a/src/core/CMakeLists.txt
+++ b/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
diff --git a/src/core/hle/kernel/k_spin_lock.cpp b/src/core/hle/kernel/k_spin_lock.cpp
new file mode 100644
index 000000000..4412aa4bb
--- /dev/null
+++ b/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
diff --git a/src/core/hle/kernel/k_spin_lock.h b/src/core/hle/kernel/k_spin_lock.h
new file mode 100644
index 000000000..12c4b2e88
--- /dev/null
+++ b/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