mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
kern: update scheduler for new switch count tracking logic
This commit is contained in:
parent
8176f085f1
commit
3a5f406c5f
6 changed files with 39 additions and 18 deletions
|
@ -263,7 +263,7 @@
|
||||||
/* NOTE: Due to constraints on ldarb relative offsets, KSCHEDULER_NEEDS_SCHEDULING cannot trivially be changed, and will require assembly edits. */
|
/* NOTE: Due to constraints on ldarb relative offsets, KSCHEDULER_NEEDS_SCHEDULING cannot trivially be changed, and will require assembly edits. */
|
||||||
#define KSCHEDULER_NEEDS_SCHEDULING 0x00
|
#define KSCHEDULER_NEEDS_SCHEDULING 0x00
|
||||||
#define KSCHEDULER_INTERRUPT_TASK_RUNNABLE 0x01
|
#define KSCHEDULER_INTERRUPT_TASK_RUNNABLE 0x01
|
||||||
#define KSCHEDULER_HIGHEST_PRIORITY_THREAD 0x10
|
#define KSCHEDULER_HIGHEST_PRIORITY_THREAD 0x18
|
||||||
#define KSCHEDULER_IDLE_THREAD_STACK 0x18
|
#define KSCHEDULER_IDLE_THREAD_STACK 0x20
|
||||||
#define KSCHEDULER_PREVIOUS_THREAD 0x20
|
#define KSCHEDULER_PREVIOUS_THREAD 0x28
|
||||||
#define KSCHEDULER_INTERRUPT_TASK_MANAGER 0x28
|
#define KSCHEDULER_INTERRUPT_TASK_MANAGER 0x30
|
||||||
|
|
|
@ -108,6 +108,7 @@ namespace ams::kern {
|
||||||
KWaitObject m_wait_object;
|
KWaitObject m_wait_object;
|
||||||
KThread *m_running_threads[cpu::NumCores];
|
KThread *m_running_threads[cpu::NumCores];
|
||||||
u64 m_running_thread_idle_counts[cpu::NumCores];
|
u64 m_running_thread_idle_counts[cpu::NumCores];
|
||||||
|
u64 m_running_thread_switch_counts[cpu::NumCores];
|
||||||
KThread *m_pinned_threads[cpu::NumCores];
|
KThread *m_pinned_threads[cpu::NumCores];
|
||||||
util::Atomic<s64> m_cpu_time;
|
util::Atomic<s64> m_cpu_time;
|
||||||
util::Atomic<s64> m_num_process_switches;
|
util::Atomic<s64> m_num_process_switches;
|
||||||
|
@ -285,9 +286,10 @@ namespace ams::kern {
|
||||||
return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetUsedSize() : 0;
|
return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetUsedSize() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRunningThread(s32 core, KThread *thread, u64 idle_count) {
|
void SetRunningThread(s32 core, KThread *thread, u64 idle_count, u64 switch_count) {
|
||||||
m_running_threads[core] = thread;
|
m_running_threads[core] = thread;
|
||||||
m_running_thread_idle_counts[core] = idle_count;
|
m_running_thread_idle_counts[core] = idle_count;
|
||||||
|
m_running_thread_switch_counts[core] = switch_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearRunningThread(KThread *thread) {
|
void ClearRunningThread(KThread *thread) {
|
||||||
|
@ -306,6 +308,7 @@ namespace ams::kern {
|
||||||
|
|
||||||
constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; }
|
constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; }
|
||||||
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; }
|
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; }
|
||||||
|
constexpr u64 GetRunningThreadSwitchCount(s32 core) const { return m_running_thread_switch_counts[core]; }
|
||||||
|
|
||||||
void RegisterThread(KThread *thread);
|
void RegisterThread(KThread *thread);
|
||||||
void UnregisterThread(KThread *thread);
|
void UnregisterThread(KThread *thread);
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace ams::kern {
|
||||||
bool interrupt_task_runnable{false};
|
bool interrupt_task_runnable{false};
|
||||||
bool should_count_idle{false};
|
bool should_count_idle{false};
|
||||||
u64 idle_count{0};
|
u64 idle_count{0};
|
||||||
|
u64 switch_count{0};
|
||||||
KThread *highest_priority_thread{nullptr};
|
KThread *highest_priority_thread{nullptr};
|
||||||
void *idle_thread_stack{nullptr};
|
void *idle_thread_stack{nullptr};
|
||||||
KThread *prev_thread{nullptr};
|
KThread *prev_thread{nullptr};
|
||||||
|
@ -67,6 +68,7 @@ namespace ams::kern {
|
||||||
m_state.interrupt_task_runnable = false;
|
m_state.interrupt_task_runnable = false;
|
||||||
m_state.should_count_idle = false;
|
m_state.should_count_idle = false;
|
||||||
m_state.idle_count = 0;
|
m_state.idle_count = 0;
|
||||||
|
m_state.switch_count = 0;
|
||||||
m_state.idle_thread_stack = nullptr;
|
m_state.idle_thread_stack = nullptr;
|
||||||
m_state.highest_priority_thread = nullptr;
|
m_state.highest_priority_thread = nullptr;
|
||||||
m_state.prev_thread = nullptr;
|
m_state.prev_thread = nullptr;
|
||||||
|
@ -93,6 +95,10 @@ namespace ams::kern {
|
||||||
return m_state.idle_count;
|
return m_state.idle_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE u64 GetSwitchCount() const {
|
||||||
|
return m_state.switch_count;
|
||||||
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE KThread *GetIdleThread() const {
|
ALWAYS_INLINE KThread *GetIdleThread() const {
|
||||||
return m_idle_thread;
|
return m_idle_thread;
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,12 +219,21 @@ namespace ams::kern {
|
||||||
const s32 core_id = GetCurrentCoreId();
|
const s32 core_id = GetCurrentCoreId();
|
||||||
KThread *thread = process->GetRunningThread(core_id);
|
KThread *thread = process->GetRunningThread(core_id);
|
||||||
|
|
||||||
/* Check that the thread's idle count is correct. */
|
/* We want to check that the thread is actually running. */
|
||||||
R_UNLESS(process->GetRunningThreadIdleCount(core_id) == Kernel::GetScheduler(core_id).GetIdleCount(), svc::ResultNoThread());
|
/* If it is, then the scheduler will have just switched from the thread to the current thread. */
|
||||||
|
/* This implies exactly one switch will have taken place, and the current thread will be on the current core. */
|
||||||
/* Check that the thread is running on the current core. */
|
const auto &scheduler = Kernel::GetScheduler(core_id);
|
||||||
R_UNLESS(thread != nullptr, svc::ResultUnknownThread());
|
if (!(thread != nullptr && thread->GetActiveCore() == core_id && process->GetRunningThreadSwitchCount(core_id) + 1 == scheduler.GetSwitchCount())) {
|
||||||
R_UNLESS(thread->GetActiveCore() == core_id, svc::ResultUnknownThread());
|
/* The most recent thread switch was from a thread other than the expected one to the current one. */
|
||||||
|
/* We want to use the appropriate result to inform userland about what thread we switched from. */
|
||||||
|
if (scheduler.GetIdleCount() + 1 == scheduler.GetSwitchCount()) {
|
||||||
|
/* We switched from the idle thread. */
|
||||||
|
R_THROW(svc::ResultNoThread());
|
||||||
|
} else {
|
||||||
|
/* We switched from some other unknown thread. */
|
||||||
|
R_THROW(svc::ResultUnknownThread());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the thread's exception context. */
|
/* Get the thread's exception context. */
|
||||||
GetExceptionContext(thread)->GetSvcThreadContext(out_context);
|
GetExceptionContext(thread)->GetSvcThreadContext(out_context);
|
||||||
|
|
|
@ -211,9 +211,10 @@ namespace ams::kern {
|
||||||
|
|
||||||
/* Set thread fields. */
|
/* Set thread fields. */
|
||||||
for (size_t i = 0; i < cpu::NumCores; i++) {
|
for (size_t i = 0; i < cpu::NumCores; i++) {
|
||||||
m_running_threads[i] = nullptr;
|
m_running_threads[i] = nullptr;
|
||||||
m_pinned_threads[i] = nullptr;
|
m_pinned_threads[i] = nullptr;
|
||||||
m_running_thread_idle_counts[i] = 0;
|
m_running_thread_idle_counts[i] = 0;
|
||||||
|
m_running_thread_switch_counts[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set max memory based on address space type. */
|
/* Set max memory based on address space type. */
|
||||||
|
|
|
@ -88,10 +88,12 @@ namespace ams::kern {
|
||||||
if (m_state.should_count_idle) {
|
if (m_state.should_count_idle) {
|
||||||
if (AMS_LIKELY(highest_thread != nullptr)) {
|
if (AMS_LIKELY(highest_thread != nullptr)) {
|
||||||
if (KProcess *process = highest_thread->GetOwnerProcess(); process != nullptr) {
|
if (KProcess *process = highest_thread->GetOwnerProcess(); process != nullptr) {
|
||||||
process->SetRunningThread(m_core_id, highest_thread, m_state.idle_count);
|
/* Set running thread (and increment switch count). */
|
||||||
|
process->SetRunningThread(m_core_id, highest_thread, m_state.idle_count, ++m_state.switch_count);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_state.idle_count++;
|
/* Set idle count and switch count to switch count + 1. */
|
||||||
|
m_state.idle_count = ++m_state.switch_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue