Merge pull request #5131 from bunnei/scheduler-rewrite
Rewrite Kernel scheduler based on Atmosphere
This commit is contained in:
commit
1279c7ce7a
41 changed files with 2218 additions and 1874 deletions
|
@ -24,6 +24,8 @@
|
|||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/memory/memory_block.h"
|
||||
#include "core/hle/kernel/memory/page_table.h"
|
||||
|
@ -32,7 +34,6 @@
|
|||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/readable_event.h"
|
||||
#include "core/hle/kernel/resource_limit.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/kernel/svc_types.h"
|
||||
|
@ -329,7 +330,8 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle,
|
|||
|
||||
/// Makes a blocking IPC call to an OS service.
|
||||
static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||
auto& kernel = system.Kernel();
|
||||
const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
|
||||
std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle);
|
||||
if (!session) {
|
||||
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
|
||||
|
@ -338,9 +340,9 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
|||
|
||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
|
||||
|
||||
auto thread = system.CurrentScheduler().GetCurrentThread();
|
||||
auto thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
{
|
||||
SchedulerLock lock(system.Kernel());
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
thread->InvalidateHLECallback();
|
||||
thread->SetStatus(ThreadStatus::WaitIPC);
|
||||
session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
|
||||
|
@ -349,12 +351,12 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
|||
if (thread->HasHLECallback()) {
|
||||
Handle event_handle = thread->GetHLETimeEvent();
|
||||
if (event_handle != InvalidHandle) {
|
||||
auto& time_manager = system.Kernel().TimeManager();
|
||||
auto& time_manager = kernel.TimeManager();
|
||||
time_manager.UnscheduleTimeEvent(event_handle);
|
||||
}
|
||||
|
||||
{
|
||||
SchedulerLock lock(system.Kernel());
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
auto* sync_object = thread->GetHLESyncObject();
|
||||
sync_object->RemoveWaitingThread(SharedFrom(thread));
|
||||
}
|
||||
|
@ -654,7 +656,6 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
|
|||
info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt);
|
||||
|
||||
if (!break_reason.signal_debugger) {
|
||||
SchedulerLock lock(system.Kernel());
|
||||
LOG_CRITICAL(
|
||||
Debug_Emulated,
|
||||
"Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
|
||||
|
@ -662,13 +663,9 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
|
|||
|
||||
handle_debug_buffer(info1, info2);
|
||||
|
||||
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||
auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
|
||||
const auto thread_processor_id = current_thread->GetProcessorID();
|
||||
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
|
||||
|
||||
// Kill the current thread
|
||||
system.Kernel().ExceptionalExit();
|
||||
current_thread->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -918,7 +915,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
|||
}
|
||||
|
||||
const auto& core_timing = system.CoreTiming();
|
||||
const auto& scheduler = system.CurrentScheduler();
|
||||
const auto& scheduler = *system.Kernel().CurrentScheduler();
|
||||
const auto* const current_thread = scheduler.GetCurrentThread();
|
||||
const bool same_thread = current_thread == thread.get();
|
||||
|
||||
|
@ -1086,7 +1083,7 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act
|
|||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (thread.get() == system.CurrentScheduler().GetCurrentThread()) {
|
||||
if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
|
||||
LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
|
||||
return ERR_BUSY;
|
||||
}
|
||||
|
@ -1119,7 +1116,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H
|
|||
return ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (thread.get() == system.CurrentScheduler().GetCurrentThread()) {
|
||||
if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
|
||||
LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
|
||||
return ERR_BUSY;
|
||||
}
|
||||
|
@ -1475,7 +1472,7 @@ static void ExitProcess(Core::System& system) {
|
|||
current_process->PrepareForTermination();
|
||||
|
||||
// Kill the current thread
|
||||
system.CurrentScheduler().GetCurrentThread()->Stop();
|
||||
system.Kernel().CurrentScheduler()->GetCurrentThread()->Stop();
|
||||
}
|
||||
|
||||
static void ExitProcess32(Core::System& system) {
|
||||
|
@ -1575,8 +1572,8 @@ static ResultCode StartThread32(Core::System& system, Handle thread_handle) {
|
|||
static void ExitThread(Core::System& system) {
|
||||
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
|
||||
|
||||
auto* const current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||
system.GlobalScheduler().RemoveThread(SharedFrom(current_thread));
|
||||
auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
|
||||
system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread));
|
||||
current_thread->Stop();
|
||||
}
|
||||
|
||||
|
@ -1589,44 +1586,31 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
|
|||
LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds);
|
||||
|
||||
enum class SleepType : s64 {
|
||||
YieldWithoutLoadBalancing = 0,
|
||||
YieldWithLoadBalancing = -1,
|
||||
YieldWithoutCoreMigration = 0,
|
||||
YieldWithCoreMigration = -1,
|
||||
YieldAndWaitForLoadBalancing = -2,
|
||||
};
|
||||
|
||||
auto& scheduler = system.CurrentScheduler();
|
||||
auto* const current_thread = scheduler.GetCurrentThread();
|
||||
bool is_redundant = false;
|
||||
|
||||
auto& scheduler = *system.Kernel().CurrentScheduler();
|
||||
if (nanoseconds <= 0) {
|
||||
switch (static_cast<SleepType>(nanoseconds)) {
|
||||
case SleepType::YieldWithoutLoadBalancing: {
|
||||
auto pair = current_thread->YieldSimple();
|
||||
is_redundant = pair.second;
|
||||
case SleepType::YieldWithoutCoreMigration: {
|
||||
scheduler.YieldWithoutCoreMigration();
|
||||
break;
|
||||
}
|
||||
case SleepType::YieldWithLoadBalancing: {
|
||||
auto pair = current_thread->YieldAndBalanceLoad();
|
||||
is_redundant = pair.second;
|
||||
case SleepType::YieldWithCoreMigration: {
|
||||
scheduler.YieldWithCoreMigration();
|
||||
break;
|
||||
}
|
||||
case SleepType::YieldAndWaitForLoadBalancing: {
|
||||
auto pair = current_thread->YieldAndWaitForLoadBalancing();
|
||||
is_redundant = pair.second;
|
||||
scheduler.YieldToAnyThread();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
|
||||
}
|
||||
} else {
|
||||
current_thread->Sleep(nanoseconds);
|
||||
}
|
||||
|
||||
if (is_redundant && !system.Kernel().IsMulticore()) {
|
||||
system.Kernel().ExitSVCProfile();
|
||||
system.CoreTiming().AddTicks(1000U);
|
||||
system.GetCpuManager().PreemptSingleCore();
|
||||
system.Kernel().EnterSVCProfile();
|
||||
scheduler.GetCurrentThread()->Sleep(nanoseconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1661,10 +1645,10 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
|
|||
ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4));
|
||||
auto& kernel = system.Kernel();
|
||||
Handle event_handle;
|
||||
Thread* current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||
auto* const current_process = system.Kernel().CurrentProcess();
|
||||
Thread* current_thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
auto* const current_process = kernel.CurrentProcess();
|
||||
{
|
||||
SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds);
|
||||
KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds);
|
||||
const auto& handle_table = current_process->GetHandleTable();
|
||||
std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||
ASSERT(thread);
|
||||
|
@ -1700,7 +1684,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
|
|||
}
|
||||
|
||||
{
|
||||
SchedulerLock lock(kernel);
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
|
||||
auto* owner = current_thread->GetLockOwner();
|
||||
if (owner != nullptr) {
|
||||
|
@ -1731,7 +1715,7 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
|
|||
|
||||
// Retrieve a list of all threads that are waiting for this condition variable.
|
||||
auto& kernel = system.Kernel();
|
||||
SchedulerLock lock(kernel);
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
auto* const current_process = kernel.CurrentProcess();
|
||||
std::vector<std::shared_ptr<Thread>> waiting_threads =
|
||||
current_process->GetConditionVariableThreads(condition_variable_addr);
|
||||
|
@ -1993,7 +1977,7 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
|
|||
}
|
||||
|
||||
*core = thread->GetIdealCore();
|
||||
*mask = thread->GetAffinityMask();
|
||||
*mask = thread->GetAffinityMask().GetAffinityMask();
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
@ -2629,7 +2613,7 @@ void Call(Core::System& system, u32 immediate) {
|
|||
auto& kernel = system.Kernel();
|
||||
kernel.EnterSVCProfile();
|
||||
|
||||
auto* thread = system.CurrentScheduler().GetCurrentThread();
|
||||
auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
thread->SetContinuousOnSVC(true);
|
||||
|
||||
const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue