diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 54d5eaa014..5ca26a2d5f 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -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) diff --git a/src/runtime/defs_darwin.go b/src/runtime/defs_darwin.go index bedaf99961..e3a25c5312 100644 --- a/src/runtime/defs_darwin.go +++ b/src/runtime/defs_darwin.go @@ -17,6 +17,7 @@ package runtime #define __DARWIN_UNIX03 0 #include #include +#include #include #include #include @@ -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 diff --git a/src/runtime/defs_darwin_386.go b/src/runtime/defs_darwin_386.go index 51c6340dfa..7f8ae9c934 100644 --- a/src/runtime/defs_darwin_386.go +++ b/src/runtime/defs_darwin_386.go @@ -395,3 +395,7 @@ type pthreadattr struct { X__sig int32 X__opaque [36]int8 } +type machTimebaseInfo struct { + numer uint32 + denom uint32 +} diff --git a/src/runtime/defs_darwin_amd64.go b/src/runtime/defs_darwin_amd64.go index d1483e7db5..f35b90a5fa 100644 --- a/src/runtime/defs_darwin_amd64.go +++ b/src/runtime/defs_darwin_amd64.go @@ -398,3 +398,7 @@ type pthreadattr struct { X__sig int64 X__opaque [56]int8 } +type machTimebaseInfo struct { + numer uint32 + denom uint32 +} diff --git a/src/runtime/stubs3.go b/src/runtime/stubs3.go index 7570dcaeb2..5c0786e411 100644 --- a/src/runtime/stubs3.go +++ b/src/runtime/stubs3.go @@ -7,6 +7,7 @@ // +build !windows // +build !nacl // +build !freebsd +// +build !darwin package runtime diff --git a/src/runtime/stubs4.go b/src/runtime/stubs4.go new file mode 100644 index 0000000000..ad0e48e455 --- /dev/null +++ b/src/runtime/stubs4.go @@ -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 diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 8757486e22..3bdd1f2b16 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -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" diff --git a/src/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s index 16ca3e06ae..44a686f400 100644 --- a/src/runtime/sys_darwin_386.s +++ b/src/runtime/sys_darwin_386.s @@ -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 diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index e48145a450..24db7f52cd 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -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