@@ -48,6 +48,15 @@ extern void objc_terminate(void);
48
48
#define USE_DISPATCH_SOURCE_FOR_TIMERS 0
49
49
#endif
50
50
51
+ static inline uint64_t __CFNanosecondsToTSR (uint64_t ns ) {
52
+ #if TARGET_OS_MAC || TARGET_OS_LINUX
53
+ return ns ;
54
+ #else
55
+ CFTimeInterval ti = ns / 1.0E9 ;
56
+ return __CFTimeIntervalToTSR (ti );
57
+ #endif
58
+ }
59
+
51
60
#if USE_DISPATCH_SOURCE_FOR_TIMERS
52
61
#if !TARGET_OS_MAC
53
62
typedef uint32_t mach_port_t ;
@@ -2399,10 +2408,10 @@ static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) {
2399
2408
2400
2409
if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm -> _timerHardDeadline || nextSoftDeadline != rlm -> _timerSoftDeadline )) {
2401
2410
if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED ()) {
2402
- CFRUNLOOP_NEXT_TIMER_ARMED ((unsigned long )(nextSoftDeadline - mach_absolute_time ()));
2411
+ CFRUNLOOP_NEXT_TIMER_ARMED ((unsigned long )(nextSoftDeadline - __CFNanosecondsToTSR ( mach_absolute_time () )));
2403
2412
}
2404
2413
2405
- cf_trace (KDEBUG_EVENT_CFRL_NEXT_TIMER_ARMED , rl , rlm , (nextSoftDeadline - mach_absolute_time ()), 0 );
2414
+ cf_trace (KDEBUG_EVENT_CFRL_NEXT_TIMER_ARMED , rl , rlm , (nextSoftDeadline - __CFNanosecondsToTSR ( mach_absolute_time () )), 0 );
2406
2415
#if USE_DISPATCH_SOURCE_FOR_TIMERS
2407
2416
// We're going to hand off the range of allowable timer fire date to dispatch and let it fire when appropriate for the system.
2408
2417
uint64_t leeway = __CFTSRToNanoseconds (nextHardDeadline - nextSoftDeadline );
@@ -2499,7 +2508,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
2499
2508
CFRetain (rlt );
2500
2509
__CFRunLoopTimerLock (rlt );
2501
2510
2502
- if (__CFIsValid (rlt ) && rlt -> _fireTSR <= mach_absolute_time () && !__CFRunLoopTimerIsFiring (rlt ) && rlt -> _runLoop == rl ) {
2511
+ if (__CFIsValid (rlt ) && rlt -> _fireTSR <= __CFNanosecondsToTSR ( mach_absolute_time () ) && !__CFRunLoopTimerIsFiring (rlt ) && rlt -> _runLoop == rl ) {
2503
2512
void * context_info = NULL ;
2504
2513
void (* context_release )(const void * ) = NULL ;
2505
2514
if (rlt -> _context .retain ) {
@@ -2576,7 +2585,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
2576
2585
CRSetCrashLogMessage ("A CFRunLoopTimer with an interval of 0 is set to repeat" );
2577
2586
HALT ;
2578
2587
}
2579
- uint64_t currentTSR = mach_absolute_time ();
2588
+ uint64_t currentTSR = __CFNanosecondsToTSR ( mach_absolute_time () );
2580
2589
nextFireTSR = oldFireTSR ;
2581
2590
while (nextFireTSR <= currentTSR ) {
2582
2591
nextFireTSR += intervalTSR ;
@@ -2920,7 +2929,7 @@ static Boolean __CFRunLoopWaitForMultipleObjects(__CFPortSet portSet, HANDLE *on
2920
2929
2921
2930
/* rl, rlm are locked on entrance and exit */
2922
2931
static int32_t __CFRunLoopRun (CFRunLoopRef rl , CFRunLoopModeRef rlm , CFTimeInterval seconds , Boolean stopAfterHandle , CFRunLoopModeRef previousMode ) {
2923
- uint64_t startTSR = mach_absolute_time ();
2932
+ uint64_t startTSR = __CFNanosecondsToTSR ( mach_absolute_time () );
2924
2933
2925
2934
if (__CFRunLoopIsStopped (rl )) {
2926
2935
__CFRunLoopUnsetStopped (rl );
@@ -3177,7 +3186,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3177
3186
else if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort ) {
3178
3187
CFRUNLOOP_WAKEUP_FOR_TIMER ();
3179
3188
cf_trace (KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_TIMER , rl , rlm , livePort , 0 );
3180
- if (!__CFRunLoopDoTimers (rl , rlm , mach_absolute_time ())) {
3189
+ if (!__CFRunLoopDoTimers (rl , rlm , __CFNanosecondsToTSR ( mach_absolute_time () ))) {
3181
3190
// Re-arm the next timer, because we apparently fired early
3182
3191
__CFArmNextTimerInMode (rlm , rl );
3183
3192
}
@@ -3187,7 +3196,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3187
3196
CFRUNLOOP_WAKEUP_FOR_TIMER ();
3188
3197
// 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.
3189
3198
// 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
3190
- if (!__CFRunLoopDoTimers (rl , rlm , mach_absolute_time ())) {
3199
+ if (!__CFRunLoopDoTimers (rl , rlm , __CFNanosecondsToTSR ( mach_absolute_time () ))) {
3191
3200
// Re-arm the next timer
3192
3201
// Since we'll be resetting the same timer as before
3193
3202
// with the same deadlines, we need to reset these
@@ -3261,7 +3270,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
3261
3270
3262
3271
if (sourceHandledThisLoop && stopAfterHandle ) {
3263
3272
retVal = kCFRunLoopRunHandledSource ;
3264
- } else if (termTSR < mach_absolute_time ()) {
3273
+ } else if (termTSR < __CFNanosecondsToTSR ( mach_absolute_time () )) {
3265
3274
retVal = kCFRunLoopRunTimedOut ;
3266
3275
} else if (__CFRunLoopIsStopped (rl )) {
3267
3276
__CFRunLoopUnsetStopped (rl );
@@ -4518,7 +4527,7 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime
4518
4527
memory -> _tolerance = 0.0 ;
4519
4528
if (TIMER_DATE_LIMIT < fireDate ) fireDate = TIMER_DATE_LIMIT ;
4520
4529
memory -> _nextFireDate = fireDate ;
4521
- uint64_t now2 = mach_absolute_time ();
4530
+ uint64_t now2 = __CFNanosecondsToTSR ( mach_absolute_time () );
4522
4531
CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent ();
4523
4532
if (fireDate < now1 ) {
4524
4533
memory -> _fireTSR = now2 ;
@@ -4578,7 +4587,7 @@ void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDat
4578
4587
if (!__CFIsValid (rlt )) return ;
4579
4588
if (TIMER_DATE_LIMIT < fireDate ) fireDate = TIMER_DATE_LIMIT ;
4580
4589
uint64_t nextFireTSR = 0ULL ;
4581
- uint64_t now2 = mach_absolute_time ();
4590
+ uint64_t now2 = __CFNanosecondsToTSR ( mach_absolute_time () );
4582
4591
CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent ();
4583
4592
if (fireDate < now1 ) {
4584
4593
nextFireTSR = now2 ;
0 commit comments