Skip to content

Commit

Permalink
Fix underlying time source for Time.nanos() on macOS (#3921)
Browse files Browse the repository at this point in the history
  • Loading branch information
ergl authored Nov 13, 2021
1 parent 1521dd2 commit 9ef833a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
6 changes: 6 additions & 0 deletions .release-notes/clock_uptime_raw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Fix underlying time source for Time.nanos() on macOS

Previously, we were using `mach_absolute_time` on macOS to get the number of ticks since boot, with the assumption that ticks increment at nanosecond intervals. However, as noted by [Apple](https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code#Apply-Timebase-Information-to-Mach-Absolute-Time-Values), this assumption is flawed on Apple Silicon, and will also affect any binaries that were built on Intel, as the Rosetta 2 translator will not apply any time conversion.

The recommended replacement to `mach_absolute_time` is to use `clock_gettime_nsec_np` with a clock of type `CLOCK_UPTIME_RAW`.

16 changes: 12 additions & 4 deletions packages/time/time.pony
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use @clock_gettime[I32](clock: U32, ts: Pointer[(I64, I64)])
if lp64 and (linux or bsd)
use @clock_gettime[I32](clock: U32, ts: Pointer[(I32, I32)])
if ilp32 and (linux or bsd)
use @mach_absolute_time[U64]() if osx
use @clock_gettime_nsec_np[U64](clock: U32) if osx
use @gettimeofday[I32](tp: Pointer[(I64, I64)], tzp: Pointer[None])
if osx
use @GetSystemTimeAsFileTime[None](times_as_file_time: Pointer[(U32, U32)])
Expand Down Expand Up @@ -43,6 +43,14 @@ primitive _ClockMonotonic
compile_error "no clock_gettime monotonic clock"
end

primitive _ClockUptimeRaw
fun apply(): U32 =>
ifdef osx then
8
else
compile_error "no clock_gettime_nsec_np uptime raw clock"
end

primitive Time
"""
A collection of ways to fetch the current time.
Expand Down Expand Up @@ -81,7 +89,7 @@ primitive Time
Monotonic unadjusted milliseconds.
"""
ifdef osx then
@mach_absolute_time() / 1000000
@clock_gettime_nsec_np(_ClockUptimeRaw()) / 1000000
elseif linux or bsd then
var ts = _clock_gettime(_ClockMonotonic)
((ts._1 * 1000) + (ts._2 / 1000000)).u64()
Expand All @@ -97,7 +105,7 @@ primitive Time
Monotonic unadjusted microseconds.
"""
ifdef osx then
@mach_absolute_time() / 1000
@clock_gettime_nsec_np(_ClockUptimeRaw()) / 1000
elseif linux or bsd then
var ts = _clock_gettime(_ClockMonotonic)
((ts._1 * 1000000) + (ts._2 / 1000)).u64()
Expand All @@ -113,7 +121,7 @@ primitive Time
Monotonic unadjusted nanoseconds.
"""
ifdef osx then
@mach_absolute_time()
@clock_gettime_nsec_np(_ClockUptimeRaw())
elseif linux or bsd then
var ts = _clock_gettime(_ClockMonotonic)
((ts._1 * 1000000000) + ts._2).u64()
Expand Down

0 comments on commit 9ef833a

Please sign in to comment.