@@ -45,6 +45,15 @@ extern void objc_terminate(void);
45
45
#define USE_DISPATCH_SOURCE_FOR_TIMERS 0
46
46
#endif
47
47
48
+ static inline uint64_t __CFNanosecondsToTSR (uint64_t ns ) {
49
+ #if TARGET_OS_MAC || TARGET_OS_LINUX
50
+ return ns ;
51
+ #else
52
+ CFTimeInterval ti = ns / 1.0E9 ;
53
+ return __CFTimeIntervalToTSR (ti );
54
+ #endif
55
+ }
56
+
48
57
#if USE_DISPATCH_SOURCE_FOR_TIMERS
49
58
#if !TARGET_OS_MAC
50
59
typedef uint32_t mach_port_t ;
@@ -2396,10 +2405,10 @@ static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) {
2396
2405
2397
2406
if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm -> _timerHardDeadline || nextSoftDeadline != rlm -> _timerSoftDeadline )) {
2398
2407
if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED ()) {
2399
- CFRUNLOOP_NEXT_TIMER_ARMED ((unsigned long )(nextSoftDeadline - mach_absolute_time ()));
2408
+ CFRUNLOOP_NEXT_TIMER_ARMED ((unsigned long )(nextSoftDeadline - __CFNanosecondsToTSR ( mach_absolute_time () )));
2400
2409
}
2401
2410
2402
- cf_trace (KDEBUG_EVENT_CFRL_NEXT_TIMER_ARMED , rl , rlm , (nextSoftDeadline - mach_absolute_time ()), 0 );
2411
+ cf_trace (KDEBUG_EVENT_CFRL_NEXT_TIMER_ARMED , rl , rlm , (nextSoftDeadline - __CFNanosecondsToTSR ( mach_absolute_time () )), 0 );
2403
2412
#if USE_DISPATCH_SOURCE_FOR_TIMERS
2404
2413
// We're going to hand off the range of allowable timer fire date to dispatch and let it fire when appropriate for the system.
2405
2414
uint64_t leeway = __CFTSRToNanoseconds (nextHardDeadline - nextSoftDeadline );
@@ -2496,7 +2505,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
2496
2505
CFRetain (rlt );
2497
2506
__CFRunLoopTimerLock (rlt );
2498
2507
2499
- if (__CFIsValid (rlt ) && rlt -> _fireTSR <= mach_absolute_time () && !__CFRunLoopTimerIsFiring (rlt ) && rlt -> _runLoop == rl ) {
2508
+ if (__CFIsValid (rlt ) && rlt -> _fireTSR <= __CFNanosecondsToTSR ( mach_absolute_time () ) && !__CFRunLoopTimerIsFiring (rlt ) && rlt -> _runLoop == rl ) {
2500
2509
void * context_info = NULL ;
2501
2510
void (* context_release )(const void * ) = NULL ;
2502
2511
if (rlt -> _context .retain ) {
@@ -2573,7 +2582,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
2573
2582
CRSetCrashLogMessage ("A CFRunLoopTimer with an interval of 0 is set to repeat" );
2574
2583
HALT ;
2575
2584
}
2576
- uint64_t currentTSR = mach_absolute_time ();
2585
+ uint64_t currentTSR = __CFNanosecondsToTSR ( mach_absolute_time () );
2577
2586
nextFireTSR = oldFireTSR ;
2578
2587
while (nextFireTSR <= currentTSR ) {
2579
2588
nextFireTSR += intervalTSR ;
@@ -2917,7 +2926,7 @@ static Boolean __CFRunLoopWaitForMultipleObjects(__CFPortSet portSet, HANDLE *on
2917
2926
2918
2927
/* rl, rlm are locked on entrance and exit */
2919
2928
static int32_t __CFRunLoopRun (CFRunLoopRef rl , CFRunLoopModeRef rlm , CFTimeInterval seconds , Boolean stopAfterHandle , CFRunLoopModeRef previousMode ) {
2920
- uint64_t startTSR = mach_absolute_time ();
2929
+ uint64_t startTSR = __CFNanosecondsToTSR ( mach_absolute_time () );
2921
2930
2922
2931
if (__CFRunLoopIsStopped (rl )) {
2923
2932
__CFRunLoopUnsetStopped (rl );
@@ -3174,7 +3183,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3174
3183
else if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort ) {
3175
3184
CFRUNLOOP_WAKEUP_FOR_TIMER ();
3176
3185
cf_trace (KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_TIMER , rl , rlm , livePort , 0 );
3177
- if (!__CFRunLoopDoTimers (rl , rlm , mach_absolute_time ())) {
3186
+ if (!__CFRunLoopDoTimers (rl , rlm , __CFNanosecondsToTSR ( mach_absolute_time () ))) {
3178
3187
// Re-arm the next timer, because we apparently fired early
3179
3188
__CFArmNextTimerInMode (rlm , rl );
3180
3189
}
@@ -3184,7 +3193,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3184
3193
CFRUNLOOP_WAKEUP_FOR_TIMER ();
3185
3194
// 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.
3186
3195
// 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
3187
- if (!__CFRunLoopDoTimers (rl , rlm , mach_absolute_time ())) {
3196
+ if (!__CFRunLoopDoTimers (rl , rlm , __CFNanosecondsToTSR ( mach_absolute_time () ))) {
3188
3197
// Re-arm the next timer
3189
3198
// Since we'll be resetting the same timer as before
3190
3199
// with the same deadlines, we need to reset these
@@ -3258,7 +3267,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3258
3267
3259
3268
if (sourceHandledThisLoop && stopAfterHandle ) {
3260
3269
retVal = kCFRunLoopRunHandledSource ;
3261
- } else if (termTSR < mach_absolute_time ()) {
3270
+ } else if (termTSR < __CFNanosecondsToTSR ( mach_absolute_time () )) {
3262
3271
retVal = kCFRunLoopRunTimedOut ;
3263
3272
} else if (__CFRunLoopIsStopped (rl )) {
3264
3273
__CFRunLoopUnsetStopped (rl );
@@ -4515,7 +4524,7 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime
4515
4524
memory -> _tolerance = 0.0 ;
4516
4525
if (TIMER_DATE_LIMIT < fireDate ) fireDate = TIMER_DATE_LIMIT ;
4517
4526
memory -> _nextFireDate = fireDate ;
4518
- uint64_t now2 = mach_absolute_time ();
4527
+ uint64_t now2 = __CFNanosecondsToTSR ( mach_absolute_time () );
4519
4528
CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent ();
4520
4529
if (fireDate < now1 ) {
4521
4530
memory -> _fireTSR = now2 ;
@@ -4575,7 +4584,7 @@ void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDat
4575
4584
if (!__CFIsValid (rlt )) return ;
4576
4585
if (TIMER_DATE_LIMIT < fireDate ) fireDate = TIMER_DATE_LIMIT ;
4577
4586
uint64_t nextFireTSR = 0ULL ;
4578
- uint64_t now2 = mach_absolute_time ();
4587
+ uint64_t now2 = __CFNanosecondsToTSR ( mach_absolute_time () );
4579
4588
CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent ();
4580
4589
if (fireDate < now1 ) {
4581
4590
nextFireTSR = now2 ;
0 commit comments