timer.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <set>
  5. #include "common/common.h"
  6. #include "core/core_timing.h"
  7. #include "core/hle/kernel/kernel.h"
  8. #include "core/hle/kernel/timer.h"
  9. #include "core/hle/kernel/thread.h"
  10. namespace Kernel {
  11. class Timer : public WaitObject {
  12. public:
  13. std::string GetTypeName() const override { return "Timer"; }
  14. std::string GetName() const override { return name; }
  15. static const HandleType HANDLE_TYPE = HandleType::Timer;
  16. HandleType GetHandleType() const override { return HANDLE_TYPE; }
  17. ResetType reset_type; ///< The ResetType of this timer
  18. bool signaled; ///< Whether the timer has been signaled or not
  19. std::string name; ///< Name of timer (optional)
  20. u64 initial_delay; ///< The delay until the timer fires for the first time
  21. u64 interval_delay; ///< The delay until the timer fires after the first time
  22. ResultVal<bool> Wait(bool wait_thread) override {
  23. bool wait = !signaled;
  24. if (wait && wait_thread) {
  25. AddWaitingThread(GetCurrentThread());
  26. Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_TIMER, this);
  27. }
  28. return MakeResult<bool>(wait);
  29. }
  30. ResultVal<bool> Acquire() override {
  31. return MakeResult<bool>(true);
  32. }
  33. };
  34. /**
  35. * Creates a timer.
  36. * @param handle Reference to handle for the newly created timer
  37. * @param reset_type ResetType describing how to create timer
  38. * @param name Optional name of timer
  39. * @return Newly created Timer object
  40. */
  41. Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
  42. Timer* timer = new Timer;
  43. handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE);
  44. timer->reset_type = reset_type;
  45. timer->signaled = false;
  46. timer->name = name;
  47. timer->initial_delay = 0;
  48. timer->interval_delay = 0;
  49. return timer;
  50. }
  51. ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) {
  52. CreateTimer(*handle, reset_type, name);
  53. return RESULT_SUCCESS;
  54. }
  55. ResultCode ClearTimer(Handle handle) {
  56. SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
  57. if (timer == nullptr)
  58. return InvalidHandle(ErrorModule::Kernel);
  59. timer->signaled = false;
  60. return RESULT_SUCCESS;
  61. }
  62. /// The event type of the generic timer callback event
  63. static int TimerCallbackEventType = -1;
  64. /// The timer callback event, called when a timer is fired
  65. static void TimerCallback(u64 timer_handle, int cycles_late) {
  66. SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
  67. if (timer == nullptr) {
  68. LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle);
  69. return;
  70. }
  71. LOG_TRACE(Kernel, "Timer %u fired", timer_handle);
  72. timer->signaled = true;
  73. // Resume all waiting threads
  74. timer->ReleaseAllWaitingThreads();
  75. if (timer->reset_type == RESETTYPE_ONESHOT)
  76. timer->signaled = false;
  77. if (timer->interval_delay != 0) {
  78. // Reschedule the timer with the interval delay
  79. u64 interval_microseconds = timer->interval_delay / 1000;
  80. CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
  81. TimerCallbackEventType, timer_handle);
  82. }
  83. }
  84. ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
  85. SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
  86. if (timer == nullptr)
  87. return InvalidHandle(ErrorModule::Kernel);
  88. timer->initial_delay = initial;
  89. timer->interval_delay = interval;
  90. u64 initial_microseconds = initial / 1000;
  91. CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
  92. return RESULT_SUCCESS;
  93. }
  94. ResultCode CancelTimer(Handle handle) {
  95. SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
  96. if (timer == nullptr)
  97. return InvalidHandle(ErrorModule::Kernel);
  98. CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
  99. return RESULT_SUCCESS;
  100. }
  101. void TimersInit() {
  102. TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
  103. }
  104. void TimersShutdown() {
  105. }
  106. } // namespace