diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2019-09-09 21:37:29 -0400 |
---|---|---|
committer | FernandoS27 <fsahmkow27@gmail.com> | 2019-10-09 12:30:31 -0400 |
commit | 555866f8dcb98897688d5d7b0e6c6cca55ac069f (patch) | |
tree | 287ffee685bd8fbd6a8a16aa02a198a6cab3ede3 /src/core/core_timing.cpp | |
parent | e664c24355bb4a53b114719a9aba960c82658403 (diff) |
Core Timing: Rework Core Timing to run all cores evenly.
Diffstat (limited to 'src/core/core_timing.cpp')
-rw-r--r-- | src/core/core_timing.cpp | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index a58f7b131d..6da2dcfb46 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -15,7 +15,7 @@ namespace Core::Timing { -constexpr int MAX_SLICE_LENGTH = 20000; +constexpr int MAX_SLICE_LENGTH = 10000; struct CoreTiming::Event { s64 time; @@ -38,10 +38,14 @@ CoreTiming::CoreTiming() = default; CoreTiming::~CoreTiming() = default; void CoreTiming::Initialize() { - downcount = MAX_SLICE_LENGTH; + for (std::size_t core = 0; core < num_cpu_cores; core++) { + downcounts[core] = MAX_SLICE_LENGTH; + time_slice[core] = MAX_SLICE_LENGTH; + } slice_length = MAX_SLICE_LENGTH; global_timer = 0; idled_cycles = 0; + current_context = 0; // The time between CoreTiming being initialized and the first call to Advance() is considered // the slice boundary between slice -1 and slice 0. Dispatcher loops must call Advance() before @@ -110,7 +114,7 @@ void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) { u64 CoreTiming::GetTicks() const { u64 ticks = static_cast<u64>(global_timer); if (!is_global_timer_sane) { - ticks += slice_length - downcount; + ticks += time_slice[current_context] - downcounts[current_context]; } return ticks; } @@ -120,7 +124,7 @@ u64 CoreTiming::GetIdleTicks() const { } void CoreTiming::AddTicks(u64 ticks) { - downcount -= static_cast<int>(ticks); + downcounts[current_context] -= static_cast<s64>(ticks); } void CoreTiming::ClearPendingEvents() { @@ -141,22 +145,36 @@ void CoreTiming::RemoveEvent(const EventType* event_type) { void CoreTiming::ForceExceptionCheck(s64 cycles) { cycles = std::max<s64>(0, cycles); - if (downcount <= cycles) { + if (downcounts[current_context] <= cycles) { return; } // downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int // here. Account for cycles already executed by adjusting the g.slice_length - slice_length -= downcount - static_cast<int>(cycles); - downcount = static_cast<int>(cycles); + slice_length -= downcounts[current_context] - static_cast<int>(cycles); + downcounts[current_context] = static_cast<int>(cycles); +} + +std::optional<u64> CoreTiming::NextAvailableCore(const s64 needed_ticks) const { + const u64 original_context = current_context; + u64 next_context = (original_context + 1) % num_cpu_cores; + while (next_context != original_context) { + if (time_slice[next_context] >= needed_ticks) { + return {next_context}; + } else if (time_slice[next_context] >= 0) { + return {}; + } + next_context = (next_context + 1) % num_cpu_cores; + } + return {}; } void CoreTiming::Advance() { std::unique_lock<std::mutex> guard(inner_mutex); - const int cycles_executed = slice_length - downcount; + const int cycles_executed = time_slice[current_context] - downcounts[current_context]; + time_slice[current_context] = std::max<s64>(0, downcounts[current_context]); global_timer += cycles_executed; - slice_length = MAX_SLICE_LENGTH; is_global_timer_sane = true; @@ -173,24 +191,40 @@ void CoreTiming::Advance() { // Still events left (scheduled in the future) if (!event_queue.empty()) { - slice_length = static_cast<int>( - std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH)); + s64 needed_ticks = std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH); + const auto next_core = NextAvailableCore(needed_ticks); + if (next_core) { + downcounts[*next_core] = needed_ticks; + } } - downcount = slice_length; + downcounts[current_context] = time_slice[current_context]; +} + +void CoreTiming::ResetRun() { + for (std::size_t core = 0; core < num_cpu_cores; core++) { + downcounts[core] = MAX_SLICE_LENGTH; + time_slice[core] = MAX_SLICE_LENGTH; + } + current_context = 0; + // Still events left (scheduled in the future) + if (!event_queue.empty()) { + s64 needed_ticks = std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH); + downcounts[current_context] = needed_ticks; + } } void CoreTiming::Idle() { - idled_cycles += downcount; - downcount = 0; + idled_cycles += downcounts[current_context]; + downcounts[current_context] = 0; } std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { return std::chrono::microseconds{GetTicks() * 1000000 / BASE_CLOCK_RATE}; } -int CoreTiming::GetDowncount() const { - return downcount; +s64 CoreTiming::GetDowncount() const { + return downcounts[current_context]; } } // namespace Core::Timing |