diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/util/lnx/os_linux.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/util/lnx/os_linux.cpp index 879ade0dd8..c5f5abc628 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/util/lnx/os_linux.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/util/lnx/os_linux.cpp @@ -47,12 +47,14 @@ #include #include #include -#include -#include #include #include +#include #include #include +#include +#include +#include namespace os { @@ -334,15 +336,36 @@ uint64_t ReadAccurateClock() { } uint64_t AccurateClockFrequency() { + static clockid_t clock = CLOCK_MONOTONIC; + static std::atomic first(true); + // Check kernel version - not a concurrency concern. + // use non-RAW for getres due to bug in older 2.6.x kernels + if (first.load(std::memory_order_acquire)) { + utsname kernelInfo; + if (uname(&kernelInfo) == 0) { + try { + std::string ver = kernelInfo.release; + size_t idx; + int major = std::stoi(ver, &idx); + int minor = std::stoi(ver.substr(idx + 1)); + if ((major >= 4) && (minor >= 4)) { + clock = CLOCK_MONOTONIC_RAW; + } + } catch (...) { + // Kernel version string doesn't conform to the standard pattern. + // Keep using the "safe" (non-RAW) clock. + } + } + first.store(false, std::memory_order_release); + } timespec time; - //use non-RAW for getres due to bug in older 2.6.x kernels - int err = clock_getres(CLOCK_MONOTONIC, &time); - assert(err == 0 && "clock_getres(CLOCK_MONOTONIC,...) failed"); + int err = clock_getres(clock, &time); + assert(err == 0 && "clock_getres(CLOCK_MONOTONIC(_RAW),...) failed"); assert(time.tv_sec == 0 && - "clock_getres(CLOCK_MONOTONIC,...) returned very low frequency " + "clock_getres(CLOCK_MONOTONIC(_RAW),...) returned very low frequency " "(<1Hz)."); assert(time.tv_nsec < 0xFFFFFFFF && - "clock_getres(CLOCK_MONOTONIC,...) returned very low frequency " + "clock_getres(CLOCK_MONOTONIC(_RAW),...) returned very low frequency " "(<1Hz)."); if (invPeriod == 0.0) invPeriod = 1.0 / double(time.tv_nsec); return 1000000000ull / uint64_t(time.tv_nsec);