X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Fwindows_timer_utils.cc;h=0fab935b082e5f0c4709e16040fd360e16b085d7;hb=cf52d6e4b40111eb04b244ec054055a4ec15dbe0;hp=d95a69e0c71b47373a7a55d5225bfa62d0b9381d;hpb=a88b2da6a90b1d6f3004333a89761d312b02cf37;p=ardour.git diff --git a/libs/pbd/windows_timer_utils.cc b/libs/pbd/windows_timer_utils.cc index d95a69e0c7..0fab935b08 100644 --- a/libs/pbd/windows_timer_utils.cc +++ b/libs/pbd/windows_timer_utils.cc @@ -23,11 +23,15 @@ #include "pbd/compose.h" #include "pbd/debug.h" +#include "pbd/error.h" + +#include "pbd/i18n.h" #define DEBUG_TIMING(msg) DEBUG_TRACE (PBD::DEBUG::Timing, msg); namespace { +static UINT& timer_resolution () { @@ -35,7 +39,7 @@ timer_resolution () return timer_res_ms; } -} +} // namespace namespace PBD { @@ -100,6 +104,7 @@ reset_resolution () DEBUG_TIMING("Could not reset the Timer resolution.\n"); return false; } + DEBUG_TIMING("Reset the Timer resolution.\n"); timer_resolution() = 0; return true; } @@ -108,32 +113,23 @@ reset_resolution () namespace { -bool& -qpc_frequency_success () -{ - static bool success = false; - return success; -} +static double timer_rate_us = 0.0; -LARGE_INTEGER -qpc_frequency () +static +bool +test_qpc_validity () { - LARGE_INTEGER freq; - if (QueryPerformanceFrequency(&freq) == 0) { - DEBUG_TIMING ("Failed to determine frequency of QPC\n"); - qpc_frequency_success() = false; - } else { - qpc_frequency_success() = true; + int64_t last_timer_val = PBD::QPC::get_microseconds (); + if (last_timer_val < 0) return false; + + for (int i = 0; i < 100000; ++i) { + int64_t timer_val = PBD::QPC::get_microseconds (); + if (timer_val < 0) return false; + // try and test for non-syncronized TSC(AMD K8/etc) + if (timer_val < last_timer_val) return false; + last_timer_val = timer_val; } - - return freq; -} - -LARGE_INTEGER -qpc_frequency_cached () -{ - static LARGE_INTEGER frequency = qpc_frequency (); - return frequency; + return true; } } // anon namespace @@ -141,11 +137,27 @@ qpc_frequency_cached () namespace QPC { bool -get_timer_valid () +check_timer_valid () +{ + if (!timer_rate_us) { + return false; + } + return test_qpc_validity (); +} + +bool +initialize () { - // setup caching the timer frequency - qpc_frequency_cached (); - return qpc_frequency_success (); + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq) || freq.QuadPart < 1) { + info << X_("Failed to determine frequency of QPC\n") << endmsg; + timer_rate_us = 0; + } else { + timer_rate_us = 1000000.0 / freq.QuadPart; + } + info << string_compose(X_("QPC timer microseconds per tick: %1\n"), + timer_rate_us) << endmsg; + return !timer_rate_us; } int64_t @@ -153,12 +165,11 @@ get_microseconds () { LARGE_INTEGER current_val; - if (qpc_frequency_success()) { + if (timer_rate_us) { // 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)qpc_frequency_cached().QuadPart) * 1000000.0); + return (int64_t)(current_val.QuadPart * timer_rate_us); } } DEBUG_TIMING ("Could not get QPC timer\n"); @@ -170,7 +181,7 @@ get_microseconds () int64_t get_microseconds () { - if (qpc_frequency_success()) { + if (timer_rate_us) { return QPC::get_microseconds (); } // For XP systems that don't support a high-res performance counter