Kernel: Implement Scheduler locks
This commit is contained in:
parent
5c90d22f3d
commit
ea956c823e
|
@ -18,6 +18,7 @@
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
|
#include "core/hle/kernel/time_manager.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -356,6 +357,29 @@ void GlobalScheduler::Shutdown() {
|
||||||
thread_list.clear();
|
thread_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlobalScheduler::Lock() {
|
||||||
|
Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadId();
|
||||||
|
if (current_thread == current_owner) {
|
||||||
|
++scope_lock;
|
||||||
|
} else {
|
||||||
|
inner_lock.lock();
|
||||||
|
current_owner = current_thread;
|
||||||
|
scope_lock = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalScheduler::Unlock() {
|
||||||
|
if (--scope_lock == 0) {
|
||||||
|
for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
|
||||||
|
SelectThread(i);
|
||||||
|
}
|
||||||
|
current_owner = Core::EmuThreadHandle::InvalidHandle();
|
||||||
|
scope_lock = 1;
|
||||||
|
inner_lock.unlock();
|
||||||
|
// TODO(Blinkhawk): Setup the interrupts and change context on current core.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id)
|
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id)
|
||||||
: system(system), cpu_core(cpu_core), core_id(core_id) {}
|
: system(system), cpu_core(cpu_core), core_id(core_id) {}
|
||||||
|
|
||||||
|
@ -485,4 +509,28 @@ void Scheduler::Shutdown() {
|
||||||
selected_thread = nullptr;
|
selected_thread = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SchedulerLock::SchedulerLock(KernelCore& kernel) : kernel{kernel} {
|
||||||
|
auto& global_scheduler = kernel.GlobalScheduler();
|
||||||
|
global_scheduler.Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
SchedulerLock::~SchedulerLock() {
|
||||||
|
auto& global_scheduler = kernel.GlobalScheduler();
|
||||||
|
global_scheduler.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
SchedulerLockAndSleep::SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle,
|
||||||
|
Thread* time_task, s64 nanoseconds)
|
||||||
|
: SchedulerLock{kernel}, event_handle{event_handle}, time_task{time_task}, nanoseconds{
|
||||||
|
nanoseconds} {
|
||||||
|
event_handle = InvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SchedulerLockAndSleep::~SchedulerLockAndSleep() {
|
||||||
|
if (!sleep_cancelled) {
|
||||||
|
auto& time_manager = kernel.TimeManager();
|
||||||
|
time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
@ -22,6 +23,7 @@ namespace Kernel {
|
||||||
|
|
||||||
class KernelCore;
|
class KernelCore;
|
||||||
class Process;
|
class Process;
|
||||||
|
class SchedulerLock;
|
||||||
|
|
||||||
class GlobalScheduler final {
|
class GlobalScheduler final {
|
||||||
public:
|
public:
|
||||||
|
@ -139,6 +141,14 @@ public:
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class SchedulerLock;
|
||||||
|
|
||||||
|
/// Lock the scheduler to the current thread.
|
||||||
|
void Lock();
|
||||||
|
|
||||||
|
/// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling
|
||||||
|
/// and reschedules current core if needed.
|
||||||
|
void Unlock();
|
||||||
/**
|
/**
|
||||||
* Transfers a thread into an specific core. If the destination_core is -1
|
* Transfers a thread into an specific core. If the destination_core is -1
|
||||||
* it will be unscheduled from its source code and added into its suggested
|
* it will be unscheduled from its source code and added into its suggested
|
||||||
|
@ -159,6 +169,11 @@ private:
|
||||||
// ordered from Core 0 to Core 3.
|
// ordered from Core 0 to Core 3.
|
||||||
std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62};
|
std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62};
|
||||||
|
|
||||||
|
/// Scheduler lock mechanisms.
|
||||||
|
std::mutex inner_lock{}; // TODO(Blinkhawk): Replace for a SpinLock
|
||||||
|
std::atomic<std::size_t> scope_lock{};
|
||||||
|
Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()};
|
||||||
|
|
||||||
/// Lists all thread ids that aren't deleted/etc.
|
/// Lists all thread ids that aren't deleted/etc.
|
||||||
std::vector<std::shared_ptr<Thread>> thread_list;
|
std::vector<std::shared_ptr<Thread>> thread_list;
|
||||||
KernelCore& kernel;
|
KernelCore& kernel;
|
||||||
|
@ -228,4 +243,30 @@ private:
|
||||||
bool is_context_switch_pending = false;
|
bool is_context_switch_pending = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SchedulerLock {
|
||||||
|
public:
|
||||||
|
SchedulerLock(KernelCore& kernel);
|
||||||
|
~SchedulerLock();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
KernelCore& kernel;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SchedulerLockAndSleep : public SchedulerLock {
|
||||||
|
public:
|
||||||
|
SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task,
|
||||||
|
s64 nanoseconds);
|
||||||
|
~SchedulerLockAndSleep();
|
||||||
|
|
||||||
|
void CancelSleep() {
|
||||||
|
sleep_cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Handle& event_handle;
|
||||||
|
Thread* time_task;
|
||||||
|
s64 nanoseconds;
|
||||||
|
bool sleep_cancelled{};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
Reference in New Issue