mirror of
https://github.com/golang/go
synced 2024-11-26 06:17:57 -07:00
runtime: bypass ABI wrapper when calling needm on Windows
On Windows, when calling into needm in cgocallback on a new thread that is unknown to the Go runtime, we currently call through an ABI wrapper. The ABI wrapper tries to restore the G register from TLS. On other platforms, TLS is set up just enough that the wrapper will simply load a nil g from TLS, but on Windows TLS isn't set up at all, so there's nowhere for the wrapper to load from. So, bypass the wrapper in the call to needm. needm takes no arguments and returns no results so there are no special ABI considerations, except that we must clear X15 which is used as a zero register in Go code (a function normally performed by the ABI wrapper). needm is also otherwise already special and carefully crafted to avoid doing anything that would require a valid G or M, at least until it is able to create one. While we're here, this change simplifies setg so that it doesn't set up TLS on Windows and instead provides an OS-specific osSetupTLS to do that. The result of this is that setg(nil) no longer clears the TLS space pointer on Windows. There's exactly one place this is used (dropm) where it doesn't matter anymore, and an empty TLS means that setg's wrapper will crash on the return path. Another result is that the G slot in the TLS will be properly cleared, however, which isn't true today. For #40724. Change-Id: I65c3d924a3b16abe667b06fd91d467d6d5da31d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/303070 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
771c57e68e
commit
fef5a15396
@ -796,7 +796,18 @@ TEXT ·cgocallback(SB),NOSPLIT,$24-24
|
||||
MOVQ BX, savedm-8(SP) // saved copy of oldm
|
||||
JMP havem
|
||||
needm:
|
||||
MOVQ $runtime·needm(SB), AX
|
||||
// On some platforms (Windows) we cannot call needm through
|
||||
// an ABI wrapper because there's no TLS set up, and the ABI
|
||||
// wrapper will try to restore the G register (R14) from TLS.
|
||||
// Clear X15 because Go expects it and we're not calling
|
||||
// through a wrapper, but otherwise avoid setting the G
|
||||
// register in the wrapper and call needm directly. It
|
||||
// takes no arguments and doesn't return any values so
|
||||
// there's no need to handle that. Clear R14 so that there's
|
||||
// a bad value in there, in case needm tries to use it.
|
||||
XORPS X15, X15
|
||||
XORQ R14, R14
|
||||
MOVQ $runtime·needm<ABIInternal>(SB), AX
|
||||
CALL AX
|
||||
MOVQ $0, savedm-8(SP) // dropm on return
|
||||
get_tls(CX)
|
||||
@ -890,9 +901,17 @@ havem:
|
||||
// for the duration of the call. Since the call is over, return it with dropm.
|
||||
MOVQ savedm-8(SP), BX
|
||||
CMPQ BX, $0
|
||||
JNE 3(PC)
|
||||
JNE done
|
||||
MOVQ $runtime·dropm(SB), AX
|
||||
CALL AX
|
||||
#ifdef GOOS_windows
|
||||
// We need to clear the TLS pointer in case the next
|
||||
// thread that comes into Go tries to reuse that space
|
||||
// but uses the same M.
|
||||
XORQ DI, DI
|
||||
CALL runtime·settls(SB)
|
||||
#endif
|
||||
done:
|
||||
|
||||
// Done!
|
||||
RET
|
||||
@ -901,16 +920,6 @@ havem:
|
||||
// set g. for use by needm.
|
||||
TEXT runtime·setg(SB), NOSPLIT, $0-8
|
||||
MOVQ gg+0(FP), BX
|
||||
#ifdef GOOS_windows
|
||||
CMPQ BX, $0
|
||||
JNE settls
|
||||
MOVQ $0, 0x28(GS)
|
||||
RET
|
||||
settls:
|
||||
MOVQ g_m(BX), AX
|
||||
LEAQ m_tls(AX), AX
|
||||
MOVQ AX, 0x28(GS)
|
||||
#endif
|
||||
get_tls(CX)
|
||||
MOVQ BX, g(CX)
|
||||
RET
|
||||
|
@ -1883,6 +1883,10 @@ func needm() {
|
||||
// Store the original signal mask for use by minit.
|
||||
mp.sigmask = sigmask
|
||||
|
||||
// Install TLS on some platforms (previously setg
|
||||
// would do this if necessary).
|
||||
osSetupTLS(mp)
|
||||
|
||||
// Install g (= m->g0) and set the stack bounds
|
||||
// to match the current stack. We don't actually know
|
||||
// how big the stack is, like we don't know how big any
|
||||
|
@ -518,3 +518,11 @@ wall:
|
||||
useQPC:
|
||||
JMP runtime·nowQPC(SB)
|
||||
RET
|
||||
|
||||
// func osSetupTLS(mp *m)
|
||||
// Setup TLS. for use by needm on Windows.
|
||||
TEXT runtime·osSetupTLS(SB),NOSPLIT,$0-8
|
||||
MOVQ mp+0(FP), AX
|
||||
LEAQ m_tls(AX), DI
|
||||
CALL runtime·settls(SB)
|
||||
RET
|
||||
|
11
src/runtime/tls_stub.go
Normal file
11
src/runtime/tls_stub.go
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2021 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.
|
||||
|
||||
//go:build (windows && !amd64) || !windows
|
||||
// +build windows,!amd64 !windows
|
||||
|
||||
package runtime
|
||||
|
||||
//go:nosplit
|
||||
func osSetupTLS(mp *m) {}
|
10
src/runtime/tls_windows_amd64.go
Normal file
10
src/runtime/tls_windows_amd64.go
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2021 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
|
||||
|
||||
// osSetupTLS is called by needm to set up TLS for non-Go threads.
|
||||
//
|
||||
// Defined in assembly.
|
||||
func osSetupTLS(mp *m)
|
Loading…
Reference in New Issue
Block a user