diff options
author | Cherry Zhang <cherryyz@google.com> | 2020-08-04 20:25:10 -0400 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2020-08-10 18:06:04 +0000 |
commit | a93a4c178025b52be85c9eb4b9f2815716a62d11 (patch) | |
tree | 85499b8d785eea7bd3ec0752da80d285fd9d52f3 /src/runtime/sys_linux_386.s | |
parent | ba9e10889976025ee1d027db6b1cad383ec56de8 (diff) | |
download | go-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_386.s')
-rw-r--r-- | src/runtime/sys_linux_386.s | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s index 1b28098ad9..5b9b638ad7 100644 --- a/src/runtime/sys_linux_386.s +++ b/src/runtime/sys_linux_386.s @@ -222,7 +222,7 @@ TEXT runtime·mincore(SB),NOSPLIT,$0-16 RET // func walltime1() (sec int64, nsec int32) -TEXT runtime·walltime1(SB), NOSPLIT, $0-12 +TEXT runtime·walltime1(SB), NOSPLIT, $8-12 // We don't know how much stack space the VDSO code will need, // so switch to g0. @@ -233,6 +233,13 @@ TEXT runtime·walltime1(SB), NOSPLIT, $0-12 MOVL g_m(AX), SI // SI 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. + MOVL m_vdsoPC(SI), CX + MOVL m_vdsoSP(SI), DX + MOVL CX, 0(SP) + MOVL DX, 4(SP) + LEAL sec+0(FP), DX MOVL -4(DX), CX MOVL CX, m_vdsoPC(SI) @@ -276,7 +283,15 @@ finish: MOVL 12(SP), BX // nsec MOVL BP, SP // Restore real SP - MOVL $0, m_vdsoSP(SI) + // 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. + MOVL 4(SP), CX + MOVL CX, m_vdsoSP(SI) + MOVL 0(SP), CX + MOVL CX, m_vdsoPC(SI) // sec is in AX, nsec in BX MOVL AX, sec_lo+0(FP) @@ -286,7 +301,7 @@ finish: // int64 nanotime(void) so really // void nanotime(int64 *nsec) -TEXT runtime·nanotime1(SB), NOSPLIT, $0-8 +TEXT runtime·nanotime1(SB), NOSPLIT, $8-8 // Switch to g0 stack. See comment above in runtime·walltime. MOVL SP, BP // Save old SP; BP unchanged by C code. @@ -296,6 +311,13 @@ TEXT runtime·nanotime1(SB), NOSPLIT, $0-8 MOVL g_m(AX), SI // SI 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. + MOVL m_vdsoPC(SI), CX + MOVL m_vdsoSP(SI), DX + MOVL CX, 0(SP) + MOVL DX, 4(SP) + LEAL ret+0(FP), DX MOVL -4(DX), CX MOVL CX, m_vdsoPC(SI) @@ -332,7 +354,15 @@ finish: MOVL 12(SP), BX // nsec MOVL BP, SP // Restore real SP - MOVL $0, m_vdsoSP(SI) + // 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. + MOVL 4(SP), CX + MOVL CX, m_vdsoSP(SI) + MOVL 0(SP), CX + MOVL CX, m_vdsoPC(SI) // sec is in AX, nsec in BX // convert to DX:AX nsec |