]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix wall time computation in macOS High Sierra
authorGiovanni Bajo <rasky@develer.com>
Sat, 30 Sep 2017 09:44:21 +0000 (11:44 +0200)
committerIan Lance Taylor <iant@golang.org>
Tue, 3 Oct 2017 20:33:29 +0000 (20:33 +0000)
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>
src/runtime/sys_darwin_amd64.s

index ea21ffdd37813781c69c5933b15a35346aab0a0b..e8ae6fac4f4242909c1310354ced3df53c825215 100644 (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: