-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
runtime: use mach_absolute_time for runtime.nanotime #17610
Comments
I flipped through the other OSs. A few others use wall-clock time, as well:
|
At least Solaris version 12 does have |
FYI |
It will be some time before we can drop support for all pre-10.12 OS X
versions, so I'm afraid we can't rely on 10.12-only syscalls now.
|
@minux, we can use it when available. |
But mach_absolute_time is available everywhere. The only problem is that I
don't know if its Mach absolute time unit changes dynamically (in the
lifetime of a process) or not.
note, AbsoluteToNanosecond is deprecated, but we can use
absolutetime_to_nanosecond instead. However, we still need to figure out
how to reimplement its functionality in Go. I'm hoping it doesn't require
kernel specific memory accesses.
|
Using mach_timebase_info_data_t info;
mach_timebase_info(&info);
uint64_t start = mach_absolute_time();
usleep(2000000);
uint64_t duration = mach_absolute_time() - start;
// Convert to nanoseconds
duration = duration * info.numer / info.denom;
printf("%lld ns\n", (long long) duration); From developer.apple.com |
mach_absolute_time is using rdtsc with some kernel provided magic numbers
from comm page.
// from xnu-3248.60.11.1.2~2
_mach_absolute_time:
00007fff5fc25726 pushq %rbp
00007fff5fc25727 movq %rsp, %rbp
00007fff5fc2572a movabsq $0x7fffffe00050, %rsi ## imm =
0x7FFFFFE00050
00007fff5fc25734 movl 0x18(%rsi), %r8d
00007fff5fc25738 testl %r8d, %r8d
00007fff5fc2573b je 0x7fff5fc25734
00007fff5fc2573d lfence
00007fff5fc25740 rdtsc
00007fff5fc25742 lfence
00007fff5fc25745 shlq $0x20, %rdx
00007fff5fc25749 orq %rdx, %rax
00007fff5fc2574c movl 0xc(%rsi), %ecx
00007fff5fc2574f andl $0x1f, %ecx
00007fff5fc25752 subq (%rsi), %rax
00007fff5fc25755 shlq %cl, %rax
00007fff5fc25758 movl 0x8(%rsi), %ecx
00007fff5fc2575b mulq %rcx
00007fff5fc2575e shrdq $0x20, %rdx, %rax
00007fff5fc25763 addq 0x10(%rsi), %rax
00007fff5fc25767 cmpl 0x18(%rsi), %r8d
00007fff5fc2576b jne 0x7fff5fc25734
00007fff5fc2576d popq %rbp
00007fff5fc2576e retq
00007fff5fc2576f nop
I think it's the same as our current runtime.nanotime implementation.
|
My nanotime replacement to support monototic nanoseconds: TEXT runtime·nanotime(SB), NOSPLIT, $32
MOVQ $0x7fffffe00000, SI // comm page base
timeloop:
MOVL nt_generation(SI), R8
TESTL R8, R8
JZ timeloop
RDTSC
SHLQ $32, DX
ORQ DX, AX
MOVL nt_shift(SI), CX
SUBQ nt_tsc_base(SI), AX
SHLQ CX, AX
MOVL nt_scale(SI), CX
MULQ CX
SHRQ $32, AX:DX
ADDQ nt_ns_base(SI), AX
CMPL nt_generation(SI), R8
JNE timeloop
MOVQ AX, ret+0(FP)
RET The algorithm is based on xnu's mach_absolute_time and works on Intel Macs. My intention is to follow Go's contributions guidelines next. |
CL https://golang.org/cl/35292 mentions this issue. |
runtime.nanotime currently returns wallclock time, which means timers do not function correctly in the presence of NTP. We should use
mach_absolute_time
instead, which returns a monotonic nanoseconds-since-boot timer. (Officially, it returns time in "absolute time units" and you have to multiply by a constant to get nanoseconds. But the implementation of bothmach_absolute_time
andgettimeofday
assume/document that it's really nanoseconds...)This has the bonus of being much simpler than gettimeofday, so it will also reduce our chances of being hit by a change in the kernel ABI.
Targeting 1.9 because this seems too dangerous for 1.8.
The text was updated successfully, but these errors were encountered: