mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user