|
24 | 24 |
|
25 | 25 | #if SWIFT_CONCURRENCY_ENABLE_DISPATCH
|
26 | 26 | #include <dispatch/dispatch.h>
|
| 27 | +#if __has_include(<dispatch/private.h>) |
| 28 | +#include <dispatch/private.h> |
| 29 | +#else |
| 30 | +extern "C" { |
| 31 | +DISPATCH_ENUM(dispatch_clockid, uintptr_t, |
| 32 | + DISPATCH_CLOCKID_UPTIME = 1, |
| 33 | + DISPATCH_CLOCKID_MONOTONIC = 2, |
| 34 | + DISPATCH_CLOCKID_WALLTIME = 3, |
| 35 | + DISPATCH_CLOCKID_REALTIME = 3, |
| 36 | +); |
| 37 | + |
| 38 | +DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NOTHROW |
| 39 | +dispatch_time_t |
| 40 | +dispatch_time_from_nsec(dispatch_clockid_t clock, uint64_t deadline); |
| 41 | +} |
| 42 | +#endif |
27 | 43 |
|
28 | 44 | #if !defined(_WIN32)
|
29 | 45 | #include <dlfcn.h>
|
@@ -227,38 +243,53 @@ static void swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
|
227 | 243 |
|
228 | 244 | #define DISPATCH_UP_OR_MONOTONIC_TIME_MASK (1ULL << 63)
|
229 | 245 |
|
| 246 | +struct __swift_job_source { |
| 247 | + dispatch_source_t source; |
| 248 | + Job *job; |
| 249 | +}; |
| 250 | + |
| 251 | +static void __swift_run_job_leeway(Job *job) { |
| 252 | + dispatch_source_t source = (dispatch_source_t)job->Reserved; |
| 253 | + job->Reserved = nullptr; |
| 254 | + __swift_run_job(job); |
| 255 | + dispatch_release(source); |
| 256 | +} |
| 257 | + |
230 | 258 | SWIFT_CC(swift)
|
231 | 259 | static void swift_task_enqueueGlobalWithDeadlineImpl(long long sec,
|
232 | 260 | long long nsec,
|
233 | 261 | long long tsec,
|
234 | 262 | long long tnsec,
|
235 | 263 | int clock, Job *job) {
|
236 | 264 | assert(job && "no job provided");
|
237 |
| - |
238 |
| - dispatch_function_t dispatchFunction = &__swift_run_job; |
239 |
| - void *dispatchContext = job; |
240 |
| - |
241 | 265 | JobPriority priority = job->getPriority();
|
242 | 266 |
|
243 | 267 | auto queue = getGlobalQueue(priority);
|
244 | 268 |
|
245 | 269 | job->SchedulerPrivate[Job::DispatchQueueIndex] =
|
246 | 270 | DISPATCH_QUEUE_GLOBAL_EXECUTOR;
|
247 | 271 |
|
248 |
| - long long nowSec; |
249 |
| - long long nowNsec; |
250 |
| - swift_get_time(&nowSec, &nowNsec, (swift_clock_id)clock); |
251 |
| - |
252 |
| - uint64_t delta = (sec - nowSec) * NSEC_PER_SEC + nsec - nowNsec; |
253 |
| - |
254 |
| - dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, delta); |
255 |
| - |
| 272 | + dispatch_clockid_t dispatchClock; |
256 | 273 | if (clock == swift_clock_id_continuous) {
|
257 |
| - when |= DISPATCH_UP_OR_MONOTONIC_TIME_MASK; |
| 274 | + dispatchClock = DISPATCH_CLOCKID_MONOTONIC; |
| 275 | + } else { |
| 276 | + dispatchClock = DISPATCH_CLOCKID_UPTIME; |
258 | 277 | }
|
259 |
| - // TODO: this should pass the leeway/tolerance along when it is not -1 nanoseconds |
260 |
| - // either a dispatch_source can be created or a better dispatch_after_f can be made for this |
261 |
| - dispatch_after_f(when, queue, dispatchContext, dispatchFunction); |
| 278 | + uint64_t deadline = sec * NSEC_PER_SEC + nsec; |
| 279 | + dispatch_time_t when = dispatch_time_from_nsec(dispatchClock, deadline); |
| 280 | + dispatch_source_t source = |
| 281 | + dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); |
| 282 | + job->Reserved = source; |
| 283 | + dispatch_set_context(source, job); |
| 284 | + uint64_t leeway = 0; |
| 285 | + if (tnsec != -1) { |
| 286 | + leeway = tsec * NSEC_PER_SEC + tnsec; |
| 287 | + } |
| 288 | + dispatch_source_set_timer(source, when, |
| 289 | + DISPATCH_TIME_FOREVER, leeway); |
| 290 | + dispatch_source_set_event_handler_f(source, |
| 291 | + (dispatch_function_t)&__swift_run_job_leeway); |
| 292 | + dispatch_activate(source); |
262 | 293 | }
|
263 | 294 |
|
264 | 295 | SWIFT_CC(swift)
|
|
0 commit comments