Commit ea59ebd3 authored by Meng Zhuo's avatar Meng Zhuo Committed by Ian Lance Taylor

runtime: use vDSO for clock_gettime on linux/arm64

Use the __vdso_clock_gettime fast path via the vDSO on linux/arm64 to
speed up nanotime and walltime. This results in the following
performance improvement for time.Now on Cavium ThunderX:

name     old time/op  new time/op  delta
TimeNow   442ns ± 0%   163ns ± 0%  -63.16%  (p=0.000 n=10+10)

And benchmarks on VDSO

BenchmarkClockVDSOAndFallbackPaths/vDSO         10000000 166 ns/op
BenchmarkClockVDSOAndFallbackPaths/Fallback     3000000 456 ns/op

Change-Id: I326118c6dff865eaa0569fc45d1fc1ff95cb74f6
Reviewed-on: https://go-review.googlesource.com/99855
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent b63b0f2b
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux // +build linux
// +build !386,!amd64,!arm // +build !386,!amd64,!arm,!arm64
package runtime package runtime
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
#define AT_FDCWD -100 #define AT_FDCWD -100
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
#define SYS_exit 93 #define SYS_exit 93
#define SYS_read 63 #define SYS_read 63
#define SYS_write 64 #define SYS_write 64
...@@ -180,23 +183,87 @@ TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 ...@@ -180,23 +183,87 @@ TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
// func walltime() (sec int64, nsec int32) // func walltime() (sec int64, nsec int32)
TEXT runtime·walltime(SB),NOSPLIT,$24-12 TEXT runtime·walltime(SB),NOSPLIT,$24-12
MOVW $0, R0 // CLOCK_REALTIME MOVD RSP, R20 // R20 is unchanged by C code
MOVD RSP, R1 MOVD RSP, R1
MOVD g_m(g), R21 // R21 = m
// Set vdsoPC and vdsoSP for SIGPROF traceback.
MOVD LR, m_vdsoPC(R21)
MOVD R20, m_vdsoSP(R21)
MOVD m_curg(R21), R0
CMP g, R0
BNE noswitch
MOVD m_g0(R21), R3
MOVD (g_sched+gobuf_sp)(R3), R1 // Set RSP to g0 stack
noswitch:
SUB $16, R1
BIC $15, R1 // Align for C code
MOVD R1, RSP
MOVW $CLOCK_REALTIME, R0
MOVD runtime·vdsoClockgettimeSym(SB), R2
CBZ R2, fallback
BL (R2)
B finish
fallback:
MOVD $SYS_clock_gettime, R8 MOVD $SYS_clock_gettime, R8
SVC SVC
finish:
MOVD 0(RSP), R3 // sec MOVD 0(RSP), R3 // sec
MOVD 8(RSP), R5 // nsec MOVD 8(RSP), R5 // nsec
MOVD R20, RSP // restore SP
MOVD $0, m_vdsoSP(R21) // clear vdsoSP
MOVD R3, sec+0(FP) MOVD R3, sec+0(FP)
MOVW R5, nsec+8(FP) MOVW R5, nsec+8(FP)
RET RET
TEXT runtime·nanotime(SB),NOSPLIT,$24-8 TEXT runtime·nanotime(SB),NOSPLIT,$24-8
MOVW $1, R0 // CLOCK_MONOTONIC MOVD RSP, R20 // R20 is unchanged by C code
MOVD RSP, R1 MOVD RSP, R1
MOVD g_m(g), R21 // R21 = m
// Set vdsoPC and vdsoSP for SIGPROF traceback.
MOVD LR, m_vdsoPC(R21)
MOVD R20, m_vdsoSP(R21)
MOVD m_curg(R21), R0
CMP g, R0
BNE noswitch
MOVD m_g0(R21), R3
MOVD (g_sched+gobuf_sp)(R3), R1 // Set RSP to g0 stack
noswitch:
SUB $16, R1
BIC $15, R1
MOVD R1, RSP
MOVW $CLOCK_MONOTONIC, R0
MOVD runtime·vdsoClockgettimeSym(SB), R2
CBZ R2, fallback
BL (R2)
B finish
fallback:
MOVD $SYS_clock_gettime, R8 MOVD $SYS_clock_gettime, R8
SVC SVC
finish:
MOVD 0(RSP), R3 // sec MOVD 0(RSP), R3 // sec
MOVD 8(RSP), R5 // nsec MOVD 8(RSP), R5 // nsec
MOVD R20, RSP // restore SP
MOVD $0, m_vdsoSP(R21) // clear vdsoSP
// sec is in R3, nsec in R5 // sec is in R3, nsec in R5
// return nsec in R3 // return nsec in R3
MOVD $1000000000, R4 MOVD $1000000000, R4
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux // +build linux
// +build amd64 // +build amd64 arm64
package runtime package runtime
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux,!386,!amd64,!arm !linux // +build linux,!386,!amd64,!arm,!arm64 !linux
package runtime package runtime
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux // +build linux
// +build 386 amd64 arm // +build 386 amd64 arm arm64
package runtime package runtime
...@@ -96,8 +96,6 @@ type vdsoInfo struct { ...@@ -96,8 +96,6 @@ type vdsoInfo struct {
verdef *elfVerdef verdef *elfVerdef
} }
var linux26 = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
// see vdso_linux_*.go for vdsoSymbolKeys[] and vdso*Sym vars // see vdso_linux_*.go for vdsoSymbolKeys[] and vdso*Sym vars
func vdsoInitFromSysinfoEhdr(info *vdsoInfo, hdr *elfEhdr) { func vdsoInitFromSysinfoEhdr(info *vdsoInfo, hdr *elfEhdr) {
...@@ -220,7 +218,6 @@ func vdsoParseSymbols(info *vdsoInfo, version int32) { ...@@ -220,7 +218,6 @@ func vdsoParseSymbols(info *vdsoInfo, version int32) {
if k.name != gostringnocopy(&info.symstrings[sym.st_name]) { if k.name != gostringnocopy(&info.symstrings[sym.st_name]) {
return false return false
} }
// Check symbol version. // Check symbol version.
if info.versym != nil && version != 0 && int32(info.versym[symIndex]&0x7fff) != version { if info.versym != nil && version != 0 && int32(info.versym[symIndex]&0x7fff) != version {
return false return false
...@@ -276,7 +273,7 @@ func vdsoauxv(tag, val uintptr) { ...@@ -276,7 +273,7 @@ func vdsoauxv(tag, val uintptr) {
// when passed to the three functions below. // when passed to the three functions below.
info1 := (*vdsoInfo)(noescape(unsafe.Pointer(&info))) info1 := (*vdsoInfo)(noescape(unsafe.Pointer(&info)))
vdsoInitFromSysinfoEhdr(info1, (*elfEhdr)(unsafe.Pointer(val))) vdsoInitFromSysinfoEhdr(info1, (*elfEhdr)(unsafe.Pointer(val)))
vdsoParseSymbols(info1, vdsoFindVersion(info1, &linux26)) vdsoParseSymbols(info1, vdsoFindVersion(info1, &vdsoLinuxVersion))
} }
} }
......
...@@ -11,11 +11,11 @@ const ( ...@@ -11,11 +11,11 @@ const (
vdsoArrayMax = 1<<31 - 1 vdsoArrayMax = 1<<31 - 1
) )
var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
var vdsoSymbolKeys = []vdsoSymbolKey{ var vdsoSymbolKeys = []vdsoSymbolKey{
{"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym}, {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
} }
// initialize to fall back to syscall // initialize to fall back to syscall
var ( var vdsoClockgettimeSym uintptr = 0
vdsoClockgettimeSym uintptr = 0
)
...@@ -10,6 +10,8 @@ const ( ...@@ -10,6 +10,8 @@ const (
vdsoArrayMax = 1<<50 - 1 vdsoArrayMax = 1<<50 - 1
) )
var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
var vdsoSymbolKeys = []vdsoSymbolKey{ var vdsoSymbolKeys = []vdsoSymbolKey{
{"__vdso_gettimeofday", 0x315ca59, 0xb01bca00, &vdsoGettimeofdaySym}, {"__vdso_gettimeofday", 0x315ca59, 0xb01bca00, &vdsoGettimeofdaySym},
{"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym}, {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
......
...@@ -11,6 +11,8 @@ const ( ...@@ -11,6 +11,8 @@ const (
vdsoArrayMax = 1<<31 - 1 vdsoArrayMax = 1<<31 - 1
) )
var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
var vdsoSymbolKeys = []vdsoSymbolKey{ var vdsoSymbolKeys = []vdsoSymbolKey{
{"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym}, {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
} }
......
// 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.
package runtime
const (
// vdsoArrayMax is the byte-size of a maximally sized array on this architecture.
// See cmd/compile/internal/arm64/galign.go arch.MAXWIDTH initialization.
vdsoArrayMax = 1<<50 - 1
)
// key and version at man 7 vdso : aarch64
var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6.39", 0x75fcb89}
var vdsoSymbolKeys = []vdsoSymbolKey{
{"__kernel_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
}
// initialize to fall back to syscall
var vdsoClockgettimeSym uintptr = 0
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux // +build linux
// +build 386 amd64 arm // +build 386 amd64 arm arm64
package runtime_test package runtime_test
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment