timer.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/assert.h"
  5. #include "common/logging/log.h"
  6. #include "core/core.h"
  7. #include "core/core_timing.h"
  8. #include "core/core_timing_util.h"
  9. #include "core/hle/kernel/handle_table.h"
  10. #include "core/hle/kernel/kernel.h"
  11. #include "core/hle/kernel/object.h"
  12. #include "core/hle/kernel/thread.h"
  13. #include "core/hle/kernel/timer.h"
  14. namespace Kernel {
  15. Timer::Timer(KernelCore& kernel) : WaitObject{kernel} {}
  16. Timer::~Timer() = default;
  17. SharedPtr<Timer> Timer::Create(KernelCore& kernel, ResetType reset_type, std::string name) {
  18. SharedPtr<Timer> timer(new Timer(kernel));
  19. timer->reset_type = reset_type;
  20. timer->signaled = false;
  21. timer->name = std::move(name);
  22. timer->initial_delay = 0;
  23. timer->interval_delay = 0;
  24. timer->callback_handle = kernel.CreateTimerCallbackHandle(timer).Unwrap();
  25. return timer;
  26. }
  27. bool Timer::ShouldWait(Thread* thread) const {
  28. return !signaled;
  29. }
  30. void Timer::Acquire(Thread* thread) {
  31. ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
  32. if (reset_type == ResetType::OneShot)
  33. signaled = false;
  34. }
  35. void Timer::Set(s64 initial, s64 interval) {
  36. // Ensure we get rid of any previous scheduled event
  37. Cancel();
  38. initial_delay = initial;
  39. interval_delay = interval;
  40. if (initial == 0) {
  41. // Immediately invoke the callback
  42. Signal(0);
  43. } else {
  44. CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), kernel.TimerCallbackEventType(),
  45. callback_handle);
  46. }
  47. }
  48. void Timer::Cancel() {
  49. CoreTiming::UnscheduleEvent(kernel.TimerCallbackEventType(), callback_handle);
  50. }
  51. void Timer::Clear() {
  52. signaled = false;
  53. }
  54. void Timer::Signal(int cycles_late) {
  55. LOG_TRACE(Kernel, "Timer {} fired", GetObjectId());
  56. signaled = true;
  57. // Resume all waiting threads
  58. WakeupAllWaitingThreads();
  59. if (interval_delay != 0) {
  60. // Reschedule the timer with the interval delay
  61. CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(interval_delay) - cycles_late,
  62. kernel.TimerCallbackEventType(), callback_handle);
  63. }
  64. }
  65. } // namespace Kernel