hle: kernel: Add KSpinLock implementation.

merge-requests/60/head
bunnei 2021-02-08 18:02:36 +07:00
parent 24e1e17a8a
commit 6da91da08e
3 changed files with 89 additions and 0 deletions

@ -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

@ -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

@ -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