Permalink
Browse files

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 <rasky@develer.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
  • Loading branch information...
rasky authored and aclements committed Jan 13, 2018
1 parent 7e05455 commit 2d6f941e8c380a0a37ade918dd76e652542e28ef
Showing with 75 additions and 56 deletions.
  1. +25 −4 src/runtime/os_darwin.go
  2. +50 −52 src/runtime/sys_darwin_amd64.s
@@ -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}
@@ -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:

0 comments on commit 2d6f941

Please sign in to comment.