From f56e12c94dd58b624a9c7b047e529ba6190be3d4 Mon Sep 17 00:00:00 2001 From: schrodingerzhu Date: Fri, 6 Dec 2024 01:27:31 -0500 Subject: [PATCH 1/3] [libc][time][windows] implement clock_getres --- libc/config/windows/entrypoints.txt | 1 + .../src/__support/time/windows/CMakeLists.txt | 10 ++ .../__support/time/windows/clock_gettime.cpp | 20 +--- libc/src/__support/time/windows/qpc.h | 35 ++++++ libc/src/time/CMakeLists.txt | 7 ++ libc/src/time/clock_getres.h | 21 ++++ libc/src/time/windows/CMakeLists.txt | 13 +++ libc/src/time/windows/clock_getres.cpp | 110 ++++++++++++++++++ libc/test/src/time/CMakeLists.txt | 12 +- libc/test/src/time/clock_getres_test.cpp | 55 +++++++++ 10 files changed, 265 insertions(+), 19 deletions(-) create mode 100644 libc/src/__support/time/windows/qpc.h create mode 100644 libc/src/time/clock_getres.h create mode 100644 libc/src/time/windows/CMakeLists.txt create mode 100644 libc/src/time/windows/clock_getres.cpp create mode 100644 libc/test/src/time/clock_getres_test.cpp diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index d0796b85aec2a..83a64e935cd02 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -98,6 +98,7 @@ set(TARGET_LIBC_ENTRYPOINTS # time.h entrypoints libc.src.time.time + libc.src.time.clock_getres ) set(TARGET_LIBM_ENTRYPOINTS diff --git a/libc/src/__support/time/windows/CMakeLists.txt b/libc/src/__support/time/windows/CMakeLists.txt index 0f557ed880080..31abc2d552661 100644 --- a/libc/src/__support/time/windows/CMakeLists.txt +++ b/libc/src/__support/time/windows/CMakeLists.txt @@ -1,3 +1,12 @@ +add_header_library( + qpc + HDRS + qpc.h + DEPENDS + libc.src.__support.CPP.atomic + libc.src.__support.common +) + add_object_library( clock_gettime HDRS @@ -5,6 +14,7 @@ add_object_library( SRCS clock_gettime.cpp DEPENDS + .qpc libc.hdr.types.struct_timespec libc.hdr.types.clockid_t libc.hdr.errno_macros diff --git a/libc/src/__support/time/windows/clock_gettime.cpp b/libc/src/__support/time/windows/clock_gettime.cpp index c2536acf37d79..6c60ffd2c4af0 100644 --- a/libc/src/__support/time/windows/clock_gettime.cpp +++ b/libc/src/__support/time/windows/clock_gettime.cpp @@ -14,6 +14,7 @@ #include "src/__support/macros/optimization.h" #include "src/__support/time/clock_gettime.h" #include "src/__support/time/units.h" +#include "src/__support/time/windows/qpc.h" #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -21,23 +22,6 @@ namespace LIBC_NAMESPACE_DECL { namespace internal { -static long long get_ticks_per_second() { - static cpp::Atomic frequency = 0; - // Relaxed ordering is enough. It is okay to record the frequency multiple - // times. The store operation itself is atomic and the value must propagate - // as required by cache coherence. - auto freq = frequency.load(cpp::MemoryOrder::RELAXED); - if (!freq) { - [[clang::uninitialized]] LARGE_INTEGER buffer; - // On systems that run Windows XP or later, the function will always - // succeed and will thus never return zero. - ::QueryPerformanceFrequency(&buffer); - frequency.store(buffer.QuadPart, cpp::MemoryOrder::RELAXED); - return buffer.QuadPart; - } - return freq; -} - ErrorOr clock_gettime(clockid_t clockid, timespec *ts) { using namespace time_units; constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL; @@ -58,7 +42,7 @@ ErrorOr clock_gettime(clockid_t clockid, timespec *ts) { // On systems that run Windows XP or later, the function will always // succeed and will thus never return zero. ::QueryPerformanceCounter(&buffer); - long long freq = get_ticks_per_second(); + long long freq = qpc::get_ticks_per_second(); long long ticks = buffer.QuadPart; long long tv_sec = ticks / freq; long long tv_nsec = (ticks % freq) * 1_s_ns / freq; diff --git a/libc/src/__support/time/windows/qpc.h b/libc/src/__support/time/windows/qpc.h new file mode 100644 index 0000000000000..ff803a0858a6e --- /dev/null +++ b/libc/src/__support/time/windows/qpc.h @@ -0,0 +1,35 @@ +//===--- Cached QPC Frequency ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/atomic.h" +#include "src/__support/common.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include + +namespace LIBC_NAMESPACE_DECL { +namespace qpc { +LIBC_INLINE long long get_ticks_per_second() { + static cpp::Atomic frequency = 0; + // Relaxed ordering is enough. It is okay to record the frequency multiple + // times. The store operation itself is atomic and the value must propagate + // as required by cache coherence. + auto freq = frequency.load(cpp::MemoryOrder::RELAXED); + if (!freq) { + [[clang::uninitialized]] LARGE_INTEGER buffer; + // On systems that run Windows XP or later, the function will always + // succeed and will thus never return zero. + ::QueryPerformanceFrequency(&buffer); + frequency.store(buffer.QuadPart, cpp::MemoryOrder::RELAXED); + return buffer.QuadPart; + } + return freq; +} +} // namespace qpc +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt index 3e8e6882ffc5d..ae835dcc74274 100644 --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -151,3 +151,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.gettimeofday ) + +add_entrypoint_object( + clock_getres + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.clock_getres +) diff --git a/libc/src/time/clock_getres.h b/libc/src/time/clock_getres.h new file mode 100644 index 0000000000000..c1c581c535994 --- /dev/null +++ b/libc/src/time/clock_getres.h @@ -0,0 +1,21 @@ +//===-- Implementation header of clock_getres -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_SRC_TIME_CLOCK_GETRES_H +#define LLVM_LIBC_SRC_TIME_CLOCK_GETRES_H + +#include "hdr/types/clockid_t.h" +#include "hdr/types/struct_timespec.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int clock_getres(clockid_t clockid, timespec *tp); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_TIME_CLOCK_GETRES_H diff --git a/libc/src/time/windows/CMakeLists.txt b/libc/src/time/windows/CMakeLists.txt new file mode 100644 index 0000000000000..69fa95e82f3c3 --- /dev/null +++ b/libc/src/time/windows/CMakeLists.txt @@ -0,0 +1,13 @@ +add_entrypoint_object( + clock_getres + SRCS + clock_getres.cpp + DEPENDS + libc.src.__support.time.windows.qpc + libc.src.__support.time.units + libc.src.__support.common + libc.src.__support.macros.optimization + libc.hdr.time_macros + libc.hdr.types.time_t + libc.hdr.types.struct_timespec +) diff --git a/libc/src/time/windows/clock_getres.cpp b/libc/src/time/windows/clock_getres.cpp new file mode 100644 index 0000000000000..0a4994061e72c --- /dev/null +++ b/libc/src/time/windows/clock_getres.cpp @@ -0,0 +1,110 @@ +//===-- Windows implementation of clock_getres ------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "hdr/errno_macros.h" +#include "hdr/time_macros.h" +#include "hdr/types/clockid_t.h" +#include "hdr/types/struct_timespec.h" + +#include "src/__support/CPP/limits.h" +#include "src/__support/common.h" +#include "src/__support/macros/optimization.h" +#include "src/__support/time/units.h" +#include "src/__support/time/windows/qpc.h" +#include "src/errno/libc_errno.h" +#include "src/time/clock_getres.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include + +// add in dependencies for GetSystemTimeAdjustmentPrecise +#pragma comment(lib, "mincore.lib") + +namespace LIBC_NAMESPACE_DECL { +LLVM_LIBC_FUNCTION(int, clock_getres, (clockid_t id, struct timespec *res)) { + using namespace time_units; + // POSIX allows nullptr to be passed as res, in which case the function should + // do nothing. + if (res == nullptr) + return 0; + constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL; + constexpr unsigned long long SEC_LIMIT = + cpp::numeric_limitstv_sec)>::max(); + // For CLOCK_MONOTONIC, we are using QPC + // https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps + // Hence, the resolution is given by the QPC frequency. + // For CLOCK_REALTIME, the precision is given by + // GetSystemTimeAdjustmentPrecise + // (https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeadjustmentprecise) + // For CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID, the precision is + // given by GetSystemTimeAdjustment + // (https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeadjustment) + switch (id) { + default: + libc_errno = EINVAL; + return -1; + + case CLOCK_MONOTONIC: { + long long freq = qpc::get_ticks_per_second(); + [[clang::assume(freq != 0)]]; + // division of 1 second by frequency, rounded up. + long long tv_sec = static_cast(freq == 1); + long long tv_nsec = + LIBC_LIKELY(freq != 1) ? 1ll + ((1_s_ns - 1ll) / freq) : 0ll; + // not possible to overflow tv_sec, tv_nsec + res->tv_sec = static_casttv_sec)>(tv_sec); + res->tv_nsec = static_casttv_nsec)>(tv_nsec); + break; + } + + case CLOCK_REALTIME: { + [[clang::uninitialized]] DWORD64 time_adjustment; + [[clang::uninitialized]] DWORD64 time_increment; + [[clang::uninitialized]] BOOL time_adjustment_disabled; + if (!::GetSystemTimeAdjustmentPrecise(&time_adjustment, &time_increment, + &time_adjustment_disabled)) { + libc_errno = EINVAL; + return -1; + } + DWORD64 tv_sec = time_adjustment / HNS_PER_SEC; + DWORD64 tv_nsec = (time_adjustment % HNS_PER_SEC) * 100ULL; + if (LIBC_UNLIKELY(tv_sec > SEC_LIMIT)) { + libc_errno = EOVERFLOW; + return -1; + } + res->tv_sec = static_casttv_sec)>(tv_sec); + res->tv_nsec = static_casttv_nsec)>(tv_nsec); + break; + } + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: { + [[clang::uninitialized]] DWORD time_adjustment; + [[clang::uninitialized]] DWORD time_increment; + [[clang::uninitialized]] BOOL time_adjustment_disabled; + if (!::GetSystemTimeAdjustment(&time_adjustment, &time_increment, + &time_adjustment_disabled)) { + libc_errno = EINVAL; + return -1; + } + DWORD hns_per_sec = static_cast(HNS_PER_SEC); + DWORD sec_limit = static_cast(SEC_LIMIT); + DWORD tv_sec = time_adjustment / hns_per_sec; + DWORD tv_nsec = (time_adjustment % hns_per_sec) * 100UL; + if (LIBC_UNLIKELY(tv_sec > sec_limit)) { + libc_errno = EOVERFLOW; + return -1; + } + res->tv_sec = static_casttv_sec)>(tv_sec); + res->tv_nsec = static_casttv_nsec)>(tv_nsec); + break; + } + } + return 0; +} +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt index d2a98677a5543..da3903f3e0e49 100644 --- a/libc/test/src/time/CMakeLists.txt +++ b/libc/test/src/time/CMakeLists.txt @@ -71,11 +71,21 @@ add_libc_test( SUITE libc_time_unittests SRCS - clock_gettime_test.cpp + clock_gettime_test.cpp DEPENDS libc.src.time.clock_gettime ) +add_libc_test( + clock_getres_test + SUITE + libc_time_unittests + SRCS + clock_getres_test.cpp + DEPENDS + libc.src.time.clock_getres +) + add_libc_unittest( difftime_test SUITE diff --git a/libc/test/src/time/clock_getres_test.cpp b/libc/test/src/time/clock_getres_test.cpp new file mode 100644 index 0000000000000..d8b3f01b37a38 --- /dev/null +++ b/libc/test/src/time/clock_getres_test.cpp @@ -0,0 +1,55 @@ +//===-- Unittests for clock_getres- ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "hdr/time_macros.h" +#include "src/time/clock_getres.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + +TEST(LlvmLibcClockGetRes, Invalid) { + timespec tp; + EXPECT_THAT(LIBC_NAMESPACE::clock_getres(-1, &tp), Fails(EINVAL)); +} + +TEST(LlvmLibcClockGetRes, NullSpec) { + EXPECT_THAT(LIBC_NAMESPACE::clock_getres(CLOCK_REALTIME, nullptr), + Succeeds()); +} + +TEST(LlvmLibcClockGetRes, Realtime) { + timespec tp; + EXPECT_THAT(LIBC_NAMESPACE::clock_getres(CLOCK_REALTIME, &tp), Succeeds()); + EXPECT_GE(tp.tv_sec, static_cast(0)); + EXPECT_GE(tp.tv_nsec, static_cast(0)); +} + +TEST(LlvmLibcClockGetRes, Monotonic) { + timespec tp; + ASSERT_THAT(LIBC_NAMESPACE::clock_getres(CLOCK_MONOTONIC, &tp), Succeeds()); + EXPECT_GE(tp.tv_sec, static_cast(0)); + EXPECT_GE(tp.tv_nsec, static_cast(0)); +} + +TEST(LlvmLibcClockGetRes, ProcessCpuTime) { + timespec tp; + ASSERT_THAT(LIBC_NAMESPACE::clock_getres(CLOCK_PROCESS_CPUTIME_ID, &tp), + Succeeds()); + EXPECT_GE(tp.tv_sec, static_cast(0)); + EXPECT_GE(tp.tv_nsec, static_cast(0)); +} + +TEST(LlvmLibcClockGetRes, ThreadCpuTime) { + timespec tp; + ASSERT_THAT(LIBC_NAMESPACE::clock_getres(CLOCK_THREAD_CPUTIME_ID, &tp), + Succeeds()); + EXPECT_GE(tp.tv_sec, static_cast(0)); + EXPECT_GE(tp.tv_nsec, static_cast(0)); +} From 6d2fe1e665b4b70d8fd8624e4edb5ccae9acc781 Mon Sep 17 00:00:00 2001 From: Schrodinger ZHU Yifan Date: Fri, 6 Dec 2024 07:06:39 -0800 Subject: [PATCH 2/3] fix increment --- libc/src/time/windows/clock_getres.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libc/src/time/windows/clock_getres.cpp b/libc/src/time/windows/clock_getres.cpp index 0a4994061e72c..42b313e4f1adf 100644 --- a/libc/src/time/windows/clock_getres.cpp +++ b/libc/src/time/windows/clock_getres.cpp @@ -72,8 +72,8 @@ LLVM_LIBC_FUNCTION(int, clock_getres, (clockid_t id, struct timespec *res)) { libc_errno = EINVAL; return -1; } - DWORD64 tv_sec = time_adjustment / HNS_PER_SEC; - DWORD64 tv_nsec = (time_adjustment % HNS_PER_SEC) * 100ULL; + DWORD64 tv_sec = time_increment / HNS_PER_SEC; + DWORD64 tv_nsec = (time_increment % HNS_PER_SEC) * 100ULL; if (LIBC_UNLIKELY(tv_sec > SEC_LIMIT)) { libc_errno = EOVERFLOW; return -1; @@ -94,8 +94,8 @@ LLVM_LIBC_FUNCTION(int, clock_getres, (clockid_t id, struct timespec *res)) { } DWORD hns_per_sec = static_cast(HNS_PER_SEC); DWORD sec_limit = static_cast(SEC_LIMIT); - DWORD tv_sec = time_adjustment / hns_per_sec; - DWORD tv_nsec = (time_adjustment % hns_per_sec) * 100UL; + DWORD tv_sec = time_increment / hns_per_sec; + DWORD tv_nsec = (time_increment % hns_per_sec) * 100UL; if (LIBC_UNLIKELY(tv_sec > sec_limit)) { libc_errno = EOVERFLOW; return -1; From 131553c7b121e8e37f887eeed6f6e4382a0a52ab Mon Sep 17 00:00:00 2001 From: Schrodinger ZHU Yifan Date: Mon, 9 Dec 2024 16:42:50 -0800 Subject: [PATCH 3/3] fix --- libc/src/__support/time/windows/CMakeLists.txt | 6 +++--- libc/src/__support/time/windows/clock_gettime.cpp | 6 +++--- .../time/windows/{qpc.h => performance_counter.h} | 6 +++--- libc/src/time/windows/CMakeLists.txt | 2 +- libc/src/time/windows/clock_getres.cpp | 10 +++++----- 5 files changed, 15 insertions(+), 15 deletions(-) rename libc/src/__support/time/windows/{qpc.h => performance_counter.h} (88%) diff --git a/libc/src/__support/time/windows/CMakeLists.txt b/libc/src/__support/time/windows/CMakeLists.txt index 31abc2d552661..dd0ac2f2f79ae 100644 --- a/libc/src/__support/time/windows/CMakeLists.txt +++ b/libc/src/__support/time/windows/CMakeLists.txt @@ -1,7 +1,7 @@ add_header_library( - qpc + performance_counter HDRS - qpc.h + performance_counter.h DEPENDS libc.src.__support.CPP.atomic libc.src.__support.common @@ -14,7 +14,7 @@ add_object_library( SRCS clock_gettime.cpp DEPENDS - .qpc + .performance_counter libc.hdr.types.struct_timespec libc.hdr.types.clockid_t libc.hdr.errno_macros diff --git a/libc/src/__support/time/windows/clock_gettime.cpp b/libc/src/__support/time/windows/clock_gettime.cpp index 6c60ffd2c4af0..813eae0df9705 100644 --- a/libc/src/__support/time/windows/clock_gettime.cpp +++ b/libc/src/__support/time/windows/clock_gettime.cpp @@ -14,7 +14,7 @@ #include "src/__support/macros/optimization.h" #include "src/__support/time/clock_gettime.h" #include "src/__support/time/units.h" -#include "src/__support/time/windows/qpc.h" +#include "src/__support/time/windows/performance_counter.h" #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -37,12 +37,12 @@ ErrorOr clock_gettime(clockid_t clockid, timespec *ts) { // see // https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps // Is the performance counter monotonic (non-decreasing)? - // Yes. QPC does not go backward. + // Yes. performance_counter does not go backward. [[clang::uninitialized]] LARGE_INTEGER buffer; // On systems that run Windows XP or later, the function will always // succeed and will thus never return zero. ::QueryPerformanceCounter(&buffer); - long long freq = qpc::get_ticks_per_second(); + long long freq = performance_counter::get_ticks_per_second(); long long ticks = buffer.QuadPart; long long tv_sec = ticks / freq; long long tv_nsec = (ticks % freq) * 1_s_ns / freq; diff --git a/libc/src/__support/time/windows/qpc.h b/libc/src/__support/time/windows/performance_counter.h similarity index 88% rename from libc/src/__support/time/windows/qpc.h rename to libc/src/__support/time/windows/performance_counter.h index ff803a0858a6e..3df81b3efff40 100644 --- a/libc/src/__support/time/windows/qpc.h +++ b/libc/src/__support/time/windows/performance_counter.h @@ -1,4 +1,4 @@ -//===--- Cached QPC Frequency ----------------------------------*- C++ -*-===// +//===--- Cached Performance Counter Frequency ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,7 +14,7 @@ #include namespace LIBC_NAMESPACE_DECL { -namespace qpc { +namespace performance_counter { LIBC_INLINE long long get_ticks_per_second() { static cpp::Atomic frequency = 0; // Relaxed ordering is enough. It is okay to record the frequency multiple @@ -31,5 +31,5 @@ LIBC_INLINE long long get_ticks_per_second() { } return freq; } -} // namespace qpc +} // namespace performance_counter } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/windows/CMakeLists.txt b/libc/src/time/windows/CMakeLists.txt index 69fa95e82f3c3..6f242cd168f52 100644 --- a/libc/src/time/windows/CMakeLists.txt +++ b/libc/src/time/windows/CMakeLists.txt @@ -3,7 +3,7 @@ add_entrypoint_object( SRCS clock_getres.cpp DEPENDS - libc.src.__support.time.windows.qpc + libc.src.__support.time.windows.performance_counter libc.src.__support.time.units libc.src.__support.common libc.src.__support.macros.optimization diff --git a/libc/src/time/windows/clock_getres.cpp b/libc/src/time/windows/clock_getres.cpp index 42b313e4f1adf..b8c0c82aa6419 100644 --- a/libc/src/time/windows/clock_getres.cpp +++ b/libc/src/time/windows/clock_getres.cpp @@ -15,7 +15,7 @@ #include "src/__support/common.h" #include "src/__support/macros/optimization.h" #include "src/__support/time/units.h" -#include "src/__support/time/windows/qpc.h" +#include "src/__support/time/windows/performance_counter.h" #include "src/errno/libc_errno.h" #include "src/time/clock_getres.h" @@ -36,9 +36,9 @@ LLVM_LIBC_FUNCTION(int, clock_getres, (clockid_t id, struct timespec *res)) { constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL; constexpr unsigned long long SEC_LIMIT = cpp::numeric_limitstv_sec)>::max(); - // For CLOCK_MONOTONIC, we are using QPC + // For CLOCK_MONOTONIC, we are using performance counter // https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps - // Hence, the resolution is given by the QPC frequency. + // Hence, the resolution is given by the performance counter frequency. // For CLOCK_REALTIME, the precision is given by // GetSystemTimeAdjustmentPrecise // (https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeadjustmentprecise) @@ -51,8 +51,8 @@ LLVM_LIBC_FUNCTION(int, clock_getres, (clockid_t id, struct timespec *res)) { return -1; case CLOCK_MONOTONIC: { - long long freq = qpc::get_ticks_per_second(); - [[clang::assume(freq != 0)]]; + long long freq = performance_counter::get_ticks_per_second(); + __builtin_assume(freq != 0); // division of 1 second by frequency, rounded up. long long tv_sec = static_cast(freq == 1); long long tv_nsec =