From a974659504b5d0797e62d2d115812be17a1ea5a0 Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Fri, 11 Sep 2015 21:48:26 +1000 Subject: Check return value of windows timer functions and handle errors Change return type of utils::get_microseconds to signed int and return -1 when failing to read timer --- libs/backends/portaudio/win_utils.cc | 39 ++++++++++++++++++++++++++++-------- libs/backends/portaudio/win_utils.h | 10 ++++++++- 2 files changed, 40 insertions(+), 9 deletions(-) (limited to 'libs/backends') diff --git a/libs/backends/portaudio/win_utils.cc b/libs/backends/portaudio/win_utils.cc index 3b985820b7..dc0f8d5270 100644 --- a/libs/backends/portaudio/win_utils.cc +++ b/libs/backends/portaudio/win_utils.cc @@ -27,15 +27,27 @@ namespace { +bool& +qpc_frequency_success () +{ + static bool success = false; + return success; +} + LARGE_INTEGER -get_frequency () +qpc_frequency () { LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); + if (QueryPerformanceFrequency(&freq) == 0) { + DEBUG_TIMING ("Failed to determine frequency of QPC\n"); + qpc_frequency_success() = false; + } else { + qpc_frequency_success() = true; + } + return freq; } - UINT& old_timer_resolution () { @@ -86,15 +98,26 @@ reset_timer_resolution () return true; } -uint64_t get_microseconds () +int64_t +get_microseconds () { - static LARGE_INTEGER frequency = get_frequency (); + static LARGE_INTEGER frequency = qpc_frequency (); LARGE_INTEGER current_val; - QueryPerformanceCounter (¤t_val); + if (qpc_frequency_success()) { - return (uint64_t)(((double)current_val.QuadPart) / - ((double)frequency.QuadPart) * 1000000.0); + // MS docs say this will always succeed for systems >= XP but it may + // not return a monotonic value with non-invariant TSC's etc + if (QueryPerformanceCounter(¤t_val) != 0) { + return (int64_t)(((double)current_val.QuadPart) / + ((double)frequency.QuadPart) * 1000000.0); + } else { + DEBUG_TIMING ("Could not get QPC timer\n"); + } + return -1; + } + // For XP systems that don't support a high-res performance counter + return g_get_monotonic_time (); } } // namespace utils diff --git a/libs/backends/portaudio/win_utils.h b/libs/backends/portaudio/win_utils.h index 1b85eb04fd..072ce1f0b0 100644 --- a/libs/backends/portaudio/win_utils.h +++ b/libs/backends/portaudio/win_utils.h @@ -27,7 +27,15 @@ bool set_min_timer_resolution (); bool reset_timer_resolution (); -uint64_t get_microseconds (); +/** The highest resolution timer source provided by the system. On Vista and + * above this is the value returned by QueryPerformanceCounter(QPC). On XP, + * this will QPC if supported or otherwise g_get_monotonic_time will be used. + * + * @return A timer value in microseconds or -1 in the event that the reading + * the timer source fails, but the MS docs say that this won't occur for + * systems >= XP + */ +int64_t get_microseconds (); } -- cgit v1.2.3