CoreTiming: Adopt integer overflow handling if clock rate gets changed

This commit is contained in:
B3n30 2017-11-14 10:26:58 +01:00
parent 1f288e06bc
commit 3f9739b60f
2 changed files with 13 additions and 10 deletions

View File

@ -4,6 +4,7 @@
#include <atomic> #include <atomic>
#include <cinttypes> #include <cinttypes>
#include <limits>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include "common/chunk_file.h" #include "common/chunk_file.h"
@ -14,6 +15,7 @@
#include "core/core_timing.h" #include "core/core_timing.h"
int g_clock_rate_arm11 = BASE_CLOCK_RATE_ARM11; int g_clock_rate_arm11 = BASE_CLOCK_RATE_ARM11;
u64 max_value_to_multiply = std::numeric_limits<s64>::max() / g_clock_rate_arm11;
// is this really necessary? // is this really necessary?
#define INITIAL_SLICE_LENGTH 20000 #define INITIAL_SLICE_LENGTH 20000
@ -79,6 +81,7 @@ void SetClockFrequencyMHz(int cpu_mhz) {
last_global_time_ticks = GetTicks(); last_global_time_ticks = GetTicks();
g_clock_rate_arm11 = cpu_mhz * 1000000; g_clock_rate_arm11 = cpu_mhz * 1000000;
max_value_to_multiply = std::numeric_limits<s64>::max() / g_clock_rate_arm11;
// TODO: Rescale times of scheduled events? // TODO: Rescale times of scheduled events?
FireMhzChange(); FireMhzChange();

View File

@ -24,12 +24,12 @@
// ScheduleEvent(periodInCycles - cycles_late, callback, "whatever") // ScheduleEvent(periodInCycles - cycles_late, callback, "whatever")
// The timing we get from the assembly is 268,111,855.956 Hz // The timing we get from the assembly is 268,111,855.956 Hz
// It is possible that this number isn't jus a integer because the compiler could have // It is possible that this number isn't just an integer because the compiler could have
// optimized the multiplication by a multiply-by-constant division. // optimized the multiplication by a multiply-by-constant division.
// Rounding to the nearest integer should be fine // Rounding to the nearest integer should be fine
constexpr s64 BASE_CLOCK_RATE_ARM11 = 268111856; constexpr s64 BASE_CLOCK_RATE_ARM11 = 268111856;
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / 268111856; extern u64 max_value_to_multiply;
extern int g_clock_rate_arm11; extern int g_clock_rate_arm11;
inline s64 msToCycles(int ms) { inline s64 msToCycles(int ms) {
@ -54,10 +54,10 @@ inline s64 usToCycles(int us) {
} }
inline s64 usToCycles(s64 us) { inline s64 usToCycles(s64 us) {
if ((us / 1000000) > MAX_VALUE_TO_MULTIPLY) { if ((us / 1000000) > max_value_to_multiply) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value"); LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max(); return std::numeric_limits<s64>::max();
} else if (us > MAX_VALUE_TO_MULTIPLY) { } else if (us > max_value_to_multiply) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding"); LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * (us / 1000000)); return (g_clock_rate_arm11 * (us / 1000000));
} }
@ -65,10 +65,10 @@ inline s64 usToCycles(s64 us) {
} }
inline s64 usToCycles(u64 us) { inline s64 usToCycles(u64 us) {
if ((us / 1000000) > MAX_VALUE_TO_MULTIPLY) { if ((us / 1000000) > max_value_to_multiply) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value"); LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max(); return std::numeric_limits<s64>::max();
} else if (us > MAX_VALUE_TO_MULTIPLY) { } else if (us > max_value_to_multiply) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding"); LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * static_cast<s64>(us / 1000000)); return (g_clock_rate_arm11 * static_cast<s64>(us / 1000000));
} }
@ -84,10 +84,10 @@ inline s64 nsToCycles(int ns) {
} }
inline s64 nsToCycles(s64 ns) { inline s64 nsToCycles(s64 ns) {
if ((ns / 1000000000) > MAX_VALUE_TO_MULTIPLY) { if ((ns / 1000000000) > max_value_to_multiply) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value"); LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max(); return std::numeric_limits<s64>::max();
} else if (ns > MAX_VALUE_TO_MULTIPLY) { } else if (ns > max_value_to_multiply) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding"); LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * (ns / 1000000000)); return (g_clock_rate_arm11 * (ns / 1000000000));
} }
@ -95,10 +95,10 @@ inline s64 nsToCycles(s64 ns) {
} }
inline s64 nsToCycles(u64 ns) { inline s64 nsToCycles(u64 ns) {
if ((ns / 1000000000) > MAX_VALUE_TO_MULTIPLY) { if ((ns / 1000000000) > max_value_to_multiply) {
LOG_ERROR(Core_Timing, "Integer overflow, use max value"); LOG_ERROR(Core_Timing, "Integer overflow, use max value");
return std::numeric_limits<s64>::max(); return std::numeric_limits<s64>::max();
} else if (ns > MAX_VALUE_TO_MULTIPLY) { } else if (ns > max_value_to_multiply) {
LOG_DEBUG(Core_Timing, "Time very big, do rounding"); LOG_DEBUG(Core_Timing, "Time very big, do rounding");
return (g_clock_rate_arm11 * static_cast<s64>(ns / 1000000000)); return (g_clock_rate_arm11 * static_cast<s64>(ns / 1000000000));
} }