Scheduler.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "Scheduler.hh"
  2. #include "Schedulable.hh"
  3. #include "Thread.hh"
  4. #include "MSXCPU.hh"
  5. #include "ranges.hh"
  6. #include "serialize.hh"
  7. #include "stl.hh"
  8. #include <cassert>
  9. #include <iterator> // for back_inserter
  10. namespace openmsx {
  11. struct EqualSchedulable {
  12. explicit EqualSchedulable(const Schedulable& schedulable_)
  13. : schedulable(schedulable_) {}
  14. bool operator()(const SynchronizationPoint& sp) const {
  15. return sp.getDevice() == &schedulable;
  16. }
  17. const Schedulable& schedulable;
  18. };
  19. Scheduler::~Scheduler()
  20. {
  21. assert(!cpu);
  22. auto copy = to_vector(queue);
  23. for (auto& s : copy) {
  24. s.getDevice()->schedulerDeleted();
  25. }
  26. assert(queue.empty());
  27. }
  28. void Scheduler::setSyncPoint(EmuTime::param time, Schedulable& device)
  29. {
  30. assert(Thread::isMainThread());
  31. assert(time >= scheduleTime);
  32. // Push sync point into queue.
  33. queue.insert(SynchronizationPoint(time, &device),
  34. [](SynchronizationPoint& sp) { sp.setTime(EmuTime::infinity()); },
  35. [](const SynchronizationPoint& x, const SynchronizationPoint& y) {
  36. return x.getTime() < y.getTime(); });
  37. if (!scheduleInProgress && cpu) {
  38. // only when scheduleHelper() is not being executed
  39. // otherwise getNext() doesn't return the correct time and
  40. // scheduleHelper() anyway calls setNextSyncPoint() at the end
  41. cpu->setNextSyncPoint(getNext());
  42. }
  43. }
  44. Scheduler::SyncPoints Scheduler::getSyncPoints(const Schedulable& device) const
  45. {
  46. SyncPoints result;
  47. ranges::copy_if(queue, back_inserter(result), EqualSchedulable(device));
  48. return result;
  49. }
  50. bool Scheduler::removeSyncPoint(Schedulable& device)
  51. {
  52. assert(Thread::isMainThread());
  53. return queue.remove(EqualSchedulable(device));
  54. }
  55. void Scheduler::removeSyncPoints(Schedulable& device)
  56. {
  57. assert(Thread::isMainThread());
  58. queue.remove_all(EqualSchedulable(device));
  59. }
  60. bool Scheduler::pendingSyncPoint(const Schedulable& device,
  61. EmuTime& result) const
  62. {
  63. assert(Thread::isMainThread());
  64. auto it = ranges::find_if(queue, EqualSchedulable(device));
  65. if (it != std::end(queue)) {
  66. result = it->getTime();
  67. return true;
  68. } else {
  69. return false;
  70. }
  71. }
  72. EmuTime::param Scheduler::getCurrentTime() const
  73. {
  74. assert(Thread::isMainThread());
  75. return scheduleTime;
  76. }
  77. void Scheduler::scheduleHelper(EmuTime::param limit, EmuTime next)
  78. {
  79. assert(!scheduleInProgress);
  80. scheduleInProgress = true;
  81. while (true) {
  82. assert(scheduleTime <= next);
  83. scheduleTime = next;
  84. const auto& sp = queue.front();
  85. auto* device = sp.getDevice();
  86. queue.remove_front();
  87. device->executeUntil(next);
  88. next = getNext();
  89. if (likely(next > limit)) break;
  90. }
  91. scheduleInProgress = false;
  92. cpu->setNextSyncPoint(next);
  93. }
  94. template <typename Archive>
  95. void SynchronizationPoint::serialize(Archive& ar, unsigned /*version*/)
  96. {
  97. // SynchronizationPoint is always serialized via Schedulable. A
  98. // Schedulable has a collection of SynchronizationPoints, all with the
  99. // same Schedulable. So there's no need to serialize 'device'.
  100. //Schedulable* device;
  101. ar.serialize("time", timeStamp);
  102. }
  103. INSTANTIATE_SERIALIZE_METHODS(SynchronizationPoint);
  104. template <typename Archive>
  105. void Scheduler::serialize(Archive& ar, unsigned /*version*/)
  106. {
  107. ar.serialize("currentTime", scheduleTime);
  108. // don't serialize 'queue', each Schedulable serializes its own
  109. // syncpoints
  110. }
  111. INSTANTIATE_SERIALIZE_METHODS(Scheduler);
  112. } // namespace openmsx