]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: always use 2MB stacks on 64-bit Windows
authorAustin Clements <austin@google.com>
Mon, 17 Jul 2017 18:18:49 +0000 (14:18 -0400)
committerAustin Clements <austin@google.com>
Tue, 18 Jul 2017 14:35:35 +0000 (14:35 +0000)
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>
src/cmd/link/internal/ld/pe.go
src/runtime/os_windows.go

index a64975cbe6e2c2e3ec67937062b59fff2a512fe1..f26c83ee30e25537126a0e10eb9c48d121398e0f 100644 (file)
@@ -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
        }
 
index 60fc8e590bc0becb833dfb550d19f19842e977d1..233cc165aa39ef32ddd13ca1d80435709fbcb2bf 100644 (file)
@@ -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)