diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index 4d13ee095d671..cbb2a261ed49a 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -15,7 +15,10 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR}/Internal set(swift_concurrency_private_link_libraries) if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - list(APPEND swift_concurrency_private_link_libraries Synchronization) + list(APPEND swift_concurrency_private_link_libraries + Synchronization + mincore.lib # For QueryInterruptTime() + ) endif() set(swift_concurrency_incorporate_object_libraries_so swiftThreading) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 50e4e61b1808f..2c9e43c8f4cdd 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -41,19 +41,15 @@ void swift_get_time( #elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) clock_gettime(CLOCK_MONOTONIC, &continuous); #elif defined(_WIN32) - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - LARGE_INTEGER count; - QueryPerformanceCounter(&count); - // Divide count (number of ticks) by frequency (number of ticks per - // second) to get the counter in seconds. We also need to multiply the - // count by 1,000,000,000 to get nanosecond resolution. By multiplying - // first, we maintain high precision. The resulting value is the tick - // count in nanoseconds. Use 128-bit math to avoid overflowing. - auto quadPart = static_cast(count.QuadPart); - auto ns = (quadPart * 1'000'000'000) / freq.QuadPart; - continuous.tv_sec = ns / 1'000'000'000; - continuous.tv_nsec = ns % 1'000'000'000; + // This needs to match what swift-corelibs-libdispatch does + + // QueryInterruptTimePrecise() outputs a value measured in 100ns + // units. We must divide the output by 10,000,000 to get a value in + // seconds and multiply the remainder by 100 to get nanoseconds. + ULONGLONG interruptTime; + (void)QueryInterruptTimePrecise(&interruptTime); + continuous.tv_sec = interruptTime / 10'000'000; + continuous.tv_nsec = (interruptTime % 10'000'000) * 100; #else #error Missing platform continuous time definition #endif @@ -72,32 +68,13 @@ void swift_get_time( #elif (defined(__OpenBSD__) || defined(__FreeBSD__)) clock_gettime(CLOCK_UPTIME, &suspending); #elif defined(_WIN32) - // QueryUnbiasedInterruptTimePrecise() was added in Windows 10 and is, as - // the name suggests, more precise than QueryUnbiasedInterruptTime(). - // Unfortunately, the symbol is not listed in any .lib file in the SDK and - // must be looked up dynamically at runtime even if our minimum deployment - // target is Windows 10. - typedef decltype(QueryUnbiasedInterruptTimePrecise) *QueryUITP_FP; - static QueryUITP_FP queryUITP = nullptr; - static swift::once_t onceToken; - swift::once(onceToken, [] { - if (HMODULE hKernelBase = GetModuleHandleW(L"KernelBase.dll")) { - queryUITP = reinterpret_cast( - GetProcAddress(hKernelBase, "QueryUnbiasedInterruptTimePrecise") - ); - } - }); + // This needs to match what swift-corelibs-libdispatch does - // Call whichever API is available. Both output a value measured in 100ns + // QueryUnbiasedInterruptTimePrecise() outputs a value measured in 100ns // units. We must divide the output by 10,000,000 to get a value in // seconds and multiply the remainder by 100 to get nanoseconds. ULONGLONG unbiasedTime; - if (queryUITP) { - (* queryUITP)(&unbiasedTime); - } else { - // Fall back to the older, less precise API. - (void)QueryUnbiasedInterruptTime(&unbiasedTime); - } + (void)QueryUnbiasedInterruptTimePrecise(&unbiasedTime); suspending.tv_sec = unbiasedTime / 10'000'000; suspending.tv_nsec = (unbiasedTime % 10'000'000) * 100; #else @@ -128,10 +105,8 @@ switch (clock_id) { #elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) clock_getres(CLOCK_MONOTONIC, &continuous); #elif defined(_WIN32) - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); continuous.tv_sec = 0; - continuous.tv_nsec = 1'000'000'000 / freq.QuadPart; + continuous.tv_nsec = 100; #else #error Missing platform continuous time definition #endif