Skip to content
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

Closed
quentinmit opened this issue Oct 26, 2016 · 10 comments
Closed

runtime: use mach_absolute_time for runtime.nanotime #17610

quentinmit opened this issue Oct 26, 2016 · 10 comments

Comments

@quentinmit
Copy link
Contributor

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 both mach_absolute_time and gettimeofday 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.

@quentinmit quentinmit added this to the Go1.9Early milestone Oct 26, 2016
@aclements
Copy link
Member

aclements commented Oct 31, 2016

I flipped through the other OSs. A few others use wall-clock time, as well:

  • Solaris uses clock_gettime(CLOCK_REALTIME). If the internet rumors are true, Solaris doesn't have CLOCK_MONOTONIC. We should perhaps use gethrtime on Solaris.
  • NetBSD uses clock_gettime(CLOCK_REALTIME). As far as I can tell, CLOCK_MONOTONIC is available and we should use it.
  • NaCl and Plan9, but there's probably nothing we can do about these.

@ianlancetaylor
Copy link
Member

At least Solaris version 12 does have CLOCK_MONOTONIC. It is documented as CLOCK_HIGHRES, but CLOCK_MONOTONIC is defined in <time.h> to the same value as CLOCK_HIGHRES and CLOCK_HIGHRES is defined by the man page to be monotonic.

@namsral
Copy link
Contributor

namsral commented Jan 11, 2017

FYI clock_gettime was introduced in September 2016 with the release of macOS 10.12 (Sierra)

@minux
Copy link
Member

minux commented Jan 11, 2017 via email

@bradfitz
Copy link
Contributor

@minux, we can use it when available.

@minux
Copy link
Member

minux commented Jan 11, 2017 via email

@namsral
Copy link
Contributor

namsral commented Jan 12, 2017

Using mach_timebase_info you can convert Mach absolute time to nanoseconds:

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

@minux
Copy link
Member

minux commented Jan 12, 2017 via email

@namsral
Copy link
Contributor

namsral commented Jan 16, 2017

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.

@gopherbot
Copy link
Contributor

CL https://golang.org/cl/35292 mentions this issue.

@golang golang locked and limited conversation to collaborators Feb 2, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants