|
|
@ -23,10 +23,6 @@ namespace Core::Timing { |
|
|
|
|
|
|
|
|
constexpr s64 MAX_SLICE_LENGTH = 10000; |
|
|
constexpr s64 MAX_SLICE_LENGTH = 10000; |
|
|
|
|
|
|
|
|
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { |
|
|
|
|
|
return std::make_shared<EventType>(std::move(callback), std::move(name)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct CoreTiming::Event { |
|
|
struct CoreTiming::Event { |
|
|
s64 time; |
|
|
s64 time; |
|
|
u64 fifo_order; |
|
|
u64 fifo_order; |
|
|
@ -36,11 +32,10 @@ struct CoreTiming::Event { |
|
|
|
|
|
|
|
|
// Sort by time, unless the times are the same, in which case sort by
|
|
|
// Sort by time, unless the times are the same, in which case sort by
|
|
|
// the order added to the queue
|
|
|
// the order added to the queue
|
|
|
friend bool operator>(const Event& left, const Event& right) { |
|
|
|
|
|
|
|
|
friend bool operator>(const Event& left, const Event& right) noexcept { |
|
|
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order); |
|
|
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
friend bool operator<(const Event& left, const Event& right) { |
|
|
|
|
|
|
|
|
friend bool operator<(const Event& left, const Event& right) noexcept { |
|
|
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order); |
|
|
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order); |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
@ -60,8 +55,6 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { |
|
|
Common::SetCurrentThreadName("HostTiming"); |
|
|
Common::SetCurrentThreadName("HostTiming"); |
|
|
Common::SetCurrentThreadPriority(Common::ThreadPriority::High); |
|
|
Common::SetCurrentThreadPriority(Common::ThreadPriority::High); |
|
|
on_thread_init(); |
|
|
on_thread_init(); |
|
|
has_started = true; |
|
|
|
|
|
|
|
|
|
|
|
// base frequency in MHz: 1ns (10^-9) = 1GHz (10^9)
|
|
|
// base frequency in MHz: 1ns (10^-9) = 1GHz (10^9)
|
|
|
while (!stop_token.stop_requested()) { |
|
|
while (!stop_token.stop_requested()) { |
|
|
while (!paused && !stop_token.stop_requested()) { |
|
|
while (!paused && !stop_token.stop_requested()) { |
|
|
@ -77,8 +70,8 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { |
|
|
// continue.
|
|
|
// continue.
|
|
|
wait_set = true; |
|
|
wait_set = true; |
|
|
event.Wait(); |
|
|
event.Wait(); |
|
|
|
|
|
wait_set = false; |
|
|
} |
|
|
} |
|
|
wait_set = false; |
|
|
|
|
|
} |
|
|
} |
|
|
paused_set = true; |
|
|
paused_set = true; |
|
|
pause_event.Wait(); |
|
|
pause_event.Wait(); |
|
|
@ -144,39 +137,28 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
|
|
event.Set(); |
|
|
event.Set(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, |
|
|
|
|
|
std::chrono::nanoseconds resched_time, |
|
|
|
|
|
const std::shared_ptr<EventType>& event_type, |
|
|
|
|
|
bool absolute_time) { |
|
|
|
|
|
|
|
|
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, std::chrono::nanoseconds resched_time, const std::shared_ptr<EventType>& event_type, bool absolute_time) { |
|
|
{ |
|
|
{ |
|
|
std::scoped_lock scope{basic_lock}; |
|
|
std::scoped_lock scope{basic_lock}; |
|
|
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; |
|
|
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; |
|
|
|
|
|
|
|
|
auto h{event_queue.emplace( |
|
|
|
|
|
Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()})}; |
|
|
|
|
|
|
|
|
auto h = event_queue.emplace(Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()}); |
|
|
(*h).handle = h; |
|
|
(*h).handle = h; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
event.Set(); |
|
|
event.Set(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, |
|
|
|
|
|
UnscheduleEventType type) { |
|
|
|
|
|
|
|
|
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, UnscheduleEventType type) { |
|
|
{ |
|
|
{ |
|
|
std::scoped_lock lk{basic_lock}; |
|
|
std::scoped_lock lk{basic_lock}; |
|
|
|
|
|
|
|
|
std::vector<heap_t::handle_type> to_remove; |
|
|
std::vector<heap_t::handle_type> to_remove; |
|
|
for (auto itr = event_queue.begin(); itr != event_queue.end(); itr++) { |
|
|
|
|
|
const Event& e = *itr; |
|
|
|
|
|
|
|
|
for (auto it = event_queue.begin(); it != event_queue.end(); it++) { |
|
|
|
|
|
auto const& e = *it; |
|
|
if (e.type.lock().get() == event_type.get()) { |
|
|
if (e.type.lock().get() == event_type.get()) { |
|
|
to_remove.push_back(itr->handle); |
|
|
|
|
|
|
|
|
to_remove.push_back(it->handle); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (auto& h : to_remove) { |
|
|
|
|
|
|
|
|
for (auto& h : to_remove) |
|
|
event_queue.erase(h); |
|
|
event_queue.erase(h); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
event_type->sequence_number++; |
|
|
event_type->sequence_number++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -187,16 +169,15 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static u64 GetNextTickCount(u64 next_ticks) { |
|
|
static u64 GetNextTickCount(u64 next_ticks) { |
|
|
if (Settings::values.use_custom_cpu_ticks.GetValue()) { |
|
|
|
|
|
|
|
|
if (Settings::values.use_custom_cpu_ticks.GetValue()) |
|
|
return Settings::values.cpu_ticks.GetValue(); |
|
|
return Settings::values.cpu_ticks.GetValue(); |
|
|
} |
|
|
|
|
|
return next_ticks; |
|
|
return next_ticks; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void CoreTiming::AddTicks(u64 ticks_to_add) { |
|
|
void CoreTiming::AddTicks(u64 ticks_to_add) { |
|
|
const u64 ticks = GetNextTickCount(ticks_to_add); |
|
|
const u64 ticks = GetNextTickCount(ticks_to_add); |
|
|
cpu_ticks += ticks; |
|
|
cpu_ticks += ticks; |
|
|
downcount -= static_cast<s64>(ticks); |
|
|
|
|
|
|
|
|
downcount -= s64(ticks); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void CoreTiming::Idle() { |
|
|
void CoreTiming::Idle() { |
|
|
@ -270,19 +251,14 @@ std::optional<s64> CoreTiming::Advance() { |
|
|
next_time = pause_end_time + next_schedule_time; |
|
|
next_time = pause_end_time + next_schedule_time; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type, |
|
|
|
|
|
next_schedule_time, evt.handle}); |
|
|
|
|
|
|
|
|
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type, next_schedule_time, evt.handle}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
global_timer = GetGlobalTimeNs().count(); |
|
|
global_timer = GetGlobalTimeNs().count(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!event_queue.empty()) { |
|
|
|
|
|
return event_queue.top().time; |
|
|
|
|
|
} else { |
|
|
|
|
|
return std::nullopt; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return event_queue.empty() ? std::optional<s64>{} : event_queue.top().time; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void CoreTiming::Reset() { |
|
|
void CoreTiming::Reset() { |
|
|
@ -293,7 +269,6 @@ void CoreTiming::Reset() { |
|
|
timer_thread.request_stop(); |
|
|
timer_thread.request_stop(); |
|
|
timer_thread.join(); |
|
|
timer_thread.join(); |
|
|
} |
|
|
} |
|
|
has_started = false; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// @brief Returns current time in nanoseconds.
|
|
|
/// @brief Returns current time in nanoseconds.
|
|
|
@ -310,10 +285,4 @@ std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept { |
|
|
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)}; |
|
|
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
void CoreTiming::SetTimerResolutionNs(std::chrono::nanoseconds ns) { |
|
|
|
|
|
timer_resolution_ns = ns.count(); |
|
|
|
|
|
} |
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Core::Timing
|
|
|
} // namespace Core::Timing
|