4 ms·
It was added some years ago, and I believe mach_absolute_time is actually now implemented in terms of (the implementation of) clock_gettime. The documentation o
by lilyball 6y ago
It was added some years ago, and I believe mach_absolute_time is actually now implemented in terms of (the implementation of) clock_gettime. The documentation on mach_absolute_time now even says you should use clock_gettime_nsec_np(CLOCK_UPTIME_RAW) instead.
macOS also has clock constants for a monotonic clock that increases while sleeping (unlike CLOCK_UPTIME_RAW and mach_absolute_time).
- saagarjha 6y agoNot yet, at least :) _mach_absolute_time: 00000000000012ec pushq %rbp 00000000000012ed movq %rsp, %rbp 00000000000012f0 movabsq $0x7fffffe00050, %rsi ## imm = 0x7FFFFFE00050 00000000000012fa movl 0x18(%rsi), %r8d 00000000000012fe testl %r8d, %r8d 0000000000001301 je 0x12fa 0000000000001303 lfence 0000000000001306 rdtsc 0000000000001308 lfence 000000000000130b shlq $0x20, %rdx 000000000000130f orq %rdx, %rax 0000000000001312 movl 0xc(%rsi), %ecx 0000000000001315 andl $0x1f, %ecx 0000000000001318 subq (%rsi), %rax 000000000000131b shlq %cl, %rax 000000000000131e movl 0x8(%rsi), %ecx 0000000000001321 mulq %rcx 0000000000001324 shrdq $0x20, %rdx, %rax 0000000000001329 addq 0x10(%rsi), %rax 000000000000132d cmpl 0x18(%rsi), %r8d 0000000000001331 jne 0x12fa 0000000000001333 popq %rbp 0000000000001334 retq
- Skunkleton 6y agoThat may be the result of inlining clock_gettime, though that would imply a pretty different implementation from the one I am familiar with. AFAIR on x86 a locked rdtsc is ~20 cycles. So to answer the gp question, it has around a precision in the few nanoseconds range. Accuracy is a different question, IE compare numbers from the same die, but be a little more suspicious across dies. No clue how this is implemented on the M1, or if the M1 has the same modern tsc guarantees that x86 has grown over the last few generations of chips.
- saagarjha 6y agoYeah, clock_gettime is somewhat more complicated than this. If anything, it might have an inlined mach_absolute_time in it…
- lilyball 6y agoI was actually misremembering a bit. Sufficiently old versions of mach_absolute_time used a function called clock_get_time() on i386 (if the COMM_PAGE_VERSION was not 1). This changed in macOS 10.5 to a tiny bit of assembly that just read from _COMM_PAGE_NANOTIME on i386/x86_64/ppc (the arm implementation(!!) triggers a software interrupt). The i386/x86_64/ppc definitions were also copied into xnu. For the next few years it kind of bounced back and forth between libc and xnu, and the routine was complicated by adding timebase conversion as needed. And at some point arm support was added back (it vanished when it first went to xnu), but this time using the commpage if possible. As for M1, I assume it's using the arm64 routine in xnu, which can be found at https://opensource.apple.com/source/xnu/xnu-7195.50.7.100.1/libsyscall/wrappers/mach_absolute_time.s https://opensource.apple.com/source/xnu/xnu-7195.50.7.100.1/.... As for clock_gettime_nsec_np(), at least as of Big Sur, it's in libc¹ instead of xnu and defers to mach_continuous_time()/mach_continuous_approximate_time()/mach_absolute_time()/mach_approximate_time() for the CLOCK__RAW[_] clocks. And clock_gettime() for those clocks is implemented in terms of clock_gettime_nsec_np(). ¹https://opensource.apple.com/source/Libc/Libc-1439.40.11/gen/clock_gettime.c.auto.html https://opensource.apple.com/source/Libc/Libc-1439.40.11/gen...
- vlovich123 6y agoI was part of the team that really pushed the kernel team to add support for a monotonic clock that counts while sleeping (this had been a persistent ask before just not prioritized). We got it in for iOS 8 or 9. The dance you otherwise have to do is not only complicated in userspace on MacOS, it's expensive & full of footguns due to race conditions (& requires changing the clock basis for your entire app if I recall correctly).
- lilyball 6y agoDo you have any insight as to why libdispatch added support for this new clock internally (in the last year or two), but did not expose it in any public API? In C I can manually construct a dispatch_time_t that will use make libdispatch use CLOCK_MONOTONIC_RAW¹, if I'm willing to make assumptions about the format of dispatch_time_t² (despite libdispatch warning that the internal format is subject to change³). And I can't even do this in Swift. It would be really useful to have this functionality, so I'm mystified as to why it's hidden. ¹Technically it uses mach_continuous_time() first if available (which appears to be equivalent to CLOCK_MONOTONIC_RAW), then clock_gettime(CLOCK_BOOTTIME, &ts) on Linux, then clock_gettime(CLOCK_MONOTONIC, &ts), then some other API for Windows. ²Conveniently enough the value that is equivalent to DISPATCH_TIME_NOW using the monotonic clock is just INT64_MIN, at least in the current encoding. ³Swift makes assumptions about the internal format of dispatch_time_t so I don't know if it actually can meaningfully change. Newer versions of Swift now use stdlib on the system, but any app built with a sufficiently old version of Swift still embeds its own copy of the stdlib. Granted, additions (like the monotonic clock) should be fine, as the Swift API does not actually bridge from dispatch_time_t so it only ends up representing times it has APIs to construct. Since it doesn't have APIs to construct monotonic times, they won't break it.
- vlovich123 6y agoI haven't worked at Apple in almost 5 years so I can't speak to more recent developments unfortunately. libdispatch integration may be trickier & have implementation details not suitable for a public API. Specifically if I recall correctly the internal representation of time only allowed for 2 formats (wallclock vs monotonic). I suspect adding other types of clocks could pose back/forward compat challenges. However, this is a wild shot in the dark & I didn't really look into the internals of libdispatch. Maybe ask on their github page? Generally upgrading a private API to public is a lot of work & goes through a lot of review (having monitored that mailing list & added 1 API during my time there). So if there's a private API probably some team at Apple needed it to deliver a feature but the maintainers were not confident the specific solution they chose generalized well & either requires some work or something else.