hle: kernel: Use std::mutex instead of spin locks for most kernel locking.
This commit is contained in:
		@@ -2,9 +2,10 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/fiber.h"
 | 
			
		||||
#include "common/spin_lock.h"
 | 
			
		||||
#include "common/virtual_buffer.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/context/detail/fcontext.hpp>
 | 
			
		||||
@@ -19,7 +20,7 @@ struct Fiber::FiberImpl {
 | 
			
		||||
    VirtualBuffer<u8> stack;
 | 
			
		||||
    VirtualBuffer<u8> rewind_stack;
 | 
			
		||||
 | 
			
		||||
    SpinLock guard{};
 | 
			
		||||
    std::mutex guard;
 | 
			
		||||
    std::function<void(void*)> entry_point;
 | 
			
		||||
    std::function<void(void*)> rewind_point;
 | 
			
		||||
    void* rewind_parameter{};
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,13 @@
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/spin_lock.h"
 | 
			
		||||
#include "common/thread.h"
 | 
			
		||||
#include "common/wall_clock.h"
 | 
			
		||||
 | 
			
		||||
@@ -149,8 +149,8 @@ private:
 | 
			
		||||
    std::shared_ptr<EventType> ev_lost;
 | 
			
		||||
    Common::Event event{};
 | 
			
		||||
    Common::Event pause_event{};
 | 
			
		||||
    Common::SpinLock basic_lock{};
 | 
			
		||||
    Common::SpinLock advance_lock{};
 | 
			
		||||
    std::mutex basic_lock;
 | 
			
		||||
    std::mutex advance_lock;
 | 
			
		||||
    std::unique_ptr<std::thread> timer_thread;
 | 
			
		||||
    std::atomic<bool> paused{};
 | 
			
		||||
    std::atomic<bool> paused_set{};
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/spin_lock.h"
 | 
			
		||||
#include "core/hardware_properties.h"
 | 
			
		||||
#include "core/hle/kernel/k_priority_queue.h"
 | 
			
		||||
#include "core/hle/kernel/k_scheduler_lock.h"
 | 
			
		||||
@@ -80,7 +79,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    /// Lists all thread ids that aren't deleted/etc.
 | 
			
		||||
    std::vector<KThread*> thread_list;
 | 
			
		||||
    Common::SpinLock global_list_guard{};
 | 
			
		||||
    std::mutex global_list_guard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Kernel
 | 
			
		||||
 
 | 
			
		||||
@@ -705,7 +705,7 @@ void KScheduler::Unload(KThread* thread) {
 | 
			
		||||
        prev_thread = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    thread->context_guard.Unlock();
 | 
			
		||||
    thread->context_guard.unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KScheduler::Reload(KThread* thread) {
 | 
			
		||||
@@ -794,13 +794,13 @@ void KScheduler::SwitchToCurrent() {
 | 
			
		||||
        do {
 | 
			
		||||
            auto next_thread = current_thread.load();
 | 
			
		||||
            if (next_thread != nullptr) {
 | 
			
		||||
                const auto locked = next_thread->context_guard.TryLock();
 | 
			
		||||
                const auto locked = next_thread->context_guard.try_lock();
 | 
			
		||||
                if (state.needs_scheduling.load()) {
 | 
			
		||||
                    next_thread->context_guard.Unlock();
 | 
			
		||||
                    next_thread->context_guard.unlock();
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                if (next_thread->GetActiveCore() != core_id) {
 | 
			
		||||
                    next_thread->context_guard.Unlock();
 | 
			
		||||
                    next_thread->context_guard.unlock();
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                if (!locked) {
 | 
			
		||||
 
 | 
			
		||||
@@ -35,20 +35,15 @@ void ThreadPause() {
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
void KSpinLock::Lock() {
 | 
			
		||||
    while (lck.test_and_set(std::memory_order_acquire)) {
 | 
			
		||||
        ThreadPause();
 | 
			
		||||
    }
 | 
			
		||||
    lck.lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KSpinLock::Unlock() {
 | 
			
		||||
    lck.clear(std::memory_order_release);
 | 
			
		||||
    lck.unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool KSpinLock::TryLock() {
 | 
			
		||||
    if (lck.test_and_set(std::memory_order_acquire)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
    return lck.try_lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Kernel
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
#include "core/hle/kernel/k_scoped_lock.h"
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +25,7 @@ public:
 | 
			
		||||
    [[nodiscard]] bool TryLock();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::atomic_flag lck = ATOMIC_FLAG_INIT;
 | 
			
		||||
    std::mutex lck;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO(bunnei): Alias for now, in case we want to implement these accurately in the future.
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/intrusive_red_black_tree.h"
 | 
			
		||||
#include "common/spin_lock.h"
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
#include "core/hle/kernel/k_affinity_mask.h"
 | 
			
		||||
#include "core/hle/kernel/k_light_lock.h"
 | 
			
		||||
@@ -762,7 +763,7 @@ private:
 | 
			
		||||
    s8 priority_inheritance_count{};
 | 
			
		||||
    bool resource_limit_release_hint{};
 | 
			
		||||
    StackParameters stack_parameters{};
 | 
			
		||||
    KSpinLock context_guard{};
 | 
			
		||||
    Common::SpinLock context_guard{};
 | 
			
		||||
    KSpinLock dummy_wait_lock{};
 | 
			
		||||
 | 
			
		||||
    // For emulation
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "common/spin_lock.h"
 | 
			
		||||
#include "core/arm/cpu_interrupt_handler.h"
 | 
			
		||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
 | 
			
		||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
 | 
			
		||||
@@ -16,7 +15,7 @@ namespace Kernel {
 | 
			
		||||
PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_,
 | 
			
		||||
                           Core::CPUInterrupts& interrupts_)
 | 
			
		||||
    : core_index{core_index_}, system{system_}, scheduler{scheduler_},
 | 
			
		||||
      interrupts{interrupts_}, guard{std::make_unique<Common::SpinLock>()} {
 | 
			
		||||
      interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} {
 | 
			
		||||
#ifdef ARCHITECTURE_x86_64
 | 
			
		||||
    // TODO(bunnei): Initialization relies on a core being available. We may later replace this with
 | 
			
		||||
    // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
 | 
			
		||||
 
 | 
			
		||||
@@ -6,13 +6,10 @@
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
 | 
			
		||||
namespace Common {
 | 
			
		||||
class SpinLock;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
class KScheduler;
 | 
			
		||||
} // namespace Kernel
 | 
			
		||||
@@ -91,7 +88,7 @@ private:
 | 
			
		||||
    Core::System& system;
 | 
			
		||||
    Kernel::KScheduler& scheduler;
 | 
			
		||||
    Core::CPUInterrupts& interrupts;
 | 
			
		||||
    std::unique_ptr<Common::SpinLock> guard;
 | 
			
		||||
    std::unique_ptr<std::mutex> guard;
 | 
			
		||||
    std::unique_ptr<Core::ARM_Interface> arm_interface;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <boost/container/flat_map.hpp>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/spin_lock.h"
 | 
			
		||||
#include "core/hle/kernel/hle_ipc.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -90,7 +89,7 @@ protected:
 | 
			
		||||
    using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&);
 | 
			
		||||
 | 
			
		||||
    /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
 | 
			
		||||
    [[nodiscard]] std::scoped_lock<Common::SpinLock> LockService() {
 | 
			
		||||
    [[nodiscard]] std::scoped_lock<std::mutex> LockService() {
 | 
			
		||||
        return std::scoped_lock{lock_service};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -135,7 +134,7 @@ private:
 | 
			
		||||
    boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc;
 | 
			
		||||
 | 
			
		||||
    /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
 | 
			
		||||
    Common::SpinLock lock_service;
 | 
			
		||||
    std::mutex lock_service;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user