1
0
mirror of https://github.com/golang/go synced 2024-11-18 08:54:45 -07:00

runtime: use libc for nanotime on Darwin

Use mach_absolute_time and mach_timebase_info to get nanosecond-level
timing information from libc on Darwin.

The conversion code from Apple's arbitrary time unit to nanoseconds is
really annoying.  It would be nice if we could replace the internal
runtime "time" with arbitrary units and put the conversion to nanoseconds
only in the places that really need it (so it isn't in every nanotime call).

It's especially annoying because numer==denom==1 for all the machines
I tried.  Makes it hard to test the conversion code :(

Update #17490

Change-Id: I6c5d602a802f5c24e35184e33d5e8194aa7afa86
Reviewed-on: https://go-review.googlesource.com/110655
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Keith Randall 2018-05-01 09:42:04 -07:00
parent e86c26789d
commit cc09212f59
9 changed files with 107 additions and 33 deletions

View File

@ -704,6 +704,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
MOVL g(CX), DI
CMPL SI, DI
JEQ noswitch
CMPL DI, m_gsignal(BP)
JEQ noswitch
CALL gosave<>(SB)
get_tls(CX)
MOVL SI, g(CX)

View File

@ -17,6 +17,7 @@ package runtime
#define __DARWIN_UNIX03 0
#include <mach/mach.h>
#include <mach/message.h>
#include <mach/mach_time.h>
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
@ -184,3 +185,5 @@ type Kevent C.struct_kevent
type Pthread C.pthread_t
type PthreadAttr C.pthread_attr_t
type MachTimebaseInfo C.mach_timebase_info_data_t

View File

@ -395,3 +395,7 @@ type pthreadattr struct {
X__sig int32
X__opaque [36]int8
}
type machTimebaseInfo struct {
numer uint32
denom uint32
}

View File

@ -398,3 +398,7 @@ type pthreadattr struct {
X__sig int64
X__opaque [56]int8
}
type machTimebaseInfo struct {
numer uint32
denom uint32
}

View File

@ -7,6 +7,7 @@
// +build !windows
// +build !nacl
// +build !freebsd
// +build !darwin
package runtime

9
src/runtime/stubs4.go Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin,arm darwin,arm64
package runtime
func nanotime() int64

View File

@ -124,6 +124,28 @@ func open(name *byte, mode, perm int32) (ret int32) {
}
func open_trampoline()
//go:nosplit
//go:cgo_unsafe_args
func nanotime() int64 {
var r struct {
t int64 // raw timer
numer, denom uint32 // conversion factors. nanoseconds = t * numer / denom.
}
asmcgocall(unsafe.Pointer(funcPC(nanotime_trampoline)), unsafe.Pointer(&r))
// Note: Apple seems unconcerned about overflow here. See
// https://developer.apple.com/library/content/qa/qa1398/_index.html
// Note also, numer == denom == 1 is common.
t := r.t
if r.numer != 1 {
t *= int64(r.numer)
}
if r.denom != 1 {
t /= int64(r.denom)
}
return t
}
func nanotime_trampoline()
// Not used on Darwin, but must be defined.
func exitThread(wait *uint32) {
}
@ -150,6 +172,9 @@ func exitThread(wait *uint32) {
//go:cgo_import_dynamic libc_error __error "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_usleep usleep "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_mach_timebase_info mach_timebase_info "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_mach_absolute_time mach_absolute_time "/usr/lib/libSystem.B.dylib"
// Magic incantation to get libSystem actually dynamically linked.
// TODO: Why does the code require this? See cmd/compile/internal/ld/go.go:210
//go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib"

View File

@ -311,13 +311,37 @@ TEXT time·now(SB),NOSPLIT,$0-20
MOVL DX, nsec+8(FP)
RET
// func nanotime() int64
TEXT runtime·nanotime(SB),NOSPLIT,$0
CALL runtime·now(SB)
SUBL runtime·startNano(SB), AX
SBBL runtime·startNano+4(SB), DX
MOVL AX, ret_lo+0(FP)
MOVL DX, ret_hi+4(FP)
GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8+(machTimebaseInfo__size+15)/16*16, SP
CALL libc_mach_absolute_time(SB)
MOVL 16+(machTimebaseInfo__size+15)/16*16(SP), CX
MOVL AX, 0(CX)
MOVL DX, 4(CX)
MOVL timebase<>+machTimebaseInfo_denom(SB), DI // atomic read
MOVL timebase<>+machTimebaseInfo_numer(SB), SI
TESTL DI, DI
JNE initialized
LEAL 4(SP), AX
MOVL AX, 0(SP)
CALL libc_mach_timebase_info(SB)
MOVL 4+machTimebaseInfo_numer(SP), SI
MOVL 4+machTimebaseInfo_denom(SP), DI
MOVL SI, timebase<>+machTimebaseInfo_numer(SB)
MOVL DI, AX
XCHGL AX, timebase<>+machTimebaseInfo_denom(SB) // atomic write
MOVL 16+(machTimebaseInfo__size+15)/16*16(SP), CX
initialized:
MOVL SI, 8(CX)
MOVL DI, 12(CX)
MOVL BP, SP
POPL BP
RET
TEXT runtime·sigprocmask(SB),NOSPLIT,$0

View File

@ -110,33 +110,35 @@ TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
#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 nt_generation(BP), R9
TESTL R9, R9
JZ timeloop
RDTSC
MOVQ nt_tsc_base(BP), R10
MOVL nt_scale(BP), R11
MOVQ nt_ns_base(BP), R12
CMPL nt_generation(BP), R9
JNE timeloop
GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
// Gathered all the data we need. Compute monotonic time:
// ((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 R10, AX
MULQ R11
SHRQ $32, AX:DX
ADDQ R12, AX
MOVQ runtime·startNano(SB), CX
SUBQ CX, AX
MOVQ AX, ret+0(FP)
TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
MOVQ DI, BX
CALL libc_mach_absolute_time(SB)
MOVQ AX, 0(BX)
MOVL timebase<>+machTimebaseInfo_numer(SB), SI
MOVL timebase<>+machTimebaseInfo_denom(SB), DI // atomic read
TESTL DI, DI
JNE initialized
SUBQ $(machTimebaseInfo__size+15)/16*16, SP
MOVQ SP, DI
CALL libc_mach_timebase_info(SB)
MOVL machTimebaseInfo_numer(SP), SI
MOVL machTimebaseInfo_denom(SP), DI
ADDQ $(machTimebaseInfo__size+15)/16*16, SP
MOVL SI, timebase<>+machTimebaseInfo_numer(SB)
MOVL DI, AX
XCHGL AX, timebase<>+machTimebaseInfo_denom(SB) // atomic write
initialized:
MOVL SI, 8(BX)
MOVL DI, 12(BX)
MOVQ BP, SP
POPQ BP
RET
TEXT time·now(SB), NOSPLIT, $32-24