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:
parent
e86c26789d
commit
cc09212f59
@ -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)
|
||||
|
@ -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
|
||||
|
@ -395,3 +395,7 @@ type pthreadattr struct {
|
||||
X__sig int32
|
||||
X__opaque [36]int8
|
||||
}
|
||||
type machTimebaseInfo struct {
|
||||
numer uint32
|
||||
denom uint32
|
||||
}
|
||||
|
@ -398,3 +398,7 @@ type pthreadattr struct {
|
||||
X__sig int64
|
||||
X__opaque [56]int8
|
||||
}
|
||||
type machTimebaseInfo struct {
|
||||
numer uint32
|
||||
denom uint32
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
// +build !windows
|
||||
// +build !nacl
|
||||
// +build !freebsd
|
||||
// +build !darwin
|
||||
|
||||
package runtime
|
||||
|
||||
|
9
src/runtime/stubs4.go
Normal file
9
src/runtime/stubs4.go
Normal 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
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user