aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/sys_linux_amd64.s
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-08-04 20:25:10 -0400
committerCherry Zhang <cherryyz@google.com>2020-08-10 18:06:04 +0000
commita93a4c178025b52be85c9eb4b9f2815716a62d11 (patch)
tree85499b8d785eea7bd3ec0752da80d285fd9d52f3 /src/runtime/sys_linux_amd64.s
parentba9e10889976025ee1d027db6b1cad383ec56de8 (diff)
downloadgo-a93a4c178025b52be85c9eb4b9f2815716a62d11.tar.gz
go-a93a4c178025b52be85c9eb4b9f2815716a62d11.zip
runtime: make nanotime1 reentrant
Currently, nanotime1 (and walltime1) is not reentrant, in that it sets m.vdsoSP at entry and clears it at exit. If a signal lands in between, and nanotime1 is called from the signal handler, it will clear m.vdsoSP while we are still in nanotime1. If (in the unlikely event) it is signaled again, m.vdsoSP will be wrong, which may cause the stack unwinding code to crash. This CL makes it reentrant, by saving/restoring the previous vdsoPC and vdsoSP, instead of setting it to 0 at exit. TODO: have some way to test? Change-Id: I9ee53b251f1d8a5a489c71d4b4c0df1dee70c3e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/246763 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/sys_linux_amd64.s')
-rw-r--r--src/runtime/sys_linux_amd64.s56
1 files changed, 38 insertions, 18 deletions
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 58d3bc54b4..fe9c6bce85 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -206,7 +206,7 @@ TEXT runtime·mincore(SB),NOSPLIT,$0-28
// func walltime1() (sec int64, nsec int32)
// non-zero frame-size means bp is saved and restored
-TEXT runtime·walltime1(SB),NOSPLIT,$8-12
+TEXT runtime·walltime1(SB),NOSPLIT,$16-12
// We don't know how much stack space the VDSO code will need,
// so switch to g0.
// In particular, a kernel configured with CONFIG_OPTIMIZE_INLINING=n
@@ -221,6 +221,13 @@ TEXT runtime·walltime1(SB),NOSPLIT,$8-12
MOVQ g_m(AX), BX // BX unchanged by C code.
// Set vdsoPC and vdsoSP for SIGPROF traceback.
+ // Save the old values on stack and restore them on exit,
+ // so this function is reentrant.
+ MOVQ m_vdsoPC(BX), CX
+ MOVQ m_vdsoSP(BX), DX
+ MOVQ CX, 0(SP)
+ MOVQ DX, 8(SP)
+
LEAQ sec+0(FP), DX
MOVQ -8(DX), CX
MOVQ CX, m_vdsoPC(BX)
@@ -244,8 +251,17 @@ noswitch:
CALL AX
MOVQ 0(SP), AX // sec
MOVQ 8(SP), DX // nsec
+ret:
MOVQ BP, SP // Restore real SP
- MOVQ $0, m_vdsoSP(BX)
+ // Restore vdsoPC, vdsoSP
+ // We don't worry about being signaled between the two stores.
+ // If we are not in a signal handler, we'll restore vdsoSP to 0,
+ // and no one will care about vdsoPC. If we are in a signal handler,
+ // we cannot receive another signal.
+ MOVQ 8(SP), CX
+ MOVQ CX, m_vdsoSP(BX)
+ MOVQ 0(SP), CX
+ MOVQ CX, m_vdsoPC(BX)
MOVQ AX, sec+0(FP)
MOVL DX, nsec+8(FP)
RET
@@ -257,15 +273,10 @@ fallback:
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // usec
IMULQ $1000, DX
- MOVQ BP, SP // Restore real SP
- MOVQ $0, m_vdsoSP(BX)
- MOVQ AX, sec+0(FP)
- MOVL DX, nsec+8(FP)
- RET
+ JMP ret
// func nanotime1() int64
-// non-zero frame-size means bp is saved and restored
-TEXT runtime·nanotime1(SB),NOSPLIT,$8-8
+TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
// Switch to g0 stack. See comment above in runtime·walltime.
MOVQ SP, BP // Save old SP; BP unchanged by C code.
@@ -275,6 +286,13 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$8-8
MOVQ g_m(AX), BX // BX unchanged by C code.
// Set vdsoPC and vdsoSP for SIGPROF traceback.
+ // Save the old values on stack and restore them on exit,
+ // so this function is reentrant.
+ MOVQ m_vdsoPC(BX), CX
+ MOVQ m_vdsoSP(BX), DX
+ MOVQ CX, 0(SP)
+ MOVQ DX, 8(SP)
+
LEAQ ret+0(FP), DX
MOVQ -8(DX), CX
MOVQ CX, m_vdsoPC(BX)
@@ -298,8 +316,17 @@ noswitch:
CALL AX
MOVQ 0(SP), AX // sec
MOVQ 8(SP), DX // nsec
+ret:
MOVQ BP, SP // Restore real SP
- MOVQ $0, m_vdsoSP(BX)
+ // Restore vdsoPC, vdsoSP
+ // We don't worry about being signaled between the two stores.
+ // If we are not in a signal handler, we'll restore vdsoSP to 0,
+ // and no one will care about vdsoPC. If we are in a signal handler,
+ // we cannot receive another signal.
+ MOVQ 8(SP), CX
+ MOVQ CX, m_vdsoSP(BX)
+ MOVQ 0(SP), CX
+ MOVQ CX, m_vdsoPC(BX)
// sec is in AX, nsec in DX
// return nsec in AX
IMULQ $1000000000, AX
@@ -313,15 +340,8 @@ fallback:
CALL AX
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // usec
- MOVQ BP, SP // Restore real SP
- MOVQ $0, m_vdsoSP(BX)
IMULQ $1000, DX
- // sec is in AX, nsec in DX
- // return nsec in AX
- IMULQ $1000000000, AX
- ADDQ DX, AX
- MOVQ AX, ret+0(FP)
- RET
+ JMP ret
TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-28
MOVL how+0(FP), DI