From 27c684f5914e2ecbaf3f4dc26a9f62d1eb7bae5f Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 25 Jan 2023 17:40:52 -0500 Subject: [PATCH 01/10] SuspendingClock on Windows does not suspend #63224 --- stdlib/public/Concurrency/Clock.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 4ad1c1bb50662..c4e6e342dcaaa 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -87,18 +87,10 @@ void swift_get_time( *seconds = suspending.tv_sec; *nanoseconds = suspending.tv_nsec; #elif defined(_WIN32) - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - LARGE_INTEGER count; - QueryPerformanceCounter(&count); - *seconds = count.QuadPart / freq.QuadPart; - if (freq.QuadPart < 1000000000) { - *nanoseconds = - ((count.QuadPart % freq.QuadPart) * 1000000000) / freq.QuadPart; - } else { - *nanoseconds = - (count.QuadPart % freq.QuadPart) * (1000000000.0 / freq.QuadPart); - } + ULONGLONG unbiasedTime; + QueryUnbiasedInterruptTimePrecise(&unbiasedTime); + *seconds = unbiasedTime / 10000000ULL; // unit is 100ns + *nanoseconds = unbiasedTime % 10000000ULL; #else #error Missing platform suspending time definition #endif From aaace52d81ece8fd961099f66e53af01a4c32288 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 25 Jan 2023 17:57:49 -0500 Subject: [PATCH 02/10] Fix inaccurate values for swift_get_clock_res() on Windows --- stdlib/public/Concurrency/Clock.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index c4e6e342dcaaa..f392b0c7cdc55 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -124,8 +124,10 @@ switch (clock_id) { *seconds = continuous.tv_sec; *nanoseconds = continuous.tv_nsec; #elif defined(_WIN32) + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); *seconds = 0; - *nanoseconds = 1000; + *nanoseconds = 1000000000 / freq.QuadPart; #else #error Missing platform continuous time definition #endif @@ -151,7 +153,7 @@ switch (clock_id) { *nanoseconds = suspending.tv_nsec; #elif defined(_WIN32) *seconds = 0; - *nanoseconds = 1000; + *nanoseconds = 100; #else #error Missing platform suspending time definition #endif From 95c092656ccacf661e1c8c3d45b6a2df1fdce5b9 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 26 Jan 2023 12:26:02 -0500 Subject: [PATCH 03/10] QueryUnbiasedInterruptTimePrecise() isn't always available so it must be dynamically looked up. Also, fix the math after calling it, and avoid floating-point math on the continuous clock. --- stdlib/public/Concurrency/Clock.cpp | 47 ++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index f392b0c7cdc55..cb1e3c9ed0338 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "swift/Runtime/Concurrency.h" +#include "swift/Runtime/Once.h" #if __has_include() #define HAS_TIME 1 @@ -20,6 +21,7 @@ #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include +#include #endif using namespace swift; @@ -52,14 +54,14 @@ void swift_get_time( QueryPerformanceFrequency(&freq); LARGE_INTEGER count; QueryPerformanceCounter(&count); - *seconds = count.QuadPart / freq.QuadPart; - if (freq.QuadPart < 1000000000) { - *nanoseconds = - ((count.QuadPart % freq.QuadPart) * 1000000000) / freq.QuadPart; - } else { - *nanoseconds = - (count.QuadPart % freq.QuadPart) * (1000000000.0 / freq.QuadPart); - } + // 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. + long long ns = (count.QuadPart * 1000000000) / freq.QuadPart; + *seconds = ns / 1000000000; + *nanoseconds = ns % 1000000000; #else #error Missing platform continuous time definition #endif @@ -87,10 +89,33 @@ void swift_get_time( *seconds = suspending.tv_sec; *nanoseconds = suspending.tv_nsec; #elif defined(_WIN32) + // QueryUnbiasedInterruptTimePrecise() was added in Windows 10 and is, as + // the name suggests, more precise than QueryUnbiasedInterruptTime(). + // However, despite being declared in Windows' headers, we must look it up + // dynamically at runtime. + 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")) { + queryUnbiasedInterruptTimePrecise = reinterpret_cast( + GetProcAddress(hKernelBase, "QueryUnbiasedInterruptTimePrecise") + ); + } + }); + + // Call whichever API is available. Both output 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; - QueryUnbiasedInterruptTimePrecise(&unbiasedTime); - *seconds = unbiasedTime / 10000000ULL; // unit is 100ns - *nanoseconds = unbiasedTime % 10000000ULL; + if (queryUITP) { + (* queryUITP)(&unbiasedTime); + } else { + // Fall back to the older, less precise API. + (void)QueryUnbiasedInterruptTime(&unbiasedTime); + } + *seconds = unbiasedTime / 10000000; + *nanoseconds = (unbiasedTime % 10000000) * 100; #else #error Missing platform suspending time definition #endif From 07f8b2d22cc6991bdeac045ab79b828d20de7f26 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 26 Jan 2023 14:07:19 -0500 Subject: [PATCH 04/10] - Add more comments explaining why we use GetProcAddress(). - Use 128-bit math with QueryPerformanceCounter() to avoid overflowing. - Use swift::fatalError() instead of abort() for bad clock IDs. - Use digit separators (C++14 feature, makes large integers easier to read.) --- stdlib/public/Concurrency/Clock.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index cb1e3c9ed0338..f37cb8fd67f30 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "swift/Runtime/Concurrency.h" +#include "swift/Runtime/Debug.h" #include "swift/Runtime/Once.h" #if __has_include() @@ -21,6 +22,7 @@ #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include +#include #include #endif @@ -58,10 +60,12 @@ void swift_get_time( // 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. - long long ns = (count.QuadPart * 1000000000) / freq.QuadPart; - *seconds = ns / 1000000000; - *nanoseconds = ns % 1000000000; + // count in nanoseconds. Use 128-bit math to avoid overflowing. + DWORD64 hi = 0; + DWORD64 lo = _umul128(count.QuadPart, 1'000'000'000, &hi); + DWORD64 ns = _udiv128(hi, lo, freq.QuadPart, nullptr); + *seconds = ns / 1'000'000'000; + *nanoseconds = ns % 1'000'000'000; #else #error Missing platform continuous time definition #endif @@ -91,8 +95,9 @@ void swift_get_time( #elif defined(_WIN32) // QueryUnbiasedInterruptTimePrecise() was added in Windows 10 and is, as // the name suggests, more precise than QueryUnbiasedInterruptTime(). - // However, despite being declared in Windows' headers, we must look it up - // dynamically at runtime. + // 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; @@ -114,15 +119,15 @@ void swift_get_time( // Fall back to the older, less precise API. (void)QueryUnbiasedInterruptTime(&unbiasedTime); } - *seconds = unbiasedTime / 10000000; - *nanoseconds = (unbiasedTime % 10000000) * 100; + *seconds = unbiasedTime / 10'000'000; + *nanoseconds = (unbiasedTime % 10'000'000) * 100; #else #error Missing platform suspending time definition #endif return; } } - abort(); // Invalid clock_id + swift::fatalError(0, "Fatal error: invalid clock ID %d\n", clock_id); } SWIFT_EXPORT_FROM(swift_Concurrency) @@ -152,7 +157,7 @@ switch (clock_id) { LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); *seconds = 0; - *nanoseconds = 1000000000 / freq.QuadPart; + *nanoseconds = 1'000'000'000 / freq.QuadPart; #else #error Missing platform continuous time definition #endif @@ -185,5 +190,5 @@ switch (clock_id) { return; } } - abort(); // Invalid clock_id + swift::fatalError(0, "Fatal error: invalid clock ID %d\n", clock_id); } From 9d0cec586ce5fbab1a54c04b5d982b7834bc0022 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 26 Jan 2023 15:23:28 -0500 Subject: [PATCH 05/10] Do 128-bit math with clang extensions instead of MSVC++ extensions/intrinsics --- stdlib/public/Concurrency/Clock.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index f37cb8fd67f30..270d20d9fcba5 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -61,9 +61,15 @@ void swift_get_time( // 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. - DWORD64 hi = 0; - DWORD64 lo = _umul128(count.QuadPart, 1'000'000'000, &hi); - DWORD64 ns = _udiv128(hi, lo, freq.QuadPart, nullptr); +//#if defined(_MSC_VER) +// DWORD64 hi = 0; +// DWORD64 lo = _umul128(count.QuadPart, 1'000'000'000, &hi); +// DWORD64 ns = _udiv128(hi, lo, freq.QuadPart, nullptr); +//#else + auto ns = static_cast(count.QuadPart); + ns *= 1'000'000'000; + ns /= freq.QuadPart; +//#endif *seconds = ns / 1'000'000'000; *nanoseconds = ns % 1'000'000'000; #else @@ -103,7 +109,7 @@ void swift_get_time( static swift::once_t onceToken; swift::once(onceToken, [] { if (HMODULE hKernelBase = GetModuleHandleW(L"KernelBase.dll")) { - queryUnbiasedInterruptTimePrecise = reinterpret_cast( + queryUITP = reinterpret_cast( GetProcAddress(hKernelBase, "QueryUnbiasedInterruptTimePrecise") ); } From 48a5fb3b9715413c5dae130e0b1dd4c9b1c950d0 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 26 Jan 2023 16:30:07 -0500 Subject: [PATCH 06/10] Use swift_Concurrency_fatalError() instead of swift::fatalError() (oops) --- stdlib/public/Concurrency/Clock.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 270d20d9fcba5..065280ca3c2aa 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "swift/Runtime/Concurrency.h" -#include "swift/Runtime/Debug.h" #include "swift/Runtime/Once.h" #if __has_include() @@ -26,6 +25,8 @@ #include #endif +#include "Error.h" + using namespace swift; SWIFT_EXPORT_FROM(swift_Concurrency) @@ -133,7 +134,8 @@ void swift_get_time( return; } } - swift::fatalError(0, "Fatal error: invalid clock ID %d\n", clock_id); + swift_Concurrency_fatalError(0, "Fatal error: invalid clock ID %d\n", + clock_id); } SWIFT_EXPORT_FROM(swift_Concurrency) @@ -196,5 +198,6 @@ switch (clock_id) { return; } } - swift::fatalError(0, "Fatal error: invalid clock ID %d\n", clock_id); + swift_Concurrency_fatalError(0, "Fatal error: invalid clock ID %d\n", + clock_id); } From 9af8d99712d64dab7e9713ed073e70b737a92ea6 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 26 Jan 2023 16:42:10 -0500 Subject: [PATCH 07/10] Remove commented-out MSVC++ 128-bit math --- stdlib/public/Concurrency/Clock.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 065280ca3c2aa..6ef2df913a238 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -62,15 +62,8 @@ void swift_get_time( // 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. -//#if defined(_MSC_VER) -// DWORD64 hi = 0; -// DWORD64 lo = _umul128(count.QuadPart, 1'000'000'000, &hi); -// DWORD64 ns = _udiv128(hi, lo, freq.QuadPart, nullptr); -//#else - auto ns = static_cast(count.QuadPart); - ns *= 1'000'000'000; - ns /= freq.QuadPart; -//#endif + auto quadPart = static_cast(count.QuadPart); + auto ns = (quadPart * 1'000'000'000) / freq.QuadPart; *seconds = ns / 1'000'000'000; *nanoseconds = ns % 1'000'000'000; #else From 5444f228a28e0c168806dbd894511d92d49ce49f Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 26 Jan 2023 21:44:21 -0500 Subject: [PATCH 08/10] Don't need immintrin.h --- stdlib/public/Concurrency/Clock.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 6ef2df913a238..12a59650bae06 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -21,7 +21,6 @@ #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include -#include #include #endif From 519193937cb311e0a1c4d11e6efa89944e135954 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 27 Jan 2023 11:26:27 -0500 Subject: [PATCH 09/10] Get rid of redundant timespecs --- stdlib/public/Concurrency/Clock.cpp | 65 +++++++++-------------------- 1 file changed, 19 insertions(+), 46 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 12a59650bae06..6ec0c0402467a 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -36,21 +36,13 @@ void swift_get_time( swift_clock_id clock_id) { switch (clock_id) { case swift_clock_id_continuous: { -#if defined(__linux__) && HAS_TIME struct timespec continuous; +#if defined(__linux__) && HAS_TIME clock_gettime(CLOCK_BOOTTIME, &continuous); - *seconds = continuous.tv_sec; - *nanoseconds = continuous.tv_nsec; #elif defined(__APPLE__) && HAS_TIME - struct timespec continuous; clock_gettime(CLOCK_MONOTONIC_RAW, &continuous); - *seconds = continuous.tv_sec; - *nanoseconds = continuous.tv_nsec; #elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) && HAS_TIME - struct timespec continuous; clock_gettime(CLOCK_MONOTONIC, &continuous); - *seconds = continuous.tv_sec; - *nanoseconds = continuous.tv_nsec; #elif defined(_WIN32) LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); @@ -63,34 +55,25 @@ void swift_get_time( // 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; - *seconds = ns / 1'000'000'000; - *nanoseconds = ns % 1'000'000'000; + continuous.tv_sec = ns / 1'000'000'000; + continuous.tv_nsec = ns % 1'000'000'000; #else #error Missing platform continuous time definition #endif + *seconds = continuous.tv_sec; + *nanoseconds = continuous.tv_nsec; return; } case swift_clock_id_suspending: { -#if defined(__linux__) && HAS_TIME struct timespec suspending; +#if defined(__linux__) && HAS_TIME clock_gettime(CLOCK_MONOTONIC, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif defined(__APPLE__) && HAS_TIME - struct timespec suspending; clock_gettime(CLOCK_UPTIME_RAW, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif defined(__wasi__) && HAS_TIME - struct timespec suspending; clock_gettime(CLOCK_MONOTONIC, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && HAS_TIME - struct timespec suspending; clock_gettime(CLOCK_UPTIME, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif defined(_WIN32) // QueryUnbiasedInterruptTimePrecise() was added in Windows 10 and is, as // the name suggests, more precise than QueryUnbiasedInterruptTime(). @@ -118,11 +101,13 @@ void swift_get_time( // Fall back to the older, less precise API. (void)QueryUnbiasedInterruptTime(&unbiasedTime); } - *seconds = unbiasedTime / 10'000'000; - *nanoseconds = (unbiasedTime % 10'000'000) * 100; + suspending.tv_sec = unbiasedTime / 10'000'000; + suspending.tv_nsec = (unbiasedTime % 10'000'000) * 100; #else #error Missing platform suspending time definition #endif + *seconds = suspending.tv_sec; + *nanoseconds = suspending.tv_nsec; return; } } @@ -138,55 +123,43 @@ void swift_get_clock_res( swift_clock_id clock_id) { switch (clock_id) { case swift_clock_id_continuous: { -#if defined(__linux__) && HAS_TIME struct timespec continuous; +#if defined(__linux__) && HAS_TIME clock_getres(CLOCK_BOOTTIME, &continuous); - *seconds = continuous.tv_sec; - *nanoseconds = continuous.tv_nsec; #elif defined(__APPLE__) && HAS_TIME - struct timespec continuous; clock_getres(CLOCK_MONOTONIC_RAW, &continuous); - *seconds = continuous.tv_sec; - *nanoseconds = continuous.tv_nsec; #elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) && HAS_TIME - struct timespec continuous; clock_getres(CLOCK_MONOTONIC, &continuous); - *seconds = continuous.tv_sec; - *nanoseconds = continuous.tv_nsec; #elif defined(_WIN32) LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); - *seconds = 0; - *nanoseconds = 1'000'000'000 / freq.QuadPart; + continuous.tv_sec = 0; + continuous.tv_nsec = 1'000'000'000 / freq.QuadPart; #else #error Missing platform continuous time definition #endif + *seconds = continuous.tv_sec; + *nanoseconds = continuous.tv_nsec; return; } case swift_clock_id_suspending: { struct timespec suspending; #if defined(__linux__) && HAS_TIME clock_getres(CLOCK_MONOTONIC_RAW, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif defined(__APPLE__) && HAS_TIME clock_getres(CLOCK_UPTIME_RAW, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif defined(__wasi__) && HAS_TIME clock_getres(CLOCK_MONOTONIC, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && HAS_TIME clock_getres(CLOCK_UPTIME, &suspending); - *seconds = suspending.tv_sec; - *nanoseconds = suspending.tv_nsec; #elif defined(_WIN32) - *seconds = 0; - *nanoseconds = 100; + suspending.tv_sec = 0; + suspending.tv_nsec = 100; #else #error Missing platform suspending time definition #endif + *seconds = suspending.tv_sec; + *nanoseconds = suspending.tv_nsec; return; } } From 4757e68aa373012e08b37f7b563442d43d227cef Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 27 Jan 2023 13:56:07 -0500 Subject: [PATCH 10/10] Every platform has time.h, so remove the HAS_TIME check --- stdlib/public/Concurrency/Clock.cpp | 31 +++++++++++++---------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 6ec0c0402467a..b661eb14d8d20 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -13,10 +13,7 @@ #include "swift/Runtime/Concurrency.h" #include "swift/Runtime/Once.h" -#if __has_include() -#define HAS_TIME 1 #include -#endif #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -37,11 +34,11 @@ void swift_get_time( switch (clock_id) { case swift_clock_id_continuous: { struct timespec continuous; -#if defined(__linux__) && HAS_TIME +#if defined(__linux__) clock_gettime(CLOCK_BOOTTIME, &continuous); -#elif defined(__APPLE__) && HAS_TIME +#elif defined(__APPLE__) clock_gettime(CLOCK_MONOTONIC_RAW, &continuous); -#elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) && HAS_TIME +#elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) clock_gettime(CLOCK_MONOTONIC, &continuous); #elif defined(_WIN32) LARGE_INTEGER freq; @@ -66,13 +63,13 @@ void swift_get_time( } case swift_clock_id_suspending: { struct timespec suspending; -#if defined(__linux__) && HAS_TIME +#if defined(__linux__) clock_gettime(CLOCK_MONOTONIC, &suspending); -#elif defined(__APPLE__) && HAS_TIME +#elif defined(__APPLE__) clock_gettime(CLOCK_UPTIME_RAW, &suspending); -#elif defined(__wasi__) && HAS_TIME +#elif defined(__wasi__) clock_gettime(CLOCK_MONOTONIC, &suspending); -#elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && HAS_TIME +#elif (defined(__OpenBSD__) || defined(__FreeBSD__)) clock_gettime(CLOCK_UPTIME, &suspending); #elif defined(_WIN32) // QueryUnbiasedInterruptTimePrecise() was added in Windows 10 and is, as @@ -124,11 +121,11 @@ void swift_get_clock_res( switch (clock_id) { case swift_clock_id_continuous: { struct timespec continuous; -#if defined(__linux__) && HAS_TIME +#if defined(__linux__) clock_getres(CLOCK_BOOTTIME, &continuous); -#elif defined(__APPLE__) && HAS_TIME +#elif defined(__APPLE__) clock_getres(CLOCK_MONOTONIC_RAW, &continuous); -#elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) && HAS_TIME +#elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)) clock_getres(CLOCK_MONOTONIC, &continuous); #elif defined(_WIN32) LARGE_INTEGER freq; @@ -144,13 +141,13 @@ switch (clock_id) { } case swift_clock_id_suspending: { struct timespec suspending; -#if defined(__linux__) && HAS_TIME +#if defined(__linux__) clock_getres(CLOCK_MONOTONIC_RAW, &suspending); -#elif defined(__APPLE__) && HAS_TIME +#elif defined(__APPLE__) clock_getres(CLOCK_UPTIME_RAW, &suspending); -#elif defined(__wasi__) && HAS_TIME +#elif defined(__wasi__) clock_getres(CLOCK_MONOTONIC, &suspending); -#elif (defined(__OpenBSD__) || defined(__FreeBSD__)) && HAS_TIME +#elif (defined(__OpenBSD__) || defined(__FreeBSD__)) clock_getres(CLOCK_UPTIME, &suspending); #elif defined(_WIN32) suspending.tv_sec = 0;