]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use vDSO for clock_gettime on linux/arm64
authorMeng Zhuo <mengzhuo1203@gmail.com>
Mon, 12 Mar 2018 07:32:28 +0000 (07:32 +0000)
committerIan Lance Taylor <iant@golang.org>
Tue, 27 Mar 2018 13:21:27 +0000 (13:21 +0000)
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: Ian Lance Taylor <iant@golang.org>
src/runtime/os_linux_novdso.go
src/runtime/sys_linux_arm64.s
src/runtime/vdso_elf64.go
src/runtime/vdso_in_none.go
src/runtime/vdso_linux.go
src/runtime/vdso_linux_386.go
src/runtime/vdso_linux_amd64.go
src/runtime/vdso_linux_arm.go
src/runtime/vdso_linux_arm64.go [new file with mode: 0644]
src/runtime/vdso_linux_test.go

index b5a6b0e947bec9fe666593094efffabfa62c5941..ee4a7a95c2aff0a2ae5a2e964a0c08ac749be4cd 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build linux
-// +build !386,!amd64,!arm
+// +build !386,!amd64,!arm,!arm64
 
 package runtime
 
index 6954f32aacd3ce762b6d6868e93284fc50704330..8a56ba6babeb459f4ee9ab8f3c8a89b3f5b903b0 100644 (file)
@@ -12,6 +12,9 @@
 
 #define AT_FDCWD -100
 
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+
 #define SYS_exit               93
 #define SYS_read               63
 #define SYS_write              64
@@ -180,23 +183,87 @@ TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
 
 // func walltime() (sec int64, nsec int32)
 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    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
        SVC
+
+finish:
        MOVD    0(RSP), R3      // sec
        MOVD    8(RSP), R5      // nsec
+
+       MOVD    R20, RSP        // restore SP
+       MOVD    $0, m_vdsoSP(R21)       // clear vdsoSP
+
        MOVD    R3, sec+0(FP)
        MOVW    R5, nsec+8(FP)
        RET
 
 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    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
        SVC
+
+finish:
        MOVD    0(RSP), R3      // sec
        MOVD    8(RSP), R5      // nsec
+
+       MOVD    R20, RSP        // restore SP
+       MOVD    $0, m_vdsoSP(R21)       // clear vdsoSP
+
        // sec is in R3, nsec in R5
        // return nsec in R3
        MOVD    $1000000000, R4
index 828714dbcfc2bdb4b90a574435b9ae09e4381818..851025006586c22147fe2581f05b39c899d23f53 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build linux
-// +build amd64
+// +build amd64 arm64
 
 package runtime
 
index f727e1d0e8a9d960a01818a9584b2fda8bfcac21..34cfac56d124565cb90c0c73b24df86359ff1268 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux,!386,!amd64,!arm !linux
+// +build linux,!386,!amd64,!arm,!arm64 !linux
 
 package runtime
 
index 7939bb54be0769903ef272f473b14e5f8714e557..c246b3388485b03b8c3cafee4edfa5b48ed39094 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build linux
-// +build 386 amd64 arm
+// +build 386 amd64 arm arm64
 
 package runtime
 
@@ -96,8 +96,6 @@ type vdsoInfo struct {
        verdef *elfVerdef
 }
 
-var linux26 = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
-
 // see vdso_linux_*.go for vdsoSymbolKeys[] and vdso*Sym vars
 
 func vdsoInitFromSysinfoEhdr(info *vdsoInfo, hdr *elfEhdr) {
@@ -220,7 +218,6 @@ func vdsoParseSymbols(info *vdsoInfo, version int32) {
                if k.name != gostringnocopy(&info.symstrings[sym.st_name]) {
                        return false
                }
-
                // Check symbol version.
                if info.versym != nil && version != 0 && int32(info.versym[symIndex]&0x7fff) != version {
                        return false
@@ -276,7 +273,7 @@ func vdsoauxv(tag, val uintptr) {
                // when passed to the three functions below.
                info1 := (*vdsoInfo)(noescape(unsafe.Pointer(&info)))
                vdsoInitFromSysinfoEhdr(info1, (*elfEhdr)(unsafe.Pointer(val)))
-               vdsoParseSymbols(info1, vdsoFindVersion(info1, &linux26))
+               vdsoParseSymbols(info1, vdsoFindVersion(info1, &vdsoLinuxVersion))
        }
 }
 
index 90f7af507ba267c0fcd60ae83c0b2c205a7114b8..5092c7c1d1e0134897a51019ad2876c8975dc984 100644 (file)
@@ -11,11 +11,11 @@ const (
        vdsoArrayMax = 1<<31 - 1
 )
 
+var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
+
 var vdsoSymbolKeys = []vdsoSymbolKey{
        {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
 }
 
 // initialize to fall back to syscall
-var (
-       vdsoClockgettimeSym uintptr = 0
-)
+var vdsoClockgettimeSym uintptr = 0
index 387d72e0cb13d3e4ba7bb7815cd29b542e39b003..d9ab4ab3c67f4538a590ee262df6f0c9a58aa14a 100644 (file)
@@ -10,6 +10,8 @@ const (
        vdsoArrayMax = 1<<50 - 1
 )
 
+var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
+
 var vdsoSymbolKeys = []vdsoSymbolKey{
        {"__vdso_gettimeofday", 0x315ca59, 0xb01bca00, &vdsoGettimeofdaySym},
        {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
index 143d2b56243e5b64224e4132ac9fd214c77da151..ac3bdcf0430df6c1409b034bd319ad8322654bd8 100644 (file)
@@ -11,6 +11,8 @@ const (
        vdsoArrayMax = 1<<31 - 1
 )
 
+var vdsoLinuxVersion = vdsoVersionKey{"LINUX_2.6", 0x3ae75f6}
+
 var vdsoSymbolKeys = []vdsoSymbolKey{
        {"__vdso_clock_gettime", 0xd35ec75, 0x6e43a318, &vdsoClockgettimeSym},
 }
diff --git a/src/runtime/vdso_linux_arm64.go b/src/runtime/vdso_linux_arm64.go
new file mode 100644 (file)
index 0000000..2f003cd
--- /dev/null
@@ -0,0 +1,21 @@
+// 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
index 5cc5493dc6d6f4efb98aa176a03a446154127d6a..b5221f90b71e4a6f05208c3b097397d8a6c88308 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build linux
-// +build 386 amd64 arm
+// +build 386 amd64 arm arm64
 
 package runtime_test