@@ -41,6 +41,15 @@ extern void objc_terminate(void);
41
41
#define USE_DISPATCH_SOURCE_FOR_TIMERS 0
42
42
#endif
43
43
44
+ static inline uint64_t __CFNanosecondsToTSR (uint64_t ns ) {
45
+ #if TARGET_OS_MAC || TARGET_OS_LINUX
46
+ return ns ;
47
+ #else
48
+ CFTimeInterval ti = ns / 1.0E9 ;
49
+ return __CFTimeIntervalToTSR (ti );
50
+ #endif
51
+ }
52
+
44
53
#if USE_DISPATCH_SOURCE_FOR_TIMERS
45
54
#if !TARGET_OS_MAC
46
55
typedef uint32_t mach_port_t ;
@@ -2353,10 +2362,10 @@ static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) {
2353
2362
2354
2363
if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm -> _timerHardDeadline || nextSoftDeadline != rlm -> _timerSoftDeadline )) {
2355
2364
if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED ()) {
2356
- CFRUNLOOP_NEXT_TIMER_ARMED ((unsigned long )(nextSoftDeadline - mach_absolute_time ()));
2365
+ CFRUNLOOP_NEXT_TIMER_ARMED ((unsigned long )(nextSoftDeadline - __CFNanosecondsToTSR ( mach_absolute_time () )));
2357
2366
}
2358
2367
2359
- cf_trace (KDEBUG_EVENT_CFRL_NEXT_TIMER_ARMED , rl , rlm , (nextSoftDeadline - mach_absolute_time ()), 0 );
2368
+ cf_trace (KDEBUG_EVENT_CFRL_NEXT_TIMER_ARMED , rl , rlm , (nextSoftDeadline - __CFNanosecondsToTSR ( mach_absolute_time () )), 0 );
2360
2369
#if USE_DISPATCH_SOURCE_FOR_TIMERS
2361
2370
// We're going to hand off the range of allowable timer fire date to dispatch and let it fire when appropriate for the system.
2362
2371
uint64_t leeway = __CFTSRToNanoseconds (nextHardDeadline - nextSoftDeadline );
@@ -2453,7 +2462,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
2453
2462
CFRetain (rlt );
2454
2463
__CFRunLoopTimerLock (rlt );
2455
2464
2456
- if (__CFIsValid (rlt ) && rlt -> _fireTSR <= mach_absolute_time () && !__CFRunLoopTimerIsFiring (rlt ) && rlt -> _runLoop == rl ) {
2465
+ if (__CFIsValid (rlt ) && rlt -> _fireTSR <= __CFNanosecondsToTSR ( mach_absolute_time () ) && !__CFRunLoopTimerIsFiring (rlt ) && rlt -> _runLoop == rl ) {
2457
2466
void * context_info = NULL ;
2458
2467
void (* context_release )(const void * ) = NULL ;
2459
2468
if (rlt -> _context .retain ) {
@@ -2528,7 +2537,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
2528
2537
CRSetCrashLogMessage ("A CFRunLoopTimer with an interval of 0 is set to repeat" );
2529
2538
HALT ;
2530
2539
}
2531
- uint64_t currentTSR = mach_absolute_time ();
2540
+ uint64_t currentTSR = __CFNanosecondsToTSR ( mach_absolute_time () );
2532
2541
nextFireTSR = oldFireTSR ;
2533
2542
while (nextFireTSR <= currentTSR ) {
2534
2543
nextFireTSR += intervalTSR ;
@@ -2872,7 +2881,7 @@ static void __CFRunLoopTimeout(void *arg) {
2872
2881
2873
2882
/* rl, rlm are locked on entrance and exit */
2874
2883
static int32_t __CFRunLoopRun (CFRunLoopRef rl , CFRunLoopModeRef rlm , CFTimeInterval seconds , Boolean stopAfterHandle , CFRunLoopModeRef previousMode ) {
2875
- uint64_t startTSR = mach_absolute_time ();
2884
+ uint64_t startTSR = __CFNanosecondsToTSR ( mach_absolute_time () );
2876
2885
2877
2886
if (__CFRunLoopIsStopped (rl )) {
2878
2887
__CFRunLoopUnsetStopped (rl );
@@ -3128,18 +3137,18 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3128
3137
else if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort ) {
3129
3138
CFRUNLOOP_WAKEUP_FOR_TIMER ();
3130
3139
cf_trace (KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_TIMER , rl , rlm , livePort , 0 );
3131
- if (!__CFRunLoopDoTimers (rl , rlm , mach_absolute_time ())) {
3140
+ if (!__CFRunLoopDoTimers (rl , rlm , __CFNanosecondsToTSR ( mach_absolute_time () ))) {
3132
3141
// Re-arm the next timer, because we apparently fired early
3133
3142
__CFArmNextTimerInMode (rlm , rl );
3134
3143
}
3135
3144
}
3136
3145
#endif
3137
3146
#endif
3138
- else if (rlm -> _timerPort != MACH_PORT_NULL && livePort == rlm -> _timerPort ) {
3147
+ else if (rlm -> _timerPort != CFPORT_NULL && livePort == rlm -> _timerPort ) {
3139
3148
CFRUNLOOP_WAKEUP_FOR_TIMER ();
3140
3149
// On Windows, we have observed an issue where the timer port is set before the time which we requested it to be set. For example, we set the fire time to be TSR 167646765860, but it is actually observed firing at TSR 167646764145, which is 1715 ticks early. The result is that, when __CFRunLoopDoTimers checks to see if any of the run loop timers should be firing, it appears to be 'too early' for the next timer, and no timers are handled.
3141
3150
// In this case, the timer port has been automatically reset (since it was returned from MsgWaitForMultipleObjectsEx), and if we do not re-arm it, then no timers will ever be serviced again unless something adjusts the timer list (e.g. adding or removing timers). The fix for the issue is to reset the timer here if CFRunLoopDoTimers did not handle a timer itself. 9308754
3142
- if (!__CFRunLoopDoTimers (rl , rlm , mach_absolute_time ())) {
3151
+ if (!__CFRunLoopDoTimers (rl , rlm , __CFNanosecondsToTSR ( mach_absolute_time () ))) {
3143
3152
// Re-arm the next timer
3144
3153
// Since we'll be resetting the same timer as before
3145
3154
// with the same deadlines, we need to reset these
@@ -3215,7 +3224,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3215
3224
3216
3225
if (sourceHandledThisLoop && stopAfterHandle ) {
3217
3226
retVal = kCFRunLoopRunHandledSource ;
3218
- } else if (timeout_context -> termTSR < mach_absolute_time ()) {
3227
+ } else if (timeout_context -> termTSR < __CFNanosecondsToTSR ( mach_absolute_time () )) {
3219
3228
retVal = kCFRunLoopRunTimedOut ;
3220
3229
} else if (__CFRunLoopIsStopped (rl )) {
3221
3230
__CFRunLoopUnsetStopped (rl );
@@ -4382,7 +4391,7 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime
4382
4391
memory -> _tolerance = 0.0 ;
4383
4392
if (TIMER_DATE_LIMIT < fireDate ) fireDate = TIMER_DATE_LIMIT ;
4384
4393
memory -> _nextFireDate = fireDate ;
4385
- uint64_t now2 = mach_absolute_time ();
4394
+ uint64_t now2 = __CFNanosecondsToTSR ( mach_absolute_time () );
4386
4395
CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent ();
4387
4396
if (fireDate < now1 ) {
4388
4397
memory -> _fireTSR = now2 ;
@@ -4441,7 +4450,7 @@ void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDat
4441
4450
if (!__CFIsValid (rlt )) return ;
4442
4451
if (TIMER_DATE_LIMIT < fireDate ) fireDate = TIMER_DATE_LIMIT ;
4443
4452
uint64_t nextFireTSR = 0ULL ;
4444
- uint64_t now2 = mach_absolute_time ();
4453
+ uint64_t now2 = __CFNanosecondsToTSR ( mach_absolute_time () );
4445
4454
CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent ();
4446
4455
if (fireDate < now1 ) {
4447
4456
nextFireTSR = now2 ;
0 commit comments