Description
Previous ID | SR-14288 |
Radar | rdar://problem/74876063 |
Original Reporter | 3405691582 (JIRA User) |
Type | Bug |
Additional Detail from JIRA
Votes | 0 |
Component/s | Foundation |
Labels | Bug |
Assignee | None |
Priority | Medium |
md5: 5562f0c8b2baa9b93e8beb0f428cabc4
Issue Description:
There are several assumptions in CFRunLoop that assume that the units obtained from mach_absolute_time()
and __CFTimeIntervalToTSR are commensurate.
mach_absolute_time()
, on non-Windows platforms, is the value of CLOCK_MONOTONIC
converted into nanosecond units.
In CFDate.c
, when clock_getres
indicates that CLOCK_MONOTONIC
has 1 ns resolution, __CFTSRRate is 1000000000 (the number of nanoseconds in 1 second). __CFTimeIntervalToTSR multiplies the CFTimeInterval
– which is a double
of fractional seconds – by __CFTSRRate. In other words, when __CFTSRRate is 1000000000, __CFTimeIntervalToTSR essentially converts fractional seconds to nanoseconds, and TSR units are identical to nanosecond units.
However, if clock_getres
indicates that CLOCK_MONOTONIC
has greater than 1 ns resolution, this no longer holds. __CFTSRRate will be set to that resolution multiplied by 1000000000. In this case, this means __CFTimeIntervalToTSR multiplies fractional seconds by the granularity and 1000000000. TSR units now are not equal to nanosecond units.
For example, with a 41 ns
CLOCK_MONOTONIC
resolution, __CFTimeIntervalToTSR is 41000000000 TSR units.CFRunLoopTimerCreate
sets _fireTSR by addingmach_absolute_time()
to the duration of the timer converted to TSR units with __CFTimeIntervalToTSR(). With a 0.5 second timer, this is 20500000000 TSR units, but this is added directly tomach_absolute_time()
resulting in a _fireTSR equivalent to 20.5 seconds in the future and not 0.5 seconds.
Therefore, performing arithmetic with mach_absolute_time()
and TSR units is incorrect as currently written.
It is a simple task to write a __CFNanosecondsToTSR that returns its input on platforms with a 1ns clock resolution, and otherwise converts the nanosecond input to a CFTimeInterval
before converting with __CFTimeIntervalToTSR.
However, it is not quite obvious that the TSR calculations in CFDate.c
are what is necessarily intended. If, for example, I want to know how many CLOCK_MONOTONIC
ticks are in a given number seconds, I want to convert this to nanoseconds, then divide by the resolution to get clock-granular units.
For example, with a granularity of 41 ns, 0.5 seconds is 500000000 ns, so this is 12195121.9512 clock-granular units.
This isn't how clock-granular units are actually used in CFRunLoop
, in the alternative, it may instead be reasonable to instead remove the clock_getres
calculations altogether and instead treat TSR units as synonymous to nanosecond conversions for the purposes of this module; indeed, TSR units are only publicly used in CFRunLoop
.