Skip to content

Commit

Permalink
runtime: fix time.Now on Sierra and older
Browse files Browse the repository at this point in the history
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 16, 2018
1 parent 7e05455 commit 2d6f941
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 56 deletions.
29 changes: 25 additions & 4 deletions src/runtime/os_darwin.go
Expand Up @@ -11,6 +11,8 @@ type mOS struct {
waitsema uint32 // semaphore for parking on locks waitsema uint32 // semaphore for parking on locks
} }


var darwinVersion int

func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
func bsdthread_register() int32 func bsdthread_register() int32


Expand Down Expand Up @@ -50,16 +52,35 @@ func osinit() {
// can look at the environment first. // can look at the environment first.


ncpu = getncpu() ncpu = getncpu()

physPageSize = getPageSize() physPageSize = getPageSize()
darwinVersion = getDarwinVersion()
} }


const ( const (
_CTL_HW = 6 _CTL_KERN = 1
_HW_NCPU = 3 _CTL_HW = 6
_HW_PAGESIZE = 7 _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 { func getncpu() int32 {
// Use sysctl to fetch hw.ncpu. // Use sysctl to fetch hw.ncpu.
mib := [2]uint32{_CTL_HW, _HW_NCPU} mib := [2]uint32{_CTL_HW, _HW_NCPU}
Expand Down
102 changes: 50 additions & 52 deletions src/runtime/sys_darwin_amd64.s
Expand Up @@ -122,36 +122,34 @@ TEXT runtime·madvise(SB), NOSPLIT, $0
// OS X comm page time offsets // OS X comm page time offsets
// https://opensource.apple.com/source/xnu/xnu-4570.1.46/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 nt_tsc_base 0x50

#define nt_scale 0x58
#define v12_nt_tsc_base 0x50 #define nt_shift 0x5c
#define v12_nt_scale 0x58 #define nt_ns_base 0x60
#define v12_nt_shift 0x5c #define nt_generation 0x68
#define v12_nt_ns_base 0x60 #define gtod_generation 0x6c // obsolete since Darwin v17 (High Sierra)
#define v12_nt_generation 0x68 #define gtod_ns_base 0x70 // obsolete since Darwin v17 (High Sierra)
#define v12_gtod_generation 0x6c // obsolete since High Sierra (v13) #define gtod_sec_base 0x78 // obsolete since Darwin v17 (High Sierra)
#define v12_gtod_ns_base 0x70 // obsolete since High Sierra (v13)
#define v12_gtod_sec_base 0x78 // obsolete since High Sierra (v13) #define v17_gtod_ns_base 0xd0

#define v17_gtod_sec_ofs 0xd8
#define v13_gtod_ns_base 0xd0 #define v17_gtod_frac_ofs 0xe0
#define v13_gtod_sec_ofs 0xd8 #define v17_gtod_scale 0xe8
#define v13_gtod_frac_ofs 0xe0 #define v17_gtod_tkspersec 0xf0
#define v13_gtod_scale 0xe8
#define v13_gtod_tkspersec 0xf0


TEXT runtime·nanotime(SB),NOSPLIT,$0-8 TEXT runtime·nanotime(SB),NOSPLIT,$0-8
MOVQ $0x7fffffe00000, BP /* comm page base */ MOVQ $0x7fffffe00000, BP /* comm page base */
// Loop trying to take a consistent snapshot // Loop trying to take a consistent snapshot
// of the time parameters. // of the time parameters.
timeloop: timeloop:
MOVL v12_nt_generation(BP), R9 MOVL nt_generation(BP), R9
TESTL R9, R9 TESTL R9, R9
JZ timeloop JZ timeloop
RDTSC RDTSC
MOVQ v12_nt_tsc_base(BP), R10 MOVQ nt_tsc_base(BP), R10
MOVL v12_nt_scale(BP), R11 MOVL nt_scale(BP), R11
MOVQ v12_nt_ns_base(BP), R12 MOVQ nt_ns_base(BP), R12
CMPL v12_nt_generation(BP), R9 CMPL nt_generation(BP), R9
JNE timeloop JNE timeloop


// Gathered all the data we need. Compute monotonic time: // Gathered all the data we need. Compute monotonic time:
Expand All @@ -173,32 +171,32 @@ TEXT time·now(SB), NOSPLIT, $32-24
// are used in the systime fallback, as the timeval address // are used in the systime fallback, as the timeval address
// filled in by the system call. // filled in by the system call.
MOVQ $0x7fffffe00000, BP /* comm page base */ MOVQ $0x7fffffe00000, BP /* comm page base */
CMPW commpage_version(BP), $13 CMPQ runtime·darwinVersion(SB), $17
JB v12 /* sierra and older */ JB legacy /* sierra and older */


// This is the new code, for macOS High Sierra (v13) and newer. // This is the new code, for macOS High Sierra (Darwin v17) and newer.
v13: v17:
// Loop trying to take a consistent snapshot // Loop trying to take a consistent snapshot
// of the time parameters. // of the time parameters.
timeloop13: timeloop17:
MOVQ v13_gtod_ns_base(BP), R12 MOVQ v17_gtod_ns_base(BP), R12


MOVL v12_nt_generation(BP), CX MOVL nt_generation(BP), CX
TESTL CX, CX TESTL CX, CX
JZ timeloop13 JZ timeloop17
RDTSC RDTSC
MOVQ v12_nt_tsc_base(BP), SI MOVQ nt_tsc_base(BP), SI
MOVL v12_nt_scale(BP), DI MOVL nt_scale(BP), DI
MOVQ v12_nt_ns_base(BP), BX MOVQ nt_ns_base(BP), BX
CMPL v12_nt_generation(BP), CX CMPL nt_generation(BP), CX
JNE timeloop13 JNE timeloop17


MOVQ v13_gtod_sec_ofs(BP), R8 MOVQ v17_gtod_sec_ofs(BP), R8
MOVQ v13_gtod_frac_ofs(BP), R9 MOVQ v17_gtod_frac_ofs(BP), R9
MOVQ v13_gtod_scale(BP), R10 MOVQ v17_gtod_scale(BP), R10
MOVQ v13_gtod_tkspersec(BP), R11 MOVQ v17_gtod_tkspersec(BP), R11
CMPQ v13_gtod_ns_base(BP), R12 CMPQ v17_gtod_ns_base(BP), R12
JNE timeloop13 JNE timeloop17


// Compute monotonic time // Compute monotonic time
// mono = ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base // mono = ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base
Expand Down Expand Up @@ -240,24 +238,24 @@ timeloop13:
MOVQ DX, nsec+8(FP) MOVQ DX, nsec+8(FP)
RET RET


// This is the legacy code needed for macOS Sierra (v12) and older. // This is the legacy code needed for macOS Sierra (Darwin v16) and older.
v12: legacy:
// Loop trying to take a consistent snapshot // Loop trying to take a consistent snapshot
// of the time parameters. // of the time parameters.
timeloop: timeloop:
MOVL v12_gtod_generation(BP), R8 MOVL gtod_generation(BP), R8
MOVL v12_nt_generation(BP), R9 MOVL nt_generation(BP), R9
TESTL R9, R9 TESTL R9, R9
JZ timeloop JZ timeloop
RDTSC RDTSC
MOVQ v12_nt_tsc_base(BP), R10 MOVQ nt_tsc_base(BP), R10
MOVL v12_nt_scale(BP), R11 MOVL nt_scale(BP), R11
MOVQ v12_nt_ns_base(BP), R12 MOVQ nt_ns_base(BP), R12
CMPL v12_nt_generation(BP), R9 CMPL nt_generation(BP), R9
JNE timeloop JNE timeloop
MOVQ v12_gtod_ns_base(BP), R13 MOVQ gtod_ns_base(BP), R13
MOVQ v12_gtod_sec_base(BP), R14 MOVQ gtod_sec_base(BP), R14
CMPL v12_gtod_generation(BP), R8 CMPL gtod_generation(BP), R8
JNE timeloop JNE timeloop


// Gathered all the data we need. Compute: // Gathered all the data we need. Compute:
Expand Down

0 comments on commit 2d6f941

Please sign in to comment.