1
0
mirror of https://github.com/golang/go synced 2024-11-19 14:04:46 -07:00

runtime: fix wall time computation in macOS High Sierra

Latest macOS High Sierra changed how the wall time information
is exported into the commpage. Backward compatibility was partly
preserved, that is previous Go versions are basically forced to
go through a syscall which is much slower and is not able to
get nanosecond precision.

Implement the new commpage layout and wall time computation,
using a version check to fallback to the previous code on
older operating systems.

Fixes #22037

Change-Id: I8c2176eaca83a5d7be23443946a6b4c653ec7f68
Reviewed-on: https://go-review.googlesource.com/67332
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Giovanni Bajo 2017-09-30 11:44:21 +02:00 committed by Ian Lance Taylor
parent b78bce08e3
commit d8ff3d5920

View File

@ -107,15 +107,24 @@ TEXT runtime·madvise(SB), NOSPLIT, $0
RET
// OS X comm page time offsets
// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
// https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h
#define commpage_version 0x1e
#define v12_nt_tsc_base 0x50
#define v12_nt_scale 0x58
#define v12_nt_shift 0x5c
#define v12_nt_ns_base 0x60
#define v12_nt_generation 0x68
#define v12_gtod_generation 0x6c
#define v12_gtod_ns_base 0x70
#define v12_gtod_sec_base 0x78
#define v12_gtod_generation 0x6c // obsolete since High Sierra (v13)
#define v12_gtod_ns_base 0x70 // obsolete since High Sierra (v13)
#define v12_gtod_sec_base 0x78 // obsolete since High Sierra (v13)
#define v13_gtod_ns_base 0xd0
#define v13_gtod_sec_ofs 0xd8
#define v13_gtod_frac_ofs 0xe0
#define v13_gtod_scale 0xe8
#define v13_gtod_tkspersec 0xf0
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
MOVQ $0x7fffffe00000, BP /* comm page base */
@ -151,6 +160,75 @@ TEXT time·now(SB), NOSPLIT, $32-24
// are used in the systime fallback, as the timeval address
// filled in by the system call.
MOVQ $0x7fffffe00000, BP /* comm page base */
CMPW commpage_version(BP), $13
JB v12 /* sierra and older */
// This is the new code, for macOS High Sierra (v13) and newer.
v13:
// Loop trying to take a consistent snapshot
// of the time parameters.
timeloop13:
MOVQ v13_gtod_ns_base(BP), R12
MOVL v12_nt_generation(BP), CX
TESTL CX, CX
JZ timeloop13
RDTSC
MOVQ v12_nt_tsc_base(BP), SI
MOVL v12_nt_scale(BP), DI
MOVQ v12_nt_ns_base(BP), BX
CMPL v12_nt_generation(BP), CX
JNE timeloop13
MOVQ v13_gtod_sec_ofs(BP), R8
MOVQ v13_gtod_frac_ofs(BP), R9
MOVQ v13_gtod_scale(BP), R10
MOVQ v13_gtod_tkspersec(BP), R11
CMPQ v13_gtod_ns_base(BP), R12
JNE timeloop13
// Compute monotonic time
// mono = ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base
// The multiply and shift extracts the top 64 bits of the 96-bit product.
SHLQ $32, DX
ADDQ DX, AX
SUBQ SI, AX
MULQ DI
SHRQ $32, AX:DX
ADDQ BX, AX
// Subtract startNano base to return the monotonic runtime timer
// which is an offset from process boot.
MOVQ AX, BX
MOVQ runtime·startNano(SB), CX
SUBQ CX, BX
MOVQ BX, monotonic+16(FP)
// Now compute the 128-bit wall time:
// wall = ((mono - gtod_ns_base) * gtod_scale) + gtod_offs
// The parameters are updated every second, so if we found them
// outdated (that is, more than one second is passed from the ns base),
// fallback to the syscall.
TESTQ R12, R12
JZ systime
SUBQ R12, AX
CMPQ R11, AX
JB systime
MULQ R10
ADDQ R9, AX
ADCQ R8, DX
// Convert the 128-bit wall time into (sec,nsec).
// High part (seconds) is already good to go, while low part
// (fraction of seconds) must be converted to nanoseconds.
MOVQ DX, sec+0(FP)
MOVQ $1000000000, CX
MULQ CX
MOVQ DX, nsec+8(FP)
RET
// This is the legacy code needed for macOS Sierra (v12) and older.
v12:
// Loop trying to take a consistent snapshot
// of the time parameters.
timeloop: