Skip to content

Commit 694aebb

Browse files
authored
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.
1 parent 1b003b2 commit 694aebb

File tree

3 files changed

+68
-9
lines changed

3 files changed

+68
-9
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,8 @@ void swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void*),
10741074

10751075
enum swift_clock_id : int {
10761076
swift_clock_id_continuous = 1,
1077-
swift_clock_id_suspending = 2
1077+
swift_clock_id_suspending = 2,
1078+
swift_clock_id_wall = 3
10781079
};
10791080

10801081
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)

stdlib/public/Concurrency/Clock.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333

3434
#include "Error.h"
3535

36+
#ifndef NSEC_PER_SEC
37+
#define NSEC_PER_SEC 1000000000ull
38+
#endif
39+
3640
using namespace swift;
3741

3842
SWIFT_EXPORT_FROM(swift_Concurrency)
@@ -109,6 +113,29 @@ void swift_get_time(
109113
*seconds = suspending.tv_sec;
110114
*nanoseconds = suspending.tv_nsec;
111115
return;
116+
case swift_clock_id_wall:
117+
struct timespec wall;
118+
#if defined(__linux__) || defined(__APPLE__) || defined(__wasi__) || defined(__OpenBSD__) || defined(__FreeBSD__)
119+
clock_gettime(CLOCK_REALTIME, &wall);
120+
#elif defined(_WIN32)
121+
// This needs to match what swift-corelibs-libdispatch does
122+
123+
static const uint64_t kNTToUNIXBiasAdjustment = 11644473600 * NSEC_PER_SEC;
124+
// FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC).
125+
FILETIME ft;
126+
ULARGE_INTEGER li;
127+
GetSystemTimePreciseAsFileTime(&ft);
128+
li.LowPart = ft.dwLowDateTime;
129+
li.HighPart = ft.dwHighDateTime;
130+
ULONGLONG ns = li.QuadPart * 100ull - kNTToUNIXBiasAdjustment;
131+
wall.tv_sec = ns / 1000000000ull;
132+
wall.tv_nsec = ns % 1000000000ull;
133+
#else
134+
#error Missing platform wall time definition
135+
#endif
136+
*seconds = wall.tv_sec;
137+
*nanoseconds = wall.tv_nsec;
138+
return;
112139
}
113140
}
114141
swift_Concurrency_fatalError(0, "Fatal error: invalid clock ID %d\n",
@@ -170,6 +197,20 @@ switch (clock_id) {
170197
*nanoseconds = suspending.tv_nsec;
171198
return;
172199
}
200+
case swift_clock_id_wall: {
201+
struct timespec wall;
202+
#if defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__)
203+
clock_getres(CLOCK_REALTIME, &wall);
204+
#elif defined(_WIN32)
205+
wall.tv_sec = 0;
206+
wall.tv_nsec = 100;
207+
#else
208+
#error Missing platform wall time definition
209+
#endif
210+
*seconds = wall.tv_sec;
211+
*nanoseconds = wall.tv_nsec;
212+
return;
213+
}
173214
}
174215
swift_Concurrency_fatalError(0, "Fatal error: invalid clock ID %d\n",
175216
clock_id);

stdlib/public/Concurrency/DispatchGlobalExecutor.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
#include "ExecutorImpl.h"
5656
#include "TaskPrivate.h"
5757

58+
#ifndef NSEC_PER_SEC
59+
#define NSEC_PER_SEC 1000000000ull
60+
#endif
61+
5862
using namespace swift;
5963

6064
/// The function passed to dispatch_async_f to execute a job.
@@ -294,7 +298,12 @@ platform_time(uint64_t nsec) {
294298
#endif
295299

296300
static inline dispatch_time_t
297-
clock_and_value_to_time(int clock, long long deadline) {
301+
clock_and_value_to_time(int clock, long long sec, long long nsec) {
302+
uint64_t deadline;
303+
if (__builtin_mul_overflow(sec, NSEC_PER_SEC, &deadline)
304+
|| __builtin_add_overflow(nsec, deadline, &deadline)) {
305+
deadline = UINT64_MAX;
306+
}
298307
uint64_t value = platform_time((uint64_t)deadline);
299308
if (value >= DISPATCH_TIME_MAX_VALUE) {
300309
return DISPATCH_TIME_FOREVER;
@@ -304,6 +313,20 @@ clock_and_value_to_time(int clock, long long deadline) {
304313
return value;
305314
case swift_clock_id_continuous:
306315
return value | DISPATCH_UP_OR_MONOTONIC_TIME_MASK;
316+
case swift_clock_id_wall: {
317+
#if defined(_WIN32)
318+
struct timespec ts = {
319+
.tv_sec = sec,
320+
.tv_nsec = static_cast<long>(nsec)
321+
};
322+
#else
323+
struct timespec ts = {
324+
.tv_sec = sec,
325+
.tv_nsec = nsec
326+
};
327+
#endif
328+
return dispatch_walltime(&ts, 0);
329+
}
307330
}
308331
__builtin_unreachable();
309332
}
@@ -332,13 +355,7 @@ void swift_dispatchEnqueueWithDeadline(bool global,
332355
job->schedulerPrivate[SwiftJobDispatchQueueIndex] = queue;
333356
}
334357

335-
uint64_t deadline;
336-
if (__builtin_mul_overflow(sec, NSEC_PER_SEC, &deadline)
337-
|| __builtin_add_overflow(nsec, deadline, &deadline)) {
338-
deadline = UINT64_MAX;
339-
}
340-
341-
dispatch_time_t when = clock_and_value_to_time(clock, deadline);
358+
dispatch_time_t when = clock_and_value_to_time(clock, sec, nsec);
342359

343360
if (tnsec != -1) {
344361
uint64_t leeway;

0 commit comments

Comments
 (0)