diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index c0bfcb7ade..cc31e5c657 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -802,6 +802,14 @@ nosave: MOVL AX, ret+16(FP) RET +#ifdef GOOS_windows +// Dummy TLS that's used on Windows so that we don't crash trying +// to restore the G register in needm. needm and its callees are +// very careful never to actually use the G, the TLS just can't be +// unset since we're in Go code. +GLOBL zeroTLS<>(SB),RODATA,$const_tlsSize +#endif + // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) // See cgocall.go for more details. TEXT ·cgocallback(SB),NOSPLIT,$24-24 @@ -825,6 +833,15 @@ TEXT ·cgocallback(SB),NOSPLIT,$24-24 MOVQ BX, savedm-8(SP) // saved copy of oldm JMP havem needm: +#ifdef GOOS_windows + // Set up a dummy TLS value. needm is careful not to use it, + // but it needs to be there to prevent autogenerated code from + // crashing when it loads from it. + // We don't need to clear it or anything later because needm + // will set up TLS properly. + MOVQ $zeroTLS<>(SB), DI + CALL runtime·settls(SB) +#endif // 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. diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index e5f948ec86..402d49ac82 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -482,17 +482,24 @@ type g struct { gcAssistBytes int64 } +const ( + // tlsSlots is the number of pointer-sized slots reserved for TLS on some platforms, + // like Windows. + tlsSlots = 6 + tlsSize = tlsSlots * sys.PtrSize +) + type m struct { g0 *g // goroutine with scheduling stack morebuf gobuf // gobuf arg to morestack divmod uint32 // div/mod denominator for arm - known to liblink // Fields not known to debuggers. - procid uint64 // for debuggers, but offset not hard-coded - gsignal *g // signal-handling g - goSigStack gsignalStack // Go-allocated signal handling stack - sigmask sigset // storage for saved signal mask - tls [6]uintptr // thread-local storage (for x86 extern register) + procid uint64 // for debuggers, but offset not hard-coded + gsignal *g // signal-handling g + goSigStack gsignalStack // Go-allocated signal handling stack + sigmask sigset // storage for saved signal mask + tls [tlsSlots]uintptr // thread-local storage (for x86 extern register) mstartfn func() curg *g // current running goroutine caughtsig guintptr // goroutine running during fatal signal