27
27
#if __has_include(<dispatch/private.h>)
28
28
#include < dispatch/private.h>
29
29
#else
30
- extern " C" {
31
30
DISPATCH_ENUM (dispatch_clockid, uintptr_t ,
32
31
DISPATCH_CLOCKID_UPTIME = 1 ,
33
32
DISPATCH_CLOCKID_MONOTONIC = 2 ,
34
33
DISPATCH_CLOCKID_WALLTIME = 3 ,
35
34
DISPATCH_CLOCKID_REALTIME = 3 ,
36
35
);
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
36
#endif
43
37
44
38
#if !defined(_WIN32)
@@ -242,19 +236,73 @@ static void swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
242
236
}
243
237
244
238
#define DISPATCH_UP_OR_MONOTONIC_TIME_MASK (1ULL << 63 )
239
+ #define DISPATCH_WALLTIME_MASK (1ULL << 62 )
240
+ #define DISPATCH_TIME_MAX_VALUE (DISPATCH_WALLTIME_MASK - 1 )
245
241
246
242
struct __swift_job_source {
247
243
dispatch_source_t source;
248
244
Job *job;
249
245
};
250
246
251
- static void __swift_run_job_leeway (Job *job) {
252
- dispatch_source_t source = (dispatch_source_t )job->Reserved ;
253
- job->Reserved = nullptr ;
247
+ static void __swift_run_job_leeway (struct __swift_job_source *jobSource) {
248
+ dispatch_source_t source = jobSource->source ;
249
+ Job *job = jobSource->job ;
250
+ free (jobSource);
254
251
__swift_run_job (job);
255
252
dispatch_release (source);
256
253
}
257
254
255
+ #if defined(__i386__) || defined(__x86_64__) || !defined(__APPLE__)
256
+ #define TIME_UNIT_USES_NANOSECONDS 1
257
+ #else
258
+ #define TIME_UNIT_USES_NANOSECONDS 0
259
+ #endif
260
+
261
+ #if TIME_UNIT_USES_NANOSECONDS
262
+ // x86 currently implements mach time in nanoseconds
263
+ // this is NOT likely to change
264
+ static inline uint64_t
265
+ time_nano2mach (uint64_t nsec) {
266
+ return nsec;
267
+ }
268
+ #else
269
+ #define DISPATCH_USE_HOST_TIME 1
270
+ #if defined(__APPLE__)
271
+ #if defined(__arm__) || defined(__arm64__)
272
+ // Apple arm platforms currently use a fixed mach timebase of 125/3 (24 MHz)
273
+ static inline uint64_t
274
+ time_nano2mach (uint64_t nsec) {
275
+ if (!nsec) {
276
+ return nsec;
277
+ }
278
+ if (nsec >= (uint64_t )INT64_MAX) {
279
+ return INT64_MAX;
280
+ }
281
+ if (nsec >= UINT64_MAX / 3ull ) {
282
+ return (nsec / 125ull ) * 3ull ;
283
+ } else {
284
+ return (nsec * 3ull ) / 125ull ;
285
+ }
286
+ }
287
+ #endif
288
+ #endif
289
+ #endif
290
+
291
+ static inline dispatch_time_t
292
+ clock_and_value_to_time (int clock, long long deadline) {
293
+ uint64_t value = time_nano2mach ((uint64_t )deadline);
294
+ if (value >= DISPATCH_TIME_MAX_VALUE) {
295
+ return DISPATCH_TIME_FOREVER;
296
+ }
297
+ switch (clock) {
298
+ case swift_clock_id_suspending:
299
+ return value;
300
+ case swift_clock_id_continuous:
301
+ return value | DISPATCH_UP_OR_MONOTONIC_TIME_MASK;
302
+ }
303
+ __builtin_unreachable ();
304
+ }
305
+
258
306
SWIFT_CC (swift)
259
307
static void swift_task_enqueueGlobalWithDeadlineImpl(long long sec,
260
308
long long nsec,
@@ -276,20 +324,31 @@ static void swift_task_enqueueGlobalWithDeadlineImpl(long long sec,
276
324
dispatchClock = DISPATCH_CLOCKID_UPTIME;
277
325
}
278
326
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 ;
327
+ dispatch_time_t when = clock_and_value_to_time (clock, deadline);
328
+
285
329
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,
330
+ uint64_t leeway = tsec * NSEC_PER_SEC + tnsec;
331
+
332
+ dispatch_source_t source =
333
+ dispatch_source_create (DISPATCH_SOURCE_TYPE_TIMER, 0 , 0 , queue);
334
+
335
+ struct __swift_job_source *jobSource =
336
+ (struct __swift_job_source *)malloc (sizeof (struct __swift_job_source ));
337
+ jobSource->job = job;
338
+ jobSource->source = source;
339
+
340
+ dispatch_set_context (source, jobSource);
341
+ dispatch_source_set_timer (source, when,
342
+ DISPATCH_TIME_FOREVER, leeway);
343
+ dispatch_source_set_event_handler_f (source,
291
344
(dispatch_function_t )&__swift_run_job_leeway);
292
- dispatch_activate (source);
345
+
346
+ dispatch_activate (source);
347
+ } else {
348
+ dispatch_function_t dispatchFunction = &__swift_run_job;
349
+ void *dispatchContext = job;
350
+ dispatch_after_f (when, queue, dispatchContext, dispatchFunction);
351
+ }
293
352
}
294
353
295
354
SWIFT_CC (swift)
0 commit comments