From 2d6f941e8c380a0a37ade918dd76e652542e28ef Mon Sep 17 00:00:00 2001 From: Giovanni Bajo Date: Sat, 13 Jan 2018 02:22:05 +0100 Subject: [PATCH] runtime: fix time.Now on Sierra and older CL 67332 created the fast no-syscall path for time.Now in High Sierra but managed to break Sierra and older by forcing them into the slow syscall path: the version check based on commpage version was wrong. This CL uses the Darwin version number instead. The assembly diff is noisy because many variables had to be renamed, but the only actual change is the version check. Fixes #23419. Change-Id: Ie31ef5fb88f66d1517a8693942a7fb6100c213b0 Reviewed-on: https://go-review.googlesource.com/87655 Run-TryBot: Giovanni Bajo TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/runtime/os_darwin.go | 29 ++++++++-- src/runtime/sys_darwin_amd64.s | 102 ++++++++++++++++----------------- 2 files changed, 75 insertions(+), 56 deletions(-) diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 4ab5a76373..580dffa1a3 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -11,6 +11,8 @@ type mOS struct { waitsema uint32 // semaphore for parking on locks } +var darwinVersion int + func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 func bsdthread_register() int32 @@ -50,16 +52,35 @@ func osinit() { // can look at the environment first. ncpu = getncpu() - physPageSize = getPageSize() + darwinVersion = getDarwinVersion() } const ( - _CTL_HW = 6 - _HW_NCPU = 3 - _HW_PAGESIZE = 7 + _CTL_KERN = 1 + _CTL_HW = 6 + _KERN_OSRELEASE = 2 + _HW_NCPU = 3 + _HW_PAGESIZE = 7 ) +func getDarwinVersion() int { + // Use sysctl to fetch kern.osrelease + mib := [2]uint32{_CTL_KERN, _KERN_OSRELEASE} + var out [32]byte + nout := unsafe.Sizeof(out) + ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) + if ret >= 0 { + ver := 0 + for i := 0; i < int(nout) && out[i] >= '0' && out[i] <= '9'; i++ { + ver *= 10 + ver += int(out[i] - '0') + } + return ver + } + return 17 // should not happen: default to a newish version +} + func getncpu() int32 { // Use sysctl to fetch hw.ncpu. mib := [2]uint32{_CTL_HW, _HW_NCPU} diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index f549efdbf6..ab57843dfa 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -122,36 +122,34 @@ TEXT runtime·madvise(SB), NOSPLIT, $0 // OS X comm page time offsets // 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 // 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 +#define nt_tsc_base 0x50 +#define nt_scale 0x58 +#define nt_shift 0x5c +#define nt_ns_base 0x60 +#define nt_generation 0x68 +#define gtod_generation 0x6c // obsolete since Darwin v17 (High Sierra) +#define gtod_ns_base 0x70 // obsolete since Darwin v17 (High Sierra) +#define gtod_sec_base 0x78 // obsolete since Darwin v17 (High Sierra) + +#define v17_gtod_ns_base 0xd0 +#define v17_gtod_sec_ofs 0xd8 +#define v17_gtod_frac_ofs 0xe0 +#define v17_gtod_scale 0xe8 +#define v17_gtod_tkspersec 0xf0 TEXT runtime·nanotime(SB),NOSPLIT,$0-8 MOVQ $0x7fffffe00000, BP /* comm page base */ // Loop trying to take a consistent snapshot // of the time parameters. timeloop: - MOVL v12_nt_generation(BP), R9 + MOVL nt_generation(BP), R9 TESTL R9, R9 JZ timeloop RDTSC - MOVQ v12_nt_tsc_base(BP), R10 - MOVL v12_nt_scale(BP), R11 - MOVQ v12_nt_ns_base(BP), R12 - CMPL v12_nt_generation(BP), R9 + MOVQ nt_tsc_base(BP), R10 + MOVL nt_scale(BP), R11 + MOVQ nt_ns_base(BP), R12 + CMPL nt_generation(BP), R9 JNE timeloop // Gathered all the data we need. Compute monotonic time: @@ -173,32 +171,32 @@ 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 */ + CMPQ runtime·darwinVersion(SB), $17 + JB legacy /* sierra and older */ - // This is the new code, for macOS High Sierra (v13) and newer. -v13: + // This is the new code, for macOS High Sierra (Darwin v17) and newer. +v17: // Loop trying to take a consistent snapshot // of the time parameters. -timeloop13: - MOVQ v13_gtod_ns_base(BP), R12 +timeloop17: + MOVQ v17_gtod_ns_base(BP), R12 - MOVL v12_nt_generation(BP), CX + MOVL nt_generation(BP), CX TESTL CX, CX - JZ timeloop13 + JZ timeloop17 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 + MOVQ nt_tsc_base(BP), SI + MOVL nt_scale(BP), DI + MOVQ nt_ns_base(BP), BX + CMPL nt_generation(BP), CX + JNE timeloop17 + + MOVQ v17_gtod_sec_ofs(BP), R8 + MOVQ v17_gtod_frac_ofs(BP), R9 + MOVQ v17_gtod_scale(BP), R10 + MOVQ v17_gtod_tkspersec(BP), R11 + CMPQ v17_gtod_ns_base(BP), R12 + JNE timeloop17 // Compute monotonic time // mono = ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base @@ -240,24 +238,24 @@ timeloop13: MOVQ DX, nsec+8(FP) RET - // This is the legacy code needed for macOS Sierra (v12) and older. -v12: + // This is the legacy code needed for macOS Sierra (Darwin v16) and older. +legacy: // Loop trying to take a consistent snapshot // of the time parameters. timeloop: - MOVL v12_gtod_generation(BP), R8 - MOVL v12_nt_generation(BP), R9 + MOVL gtod_generation(BP), R8 + MOVL nt_generation(BP), R9 TESTL R9, R9 JZ timeloop RDTSC - MOVQ v12_nt_tsc_base(BP), R10 - MOVL v12_nt_scale(BP), R11 - MOVQ v12_nt_ns_base(BP), R12 - CMPL v12_nt_generation(BP), R9 + MOVQ nt_tsc_base(BP), R10 + MOVL nt_scale(BP), R11 + MOVQ nt_ns_base(BP), R12 + CMPL nt_generation(BP), R9 JNE timeloop - MOVQ v12_gtod_ns_base(BP), R13 - MOVQ v12_gtod_sec_base(BP), R14 - CMPL v12_gtod_generation(BP), R8 + MOVQ gtod_ns_base(BP), R13 + MOVQ gtod_sec_base(BP), R14 + CMPL gtod_generation(BP), R8 JNE timeloop // Gathered all the data we need. Compute: -- 2.48.1