Merge pull request #5131 from bunnei/scheduler-rewrite

Rewrite Kernel scheduler based on Atmosphere
This commit is contained in:
bunnei 2020-12-20 20:57:54 -08:00 committed by GitHub
commit 1279c7ce7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 2218 additions and 1874 deletions

View file

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