From 0a5d57dddf86181f56cbc6ea40087b92d89134ae Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Tue, 4 Feb 2025 13:20:47 -0800 Subject: [PATCH 1/3] Add an additional case for clocks to sleep with a wallclock deadline --- include/swift/Runtime/Concurrency.h | 3 ++- stdlib/public/Concurrency/DispatchGlobalExecutor.cpp | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/swift/Runtime/Concurrency.h b/include/swift/Runtime/Concurrency.h index 774333e67034d..afc62515072cc 100644 --- a/include/swift/Runtime/Concurrency.h +++ b/include/swift/Runtime/Concurrency.h @@ -1022,7 +1022,8 @@ void swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void*), enum swift_clock_id : int { swift_clock_id_continuous = 1, - swift_clock_id_suspending = 2 + swift_clock_id_suspending = 2, + swift_clock_id_wall = 3 }; SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift) diff --git a/stdlib/public/Concurrency/DispatchGlobalExecutor.cpp b/stdlib/public/Concurrency/DispatchGlobalExecutor.cpp index 473463f6a2e4b..5440c0ed9f3fe 100644 --- a/stdlib/public/Concurrency/DispatchGlobalExecutor.cpp +++ b/stdlib/public/Concurrency/DispatchGlobalExecutor.cpp @@ -314,7 +314,8 @@ platform_time(uint64_t nsec) { #endif static inline dispatch_time_t -clock_and_value_to_time(int clock, long long deadline) { +clock_and_value_to_time(int clock, long long sec, long long nsec) { + uint64_t deadline = sec * NSEC_PER_SEC + nsec; uint64_t value = platform_time((uint64_t)deadline); if (value >= DISPATCH_TIME_MAX_VALUE) { return DISPATCH_TIME_FOREVER; @@ -324,6 +325,13 @@ clock_and_value_to_time(int clock, long long deadline) { return value; case swift_clock_id_continuous: return value | DISPATCH_UP_OR_MONOTONIC_TIME_MASK; + case swift_clock_id_wall: { + struct timespec ts = { + .tv_sec = sec, + .tv_nsec = nsec + }; + return dispatch_walltime(&ts, 0); + } } __builtin_unreachable(); } From ff94b86fe202017855c7b1df06425ae88adf0eb4 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Tue, 4 Feb 2025 18:05:39 -0800 Subject: [PATCH 2/3] Add an additional clock fetch for wall time --- stdlib/public/Concurrency/Clock.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 2c9e43c8f4cdd..0f5bd8bccf104 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -83,6 +83,29 @@ void swift_get_time( *seconds = suspending.tv_sec; *nanoseconds = suspending.tv_nsec; return; + case swift_clock_id_wall: + struct timespec wall; +#if defined(__linux__) || defined(__APPLE__) || defined(__wasi__) || defined(__OpenBSD__) || defined(__FreeBSD__) + clock_gettime(CLOCK_REALTIME, &wall); +#elif defined(_WIN32) + // This needs to match what swift-corelibs-libdispatch does + + static const uint64_t kNTToUNIXBiasAdjustment = 11644473600 * NSEC_PER_SEC; + // FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC). + FILETIME ft; + ULARGE_INTEGER li; + GetSystemTimePreciseAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + ULONGLONG ns = li.QuadPart * 100ull - kNTToUNIXBiasAdjustment; + wall.tv_sec = ns / 1000000000ull; + wall.tv_nsec = ns % 1000000000ull; +#else +#error Missing platform wall time definition +#endif + *seconds = wall.tv_sec; + *nanoseconds = wall.tv_nsec; + return; } } swift_Concurrency_fatalError(0, "Fatal error: invalid clock ID %d\n", From 48ce15ec04f3e5d14f5012ba4807251298009fb9 Mon Sep 17 00:00:00 2001 From: Philippe Hausler Date: Wed, 5 Feb 2025 08:06:52 -0800 Subject: [PATCH 3/3] Add resolution wall times --- stdlib/public/Concurrency/Clock.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 0f5bd8bccf104..6047ad91121e2 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -89,7 +89,7 @@ void swift_get_time( clock_gettime(CLOCK_REALTIME, &wall); #elif defined(_WIN32) // This needs to match what swift-corelibs-libdispatch does - + static const uint64_t kNTToUNIXBiasAdjustment = 11644473600 * NSEC_PER_SEC; // FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC). FILETIME ft; @@ -157,6 +157,20 @@ switch (clock_id) { *nanoseconds = suspending.tv_nsec; return; } + case swift_clock_id_wall: { + struct timespec wall; +#if defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__) + clock_getres(CLOCK_REALTIME, &wall); +#elif defined(_WIN32) + wall.tv_sec = 0; + wall.tv_nsec = 100; +#else +#error Missing platform wall time definition +#endif + *seconds = wall.tv_sec; + *nanoseconds = wall.tv_nsec; + return; + } } swift_Concurrency_fatalError(0, "Fatal error: invalid clock ID %d\n", clock_id);