aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2017-07-17 14:18:49 -0400
committerAustin Clements <austin@google.com>2017-07-18 14:35:35 +0000
commitc2c07c798940f484eece7a57af568783f8a02839 (patch)
tree56019ed8b76315fe6e1d97cba7fbeffe1bb9fc9e
parente9b9dfe3f71a8b9f5006616f877836c67eb4fba0 (diff)
downloadgo-c2c07c798940f484eece7a57af568783f8a02839.tar.gz
go-c2c07c798940f484eece7a57af568783f8a02839.zip
runtime: always use 2MB stacks on 64-bit Windows
Currently, Windows stacks are either 128kB or 2MB depending on whether the binary uses cgo. This is because we assume that Go system stacks and the small amount of C code invoked by the standard library can operate within smaller stacks, but general Windows C code assumes larger stacks. However, it's easy to call into arbitrary C code using the syscall package on Windows without ever importing cgo into a binary. Such binaries need larger system stacks even though they don't use cgo. Fix this on 64-bit by increasing the system stack size to 2MB always. This only costs address space, which is free enough on 64-bit to not worry about. We keep (for now) the existing heuristic on 32-bit, where address space comes at more of a premium. Updates #20975. Change-Id: Iaaaa9a2fcbadc825cddc797aaaea8d34ef8debf2 Reviewed-on: https://go-review.googlesource.com/49331 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
-rw-r--r--src/cmd/link/internal/ld/pe.go22
-rw-r--r--src/runtime/os_windows.go4
2 files changed, 15 insertions, 11 deletions
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index a64975cbe6..f26c83ee30 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -1308,30 +1308,32 @@ func Asmbpe(ctxt *Link) {
// size otherwise reserve will be rounded up to a
// larger size, as verified with VMMap.
- // Go code would be OK with 64k stacks, but we need larger stacks for cgo.
+ // On 64-bit, we always reserve 2MB stacks. "Pure" Go code is
+ // okay with much smaller stacks, but the syscall package
+ // makes it easy to call into arbitrary C code without cgo,
+ // and system calls even in "pure" Go code are actually C
+ // calls that may need more stack than we think.
//
// The default stack reserve size affects only the main
// thread, ctrlhandler thread, and profileloop thread. For
// these, it must be greater than the stack size assumed by
// externalthreadhandler.
//
- // For other threads we specify stack size in runtime explicitly
- // (runtime knows whether cgo is enabled or not).
+ // For other threads we specify stack size in runtime explicitly.
// For these, the reserve must match STACKSIZE in
// runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent
// CreateThread parameter in runtime.newosproc.
+ oh64.SizeOfStackReserve = 0x00200000
+ oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
+
+ // 32-bit is trickier since there much less address space to
+ // work with. Here we use large stacks only in cgo binaries as
+ // a compromise.
if !iscgo {
- oh64.SizeOfStackReserve = 0x00020000
oh.SizeOfStackReserve = 0x00020000
- oh64.SizeOfStackCommit = 0x00001000
oh.SizeOfStackCommit = 0x00001000
} else {
- oh64.SizeOfStackReserve = 0x00200000
oh.SizeOfStackReserve = 0x00100000
-
- // account for 2 guard pages
- oh64.SizeOfStackCommit = 0x00200000 - 0x2000
-
oh.SizeOfStackCommit = 0x00100000 - 0x2000
}
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 60fc8e590b..233cc165aa 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -622,7 +622,9 @@ func semacreate(mp *m) {
//go:nosplit
func newosproc(mp *m, stk unsafe.Pointer) {
const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
- thandle := stdcall6(_CreateThread, 0, 0x20000,
+ // stackSize must match SizeOfStackReserve in cmd/link/internal/ld/pe.go.
+ const stackSize = 0x00200000*_64bit + 0x00020000*(1-_64bit)
+ thandle := stdcall6(_CreateThread, 0, stackSize,
funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
_STACK_SIZE_PARAM_IS_A_RESERVATION, 0)