kern: implement much of KScheduler, KHardwareTimer

This commit is contained in:
Michael Scire
2020-02-05 13:02:35 -08:00
parent 5e4307046a
commit 62de3322ff
19 changed files with 972 additions and 72 deletions

View File

@@ -15,13 +15,12 @@
*/
#pragma once
#include <mesosphere/kern_k_spin_lock.hpp>
#include <mesosphere/kern_k_interrupt_task.hpp>
#include <mesosphere/kern_k_timer_task.hpp>
#include <mesosphere/kern_select_interrupt_manager.hpp>
namespace ams::kern {
class KHardwareTimerBase : public KInterruptTask {
class KHardwareTimerBase {
private:
using TimerTaskTree = util::IntrusiveRedBlackTreeBaseTraits<KTimerTask>::TreeType<KTimerTask>;
private:
@@ -29,13 +28,68 @@ namespace ams::kern {
TimerTaskTree task_tree;
KTimerTask *next_task;
public:
constexpr KHardwareTimerBase() : lock(), task_tree(), next_task(nullptr) { /* ... */ }
constexpr ALWAYS_INLINE KHardwareTimerBase() : lock(), task_tree(), next_task(nullptr) { /* ... */ }
private:
ALWAYS_INLINE void RemoveTaskFromTree(KTimerTask *task) {
/* Erase from the tree. */
auto it = this->task_tree.erase(this->task_tree.iterator_to(*task));
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override { return this; }
/* Clear the task's scheduled time. */
task->SetTime(0);
/* Update our next task if relevant. */
if (this->next_task == task) {
this->next_task = (it != this->task_tree.end()) ? std::addressof(*it) : nullptr;
}
}
public:
NOINLINE void CancelTask(KTimerTask *task) {
KScopedDisableDispatch dd;
KScopedSpinLock lk(this->lock);
if (const s64 task_time = task->GetTime(); task_time > 0) {
this->RemoveTaskFromTree(task);
}
}
protected:
KSpinLock &GetLock() { return this->lock; }
ALWAYS_INLINE KSpinLock &GetLock() { return this->lock; }
/* TODO: Actually implement more of KHardwareTimerBase */
ALWAYS_INLINE s64 DoInterruptTaskImpl(s64 cur_time) {
/* We want to handle all tasks, returning the next time that a task is scheduled. */
while (true) {
/* Get the next task. If there isn't one, return 0. */
KTimerTask *task = this->next_task;
if (task == nullptr) {
return 0;
}
/* If the task needs to be done in the future, do it in the future and not now. */
if (const s64 task_time = task->GetTime(); task_time > cur_time) {
return task_time;
}
/* Remove the task from the tree of tasks, and update our next task. */
this->RemoveTaskFromTree(task);
/* Handle the task. */
task->OnTimer();
}
}
ALWAYS_INLINE bool RegisterAbsoluteTaskImpl(KTimerTask *task, s64 task_time) {
MESOSPHERE_ASSERT(task_time > 0);
/* Set the task's time, and insert it into our tree. */
task->SetTime(task_time);
this->task_tree.insert(*task);
/* Update our next task if relevant. */
if (this->next_task != nullptr && this->next_task->GetTime() <= task_time) {
return false;
}
this->next_task = task;
return true;
}
};
}