kernel/timer: add TimerManager for timer system states

This commit is contained in:
Weiyi Wang 2018-10-23 14:17:30 -04:00
parent 20ae37ba4f
commit e5b93741d3
4 changed files with 49 additions and 28 deletions

View file

@ -22,12 +22,11 @@ KernelSystem::KernelSystem(u32 system_mode) {
resource_limits = std::make_unique<ResourceLimitList>(*this); resource_limits = std::make_unique<ResourceLimitList>(*this);
thread_manager = std::make_unique<ThreadManager>(); thread_manager = std::make_unique<ThreadManager>();
Kernel::TimersInit(); timer_manager = std::make_unique<TimerManager>();
} }
/// Shutdown the kernel /// Shutdown the kernel
KernelSystem::~KernelSystem() { KernelSystem::~KernelSystem() {
Kernel::TimersShutdown();
Kernel::MemoryShutdown(); Kernel::MemoryShutdown();
} }
@ -59,4 +58,12 @@ const ThreadManager& KernelSystem::GetThreadManager() const {
return *thread_manager; return *thread_manager;
} }
TimerManager& KernelSystem::GetTimerManager() {
return *timer_manager;
}
const TimerManager& KernelSystem::GetTimerManager() const {
return *timer_manager;
}
} // namespace Kernel } // namespace Kernel

View file

@ -29,6 +29,7 @@ class ServerSession;
class ResourceLimitList; class ResourceLimitList;
class SharedMemory; class SharedMemory;
class ThreadManager; class ThreadManager;
class TimerManager;
enum class ResetType { enum class ResetType {
OneShot, OneShot,
@ -191,6 +192,9 @@ public:
ThreadManager& GetThreadManager(); ThreadManager& GetThreadManager();
const ThreadManager& GetThreadManager() const; const ThreadManager& GetThreadManager() const;
TimerManager& GetTimerManager();
const TimerManager& GetTimerManager() const;
private: private:
std::unique_ptr<ResourceLimitList> resource_limits; std::unique_ptr<ResourceLimitList> resource_limits;
std::atomic<u32> next_object_id{0}; std::atomic<u32> next_object_id{0};
@ -205,6 +209,7 @@ private:
SharedPtr<Process> current_process; SharedPtr<Process> current_process;
std::unique_ptr<ThreadManager> thread_manager; std::unique_ptr<ThreadManager> thread_manager;
std::unique_ptr<TimerManager> timer_manager;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -6,7 +6,6 @@
#include <unordered_map> #include <unordered_map>
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core_timing.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
@ -14,16 +13,10 @@
namespace Kernel { namespace Kernel {
/// The event type of the generic timer callback event Timer::Timer(KernelSystem& kernel) : WaitObject(kernel), timer_manager(kernel.GetTimerManager()) {}
static CoreTiming::EventType* timer_callback_event_type = nullptr;
static u64 next_timer_callback_id;
static std::unordered_map<u64, Timer*> timer_callback_table;
Timer::Timer(KernelSystem& kernel) : WaitObject(kernel) {}
Timer::~Timer() { Timer::~Timer() {
Cancel(); Cancel();
timer_callback_table.erase(callback_id); timer_manager.timer_callback_table.erase(callback_id);
} }
SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) { SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
@ -34,8 +27,8 @@ SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string nam
timer->name = std::move(name); timer->name = std::move(name);
timer->initial_delay = 0; timer->initial_delay = 0;
timer->interval_delay = 0; timer->interval_delay = 0;
timer->callback_id = ++next_timer_callback_id; timer->callback_id = ++timer_manager->next_timer_callback_id;
timer_callback_table[timer->callback_id] = timer.get(); timer_manager->timer_callback_table[timer->callback_id] = timer.get();
return timer; return timer;
} }
@ -62,12 +55,13 @@ void Timer::Set(s64 initial, s64 interval) {
// Immediately invoke the callback // Immediately invoke the callback
Signal(0); Signal(0);
} else { } else {
CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type, callback_id); CoreTiming::ScheduleEvent(nsToCycles(initial), timer_manager.timer_callback_event_type,
callback_id);
} }
} }
void Timer::Cancel() { void Timer::Cancel() {
CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_id); CoreTiming::UnscheduleEvent(timer_manager.timer_callback_event_type, callback_id);
} }
void Timer::Clear() { void Timer::Clear() {
@ -92,12 +86,12 @@ void Timer::Signal(s64 cycles_late) {
if (interval_delay != 0) { if (interval_delay != 0) {
// Reschedule the timer with the interval delay // Reschedule the timer with the interval delay
CoreTiming::ScheduleEvent(nsToCycles(interval_delay) - cycles_late, CoreTiming::ScheduleEvent(nsToCycles(interval_delay) - cycles_late,
timer_callback_event_type, callback_id); timer_manager.timer_callback_event_type, callback_id);
} }
} }
/// The timer callback event, called when a timer is fired /// The timer callback event, called when a timer is fired
static void TimerCallback(u64 callback_id, s64 cycles_late) { void TimerManager::TimerCallback(u64 callback_id, s64 cycles_late) {
SharedPtr<Timer> timer = timer_callback_table.at(callback_id); SharedPtr<Timer> timer = timer_callback_table.at(callback_id);
if (timer == nullptr) { if (timer == nullptr) {
@ -108,12 +102,11 @@ static void TimerCallback(u64 callback_id, s64 cycles_late) {
timer->Signal(cycles_late); timer->Signal(cycles_late);
} }
void TimersInit() { TimerManager::TimerManager() {
next_timer_callback_id = 0; timer_callback_event_type =
timer_callback_table.clear(); CoreTiming::RegisterEvent("TimerCallback", [this](u64 thread_id, s64 cycle_late) {
timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); TimerCallback(thread_id, cycle_late);
});
} }
void TimersShutdown() {}
} // namespace Kernel } // namespace Kernel

View file

@ -5,11 +5,30 @@
#pragma once #pragma once
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core_timing.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h" #include "core/hle/kernel/wait_object.h"
namespace Kernel { namespace Kernel {
class TimerManager {
public:
TimerManager();
private:
/// The timer callback event, called when a timer is fired
void TimerCallback(u64 callback_id, s64 cycles_late);
/// The event type of the generic timer callback event
CoreTiming::EventType* timer_callback_event_type = nullptr;
u64 next_timer_callback_id = 0;
std::unordered_map<u64, Timer*> timer_callback_table;
friend class Timer;
friend class KernelSystem;
};
class Timer final : public WaitObject { class Timer final : public WaitObject {
public: public:
std::string GetTypeName() const override { std::string GetTypeName() const override {
@ -74,12 +93,9 @@ private:
/// ID used as userdata to reference this object when inserting into the CoreTiming queue. /// ID used as userdata to reference this object when inserting into the CoreTiming queue.
u64 callback_id; u64 callback_id;
TimerManager& timer_manager;
friend class KernelSystem; friend class KernelSystem;
}; };
/// Initializes the required variables for timers
void TimersInit();
/// Tears down the timer variables
void TimersShutdown();
} // namespace Kernel } // namespace Kernel