kern: kill the interrupt task manager thread

This commit is contained in:
Michael Scire
2021-09-17 16:12:01 -07:00
parent a85a87a907
commit 05e9084e93
9 changed files with 112 additions and 140 deletions

View File

@@ -59,50 +59,6 @@ namespace ams::kern {
#endif
}
void KInterruptTaskManager::ThreadFunction(uintptr_t arg) {
reinterpret_cast<KInterruptTaskManager *>(arg)->ThreadFunctionImpl();
}
void KInterruptTaskManager::ThreadFunctionImpl() {
MESOSPHERE_ASSERT_THIS();
while (true) {
/* Get a task. */
KInterruptTask *task = nullptr;
{
KScopedInterruptDisable di;
task = m_task_queue.GetHead();
if (task == nullptr) {
m_thread->SetState(KThread::ThreadState_Waiting);
continue;
}
m_task_queue.Dequeue();
}
/* Do the task. */
task->DoTask();
/* Destroy any objects we may need to close. */
m_thread->DestroyClosedObjects();
}
}
void KInterruptTaskManager::Initialize() {
/* Reserve a thread from the system limit. */
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_ThreadCountMax, 1));
/* Create and initialize the thread. */
m_thread = KThread::Create();
MESOSPHERE_ABORT_UNLESS(m_thread != nullptr);
MESOSPHERE_R_ABORT_UNLESS(KThread::InitializeHighPriorityThread(m_thread, ThreadFunction, reinterpret_cast<uintptr_t>(this)));
KThread::Register(m_thread);
/* Run the thread. */
m_thread->Run();
}
void KInterruptTaskManager::EnqueueTask(KInterruptTask *task) {
MESOSPHERE_ASSERT(!KInterruptManager::AreInterruptsEnabled());
@@ -111,4 +67,24 @@ namespace ams::kern {
Kernel::GetScheduler().SetInterruptTaskRunnable();
}
void KInterruptTaskManager::DoTasks() {
/* Execute pending tasks. */
const s64 start_time = KHardwareTimer::GetTick();
for (KInterruptTask *task = m_task_queue.GetHead(); task != nullptr; task = m_task_queue.GetHead()) {
/* Dequeue the task. */
m_task_queue.Dequeue();
/* Do the task with interrupts temporarily enabled. */
{
KScopedInterruptEnable ei;
task->DoTask();
}
}
const s64 end_time = KHardwareTimer::GetTick();
/* Increment the time we've spent executing. */
m_cpu_time += end_time - start_time;
}
}

View File

@@ -55,10 +55,11 @@ namespace ams::kern {
}
void KScheduler::Initialize(KThread *idle_thread) {
/* Set core ID and idle thread. */
m_core_id = GetCurrentCoreId();
m_idle_thread = idle_thread;
m_state.idle_thread_stack = m_idle_thread->GetStackTop();
/* Set core ID/idle thread/interrupt task manager. */
m_core_id = GetCurrentCoreId();
m_idle_thread = idle_thread;
m_state.idle_thread_stack = m_idle_thread->GetStackTop();
m_state.interrupt_task_manager = std::addressof(Kernel::GetInterruptTaskManager());
/* Insert the main thread into the priority queue. */
{
@@ -212,19 +213,9 @@ namespace ams::kern {
return cores_needing_scheduling;
}
void KScheduler::InterruptTaskThreadToRunnable() {
MESOSPHERE_ASSERT(GetCurrentThread().GetDisableDispatchCount() == 1);
KThread *task_thread = Kernel::GetInterruptTaskManager().GetThread();
{
KScopedSchedulerLock sl;
task_thread->SetState(KThread::ThreadState_Runnable);
}
}
void KScheduler::SwitchThread(KThread *next_thread) {
KProcess *cur_process = GetCurrentProcessPointer();
KThread *cur_thread = GetCurrentThreadPointer();
KProcess * const cur_process = GetCurrentProcessPointer();
KThread * const cur_thread = GetCurrentThreadPointer();
/* We never want to schedule a null thread, so use the idle thread if we don't have a next. */
if (next_thread == nullptr) {
@@ -257,12 +248,10 @@ namespace ams::kern {
if (cur_process != nullptr) {
/* NOTE: Combining this into AMS_LIKELY(!... && ...) triggers an internal compiler error: Segmentation fault in GCC 9.2.0. */
if (AMS_LIKELY(!cur_thread->IsTerminationRequested()) && AMS_LIKELY(cur_thread->GetActiveCore() == m_core_id)) {
m_prev_thread = cur_thread;
m_state.prev_thread = cur_thread;
} else {
m_prev_thread = nullptr;
m_state.prev_thread = nullptr;
}
} else if (cur_thread == m_idle_thread) {
m_prev_thread = nullptr;
}
MESOSPHERE_KTRACE_THREAD_SWITCH(next_thread);
@@ -284,7 +273,7 @@ namespace ams::kern {
MESOSPHERE_ASSERT(IsSchedulerLockedByCurrentThread());
for (size_t i = 0; i < cpu::NumCores; ++i) {
/* Get an atomic reference to the core scheduler's previous thread. */
std::atomic_ref<KThread *> prev_thread(Kernel::GetScheduler(static_cast<s32>(i)).m_prev_thread);
std::atomic_ref<KThread *> prev_thread(Kernel::GetScheduler(static_cast<s32>(i)).m_state.prev_thread);
static_assert(std::atomic_ref<KThread *>::is_always_lock_free);
/* Atomically clear the previous thread if it's our target. */

View File

@@ -99,7 +99,6 @@ namespace ams::kern {
DoOnEachCoreInOrder(core_id, [=]() ALWAYS_INLINE_LAMBDA {
KThread::Register(std::addressof(Kernel::GetMainThread(core_id)));
KThread::Register(std::addressof(Kernel::GetIdleThread(core_id)));
Kernel::GetInterruptTaskManager().Initialize();
});
/* Activate the scheduler and enable interrupts. */

View File

@@ -189,7 +189,7 @@ namespace ams::kern::svc {
R_UNLESS(core_valid, svc::ResultInvalidCombination());
/* Get the idle tick count. */
*out = Kernel::GetScheduler().GetIdleThread()->GetCpuTime();
*out = Kernel::GetScheduler().GetIdleThread()->GetCpuTime() - Kernel::GetInterruptTaskManager().GetCpuTime();
}
break;
case ams::svc::InfoType_RandomEntropy: