kern: implement much of KScheduler, KHardwareTimer
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user