diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_spin_lock.cpp | 54 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_spin_lock.h | 33 | 
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 | 
