Add an additional case for clocks to sleep with a wallclock deadline (#79139)

This only modifies the runtime function `swift_task_enqueueGlobalWithDeadline` to take new clock primitive to
interoperate with existing dispatch wall clock values.
This commit is contained in:
Philippe Hausler
2025-06-09 09:01:27 -07:00
committed by GitHub
parent 1b003b2c51
commit 694aebb1fb
3 changed files with 68 additions and 9 deletions

View File

@@ -1074,7 +1074,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)

View File

@@ -33,6 +33,10 @@
#include "Error.h"
#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC 1000000000ull
#endif
using namespace swift;
SWIFT_EXPORT_FROM(swift_Concurrency)
@@ -109,6 +113,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",
@@ -170,6 +197,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);

View File

@@ -55,6 +55,10 @@
#include "ExecutorImpl.h"
#include "TaskPrivate.h"
#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC 1000000000ull
#endif
using namespace swift;
/// The function passed to dispatch_async_f to execute a job.
@@ -294,7 +298,12 @@ 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;
if (__builtin_mul_overflow(sec, NSEC_PER_SEC, &deadline)
|| __builtin_add_overflow(nsec, deadline, &deadline)) {
deadline = UINT64_MAX;
}
uint64_t value = platform_time((uint64_t)deadline);
if (value >= DISPATCH_TIME_MAX_VALUE) {
return DISPATCH_TIME_FOREVER;
@@ -304,6 +313,20 @@ 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: {
#if defined(_WIN32)
struct timespec ts = {
.tv_sec = sec,
.tv_nsec = static_cast<long>(nsec)
};
#else
struct timespec ts = {
.tv_sec = sec,
.tv_nsec = nsec
};
#endif
return dispatch_walltime(&ts, 0);
}
}
__builtin_unreachable();
}
@@ -332,13 +355,7 @@ void swift_dispatchEnqueueWithDeadline(bool global,
job->schedulerPrivate[SwiftJobDispatchQueueIndex] = queue;
}
uint64_t deadline;
if (__builtin_mul_overflow(sec, NSEC_PER_SEC, &deadline)
|| __builtin_add_overflow(nsec, deadline, &deadline)) {
deadline = UINT64_MAX;
}
dispatch_time_t when = clock_and_value_to_time(clock, deadline);
dispatch_time_t when = clock_and_value_to_time(clock, sec, nsec);
if (tnsec != -1) {
uint64_t leeway;