[go] runtime: query thread stack size from OS on Windows

89 views
Skip to first unread message

Austin Clements (Gerrit)

unread,
Jun 21, 2018, 12:23:00 PM6/21/18
to Ian Lance Taylor, Alex Brainman, goph...@pubsubhelper.golang.org, Austin Clements, golang-co...@googlegroups.com

Austin Clements would like Ian Lance Taylor and Alex Brainman to review this change.

View Change

runtime: query thread stack size from OS on Windows

Currently, on Windows, the thread stack size is set or assumed in many
different places. In non-cgo binaries, both the Go linker and the
runtime have a copy of the stack size, the Go linker sets the size of
the main thread stack, and the runtime sets the size of other thread
stacks. In cgo binaries, the external linker sets the main thread
stack size, the runtime assumes the size of the main thread stack will
be the same as used by the Go linker, and the cgo entry code assumes
the same.

Furthermore, users can change the main thread stack size using
editbin, so the runtime doesn't even really know what size it is, and
user C code can create threads with unknown thread stack sizes, which
we also assume have the same default stack size.

This is all a mess.

Fix the corner cases of this and the duplication of knowledge between
the linker and the runtime by querying the OS for the stack bounds
during thread setup. Furthermore, we unify all of this into just
runtime.minit for both cgo and non-cgo binaries and for the main
thread, other runtime-created threads, and C-created threads.

Updates #20975.

Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
---
M src/cmd/link/internal/ld/pe.go
M src/runtime/cgo/gcc_windows_386.c
M src/runtime/cgo/gcc_windows_amd64.c
M src/runtime/crash_cgo_test.go
M src/runtime/defs_windows_386.go
M src/runtime/defs_windows_amd64.go
M src/runtime/os_windows.go
M src/runtime/proc.go
M src/runtime/sys_windows_386.s
M src/runtime/sys_windows_amd64.s
A src/runtime/testdata/testprogcgo/bigstack_windows.go
11 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 3b7df9a..efd971c 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -845,15 +845,18 @@
// 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
+ // The default stack reserve size directly 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.
- // For these, the reserve must match STACKSIZE in
- // runtime/cgo/gcc_windows_{386,amd64}.c and osStackSize in
- // runtime/os_windows.go.
+ // For other threads, the runtime explicitly asks the kernel
+ // to use the default stack size so that all stacks are
+ // consistent.
+ //
+ // At thread start, in minit, the runtime queries the OS for
+ // the actual stack bounds so that the stack size doesn't need
+ // to be hard-coded into the runtime.
oh64.SizeOfStackReserve = 0x00200000
if !iscgo {
oh64.SizeOfStackCommit = 0x00001000
diff --git a/src/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c
index e80a564..f2ff710 100644
--- a/src/runtime/cgo/gcc_windows_386.c
+++ b/src/runtime/cgo/gcc_windows_386.c
@@ -11,16 +11,9 @@

static void threadentry(void*);

-/* 1MB is default stack size for 32-bit Windows.
- Allocation granularity on Windows is typically 64 KB.
- This constant must match SizeOfStackReserve in ../cmd/link/internal/ld/pe.go. */
-#define STACKSIZE (1*1024*1024)
-
void
x_cgo_init(G *g)
{
- int tmp;
- g->stacklo = (uintptr)&tmp - STACKSIZE + 8*1024;
}


@@ -44,8 +37,7 @@
ts = *(ThreadStart*)v;
free(v);

- ts.g->stackhi = (uintptr)&ts;
- ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;
+ // minit queries stack bounds from the OS.

/*
* Set specific keys in thread local storage.
diff --git a/src/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c
index 75a7dc8..511ab44 100644
--- a/src/runtime/cgo/gcc_windows_amd64.c
+++ b/src/runtime/cgo/gcc_windows_amd64.c
@@ -11,16 +11,9 @@

static void threadentry(void*);

-/* 2MB is default stack size for 64-bit Windows.
- Allocation granularity on Windows is typically 64 KB.
- This constant must match SizeOfStackReserve in ../cmd/link/internal/ld/pe.go. */
-#define STACKSIZE (2*1024*1024)
-
void
x_cgo_init(G *g)
{
- int tmp;
- g->stacklo = (uintptr)&tmp - STACKSIZE + 8*1024;
}


@@ -44,8 +37,7 @@
ts = *(ThreadStart*)v;
free(v);

- ts.g->stackhi = (uintptr)&ts;
- ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;
+ // minit queries stack bounds from the OS.

/*
* Set specific keys in thread local storage.
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index d8f75a4..6cfb209 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -489,3 +489,17 @@
t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
}
}
+
+func TestCgoBigStack(t *testing.T) {
+ // Test that C code can use the large Windows stack without
+ // crashing Go.
+ if runtime.GOOS != "windows" {
+ t.Skip("skipping windows specific test")
+ }
+ t.Parallel()
+ got := runTestProg(t, "testprogcgo", "BigStack")
+ want := "OK\n"
+ if got != want {
+ t.Errorf("expected %q got %v", want, got)
+ }
+}
diff --git a/src/runtime/defs_windows_386.go b/src/runtime/defs_windows_386.go
index bac6ce7..589a788 100644
--- a/src/runtime/defs_windows_386.go
+++ b/src/runtime/defs_windows_386.go
@@ -129,3 +129,13 @@
anon0 [8]byte
hevent *byte
}
+
+type memoryBasicInformation struct {
+ baseAddress uintptr
+ allocationBase uintptr
+ allocationProtect uint32
+ regionSize uintptr
+ state uint32
+ protect uint32
+ type_ uint32
+}
diff --git a/src/runtime/defs_windows_amd64.go b/src/runtime/defs_windows_amd64.go
index 6e04568..1e173e9 100644
--- a/src/runtime/defs_windows_amd64.go
+++ b/src/runtime/defs_windows_amd64.go
@@ -151,3 +151,13 @@
anon0 [8]byte
hevent *byte
}
+
+type memoryBasicInformation struct {
+ baseAddress uintptr
+ allocationBase uintptr
+ allocationProtect uint32
+ regionSize uintptr
+ state uint32
+ protect uint32
+ type_ uint32
+}
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index a4df970..a879e4b 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -45,6 +45,7 @@
//go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
+//go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll"
//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
//go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
@@ -92,6 +93,7 @@
_SwitchToThread,
_VirtualAlloc,
_VirtualFree,
+ _VirtualQuery,
_WSAGetOverlappedResult,
_WaitForSingleObject,
_WriteConsoleW,
@@ -291,9 +293,6 @@
}
}

-// osStackSize must match SizeOfStackReserve in ../cmd/link/internal/ld/pe.go.
-var osStackSize uintptr = 0x00200000*_64bit + 0x00100000*(1-_64bit)
-
func osinit() {
asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
usleep2Addr = unsafe.Pointer(funcPC(usleep2))
@@ -322,15 +321,6 @@
// equivalent threads that all do a mix of GUI, IO, computations, etc.
// In such context dynamic priority boosting does nothing but harm, so we turn it off.
stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
-
- // Fix the entry thread's stack bounds, since runtime entry
- // assumed we were on a tiny stack. If this is a cgo binary,
- // x_cgo_init already fixed these.
- if !iscgo {
- g0.stack.lo = g0.stack.hi - osStackSize + 8*1024
- g0.stackguard0 = g0.stack.lo + _StackGuard
- g0.stackguard1 = g0.stackguard0
- }
}

func nanotime() int64
@@ -631,10 +621,11 @@
//go:nowritebarrierrec
//go:nosplit
func newosproc(mp *m) {
- const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
- thandle := stdcall6(_CreateThread, 0, osStackSize,
+ // Pass 0 for the stack size to use the default for this binary.
+ const stackSizeFromPEHeader = 0
+ thandle := stdcall6(_CreateThread, 0, stackSizeFromPEHeader,
funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
- _STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
+ 0, 0)

if thandle == 0 {
if atomic.Load(&exiting) != 0 {
@@ -699,8 +690,24 @@
var thandle uintptr
stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
atomic.Storeuintptr(&getg().m.thread, thandle)
+
+ // Query the true stack base from the OS. Currently we're
+ // running on a small assumed stack.
+ var mbi memoryBasicInformation
+ res := stdcall3(_VirtualQuery, uintptr(unsafe.Pointer(&mbi)), uintptr(unsafe.Pointer(&mbi)), unsafe.Sizeof(mbi))
+ if res == 0 {
+ throw("VirtualQuery for stack base failed")
+ }
+ base := mbi.allocationBase + 1024
+ g0 := getg()
+ g0.stack.lo = base
+ g0.stackguard0 = g0.stack.lo + _StackGuard
+ g0.stackguard1 = g0.stackguard0
+ stackcheck()
}

+func stackcheck()
+
// Called from dropm to undo the effect of an minit.
//go:nosplit
func unminit() {
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 36c74a1..22132bf 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -1231,6 +1231,7 @@
if osStack {
// Initialize stack bounds from system stack.
// Cgo may have left stack size in stack.hi.
+ // minit may update the stack bounds.
size := _g_.stack.hi
if size == 0 {
size = 8192 * sys.StackGuardMultiplier
diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
index abb6bad..d6f3997 100644
--- a/src/runtime/sys_windows_386.s
+++ b/src/runtime/sys_windows_386.s
@@ -315,8 +315,7 @@
// Layout new m scheduler stack on os stack.
MOVL SP, AX
MOVL AX, (g_stack+stack_hi)(DX)
- SUBL runtimeĀ·osStackSize(SB), AX // stack size
- ADDL $(8*1024), AX
+ SUBL $(64*1024), AX // initial stack size
MOVL AX, (g_stack+stack_lo)(DX)
ADDL $const__StackGuard, AX
MOVL AX, g_stackguard0(DX)
diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
index 8a12cda..f682e8a 100644
--- a/src/runtime/sys_windows_amd64.s
+++ b/src/runtime/sys_windows_amd64.s
@@ -363,8 +363,7 @@
// Layout new m scheduler stack on os stack.
MOVQ SP, AX
MOVQ AX, (g_stack+stack_hi)(DX)
- SUBQ runtimeĀ·osStackSize(SB), AX // stack size
- ADDQ $(8*1024), AX
+ SUBQ $(64*1024), AX // inital stack size
MOVQ AX, (g_stack+stack_lo)(DX)
ADDQ $const__StackGuard, AX
MOVQ AX, g_stackguard0(DX)
diff --git a/src/runtime/testdata/testprogcgo/bigstack_windows.go b/src/runtime/testdata/testprogcgo/bigstack_windows.go
new file mode 100644
index 0000000..150928a
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/bigstack_windows.go
@@ -0,0 +1,31 @@
+// Copyright 2018 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 main
+
+/*
+extern void goBigStack1(char*);
+
+static void bigStack(void) {
+ char x[256<<10];
+ goBigStack1(x);
+}
+*/
+import "C"
+
+func init() {
+ register("BigStack", BigStack)
+}
+
+func BigStack() {
+ // Use a lot of stack and call back into Go.
+ C.bigStack()
+}
+
+var alwaysFalse bool
+
+//export goBigStack1
+func goBigStack1(x *C.char) {
+ println("OK")
+}

To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
Gerrit-Change-Number: 120336
Gerrit-PatchSet: 1
Gerrit-Owner: Austin Clements <aus...@google.com>
Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
Gerrit-Reviewer: Austin Clements <aus...@google.com>
Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
Gerrit-MessageType: newchange

Gobot Gobot (Gerrit)

unread,
Jun 21, 2018, 12:23:10 PM6/21/18
to Austin Clements, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Alex Brainman, golang-co...@googlegroups.com

TryBots beginning. Status page: https://farmer.golang.org/try?commit=0f575d4c

View Change

    To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
    Gerrit-Change-Number: 120336
    Gerrit-PatchSet: 1
    Gerrit-Owner: Austin Clements <aus...@google.com>
    Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
    Gerrit-Reviewer: Austin Clements <aus...@google.com>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-CC: Gobot Gobot <go...@golang.org>
    Gerrit-Comment-Date: Thu, 21 Jun 2018 16:23:07 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Austin Clements (Gerrit)

    unread,
    Jun 21, 2018, 12:25:20 PM6/21/18
    to Austin Clements, goph...@pubsubhelper.golang.org, Gobot Gobot, Ian Lance Taylor, Alex Brainman, golang-co...@googlegroups.com

    We may want to go ahead and do this for Go 1.11. It's obviously a more complicated change than the parent CL, but I'm also not convinced I got all of the code paths in the previous CL since we set up stacks in a surprising variety of ways. This CL is a much cleaner and more complete solution.

    View Change

      To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
      Gerrit-Change-Number: 120336
      Gerrit-PatchSet: 1
      Gerrit-Owner: Austin Clements <aus...@google.com>
      Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
      Gerrit-Reviewer: Austin Clements <aus...@google.com>
      Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
      Gerrit-CC: Gobot Gobot <go...@golang.org>
      Gerrit-Comment-Date: Thu, 21 Jun 2018 16:25:18 +0000

      Gobot Gobot (Gerrit)

      unread,
      Jun 21, 2018, 12:27:32 PM6/21/18
      to Austin Clements, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Alex Brainman, golang-co...@googlegroups.com

      Build is still in progress...
      This change failed on misc-vet-vetall:
      See https://storage.googleapis.com/go-build-log/0f575d4c/misc-vet-vetall_b850a9d3.log

      Consult https://build.golang.org/ to see whether it's a new failure. Other builds still in progress; subsequent failure notices suppressed until final report.

      View Change

        To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: go
        Gerrit-Branch: master
        Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
        Gerrit-Change-Number: 120336
        Gerrit-PatchSet: 1
        Gerrit-Owner: Austin Clements <aus...@google.com>
        Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
        Gerrit-Reviewer: Austin Clements <aus...@google.com>
        Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
        Gerrit-CC: Gobot Gobot <go...@golang.org>
        Gerrit-Comment-Date: Thu, 21 Jun 2018 16:27:30 +0000

        Austin Clements (Gerrit)

        unread,
        Jun 21, 2018, 12:31:42 PM6/21/18
        to Austin Clements, Ian Lance Taylor, Alex Brainman, goph...@pubsubhelper.golang.org, Gobot Gobot, golang-co...@googlegroups.com

        Austin Clements uploaded patch set #2 to this change.

        View Change

        runtime: query thread stack size from OS on Windows

        Currently, on Windows, the thread stack size is set or assumed in many
        different places. In non-cgo binaries, both the Go linker and the
        runtime have a copy of the stack size, the Go linker sets the size of
        the main thread stack, and the runtime sets the size of other thread
        stacks. In cgo binaries, the external linker sets the main thread
        stack size, the runtime assumes the size of the main thread stack will
        be the same as used by the Go linker, and the cgo entry code assumes
        the same.

        Furthermore, users can change the main thread stack size using
        editbin, so the runtime doesn't even really know what size it is, and
        user C code can create threads with unknown thread stack sizes, which
        we also assume have the same default stack size.

        This is all a mess.

        Fix the corner cases of this and the duplication of knowledge between
        the linker and the runtime by querying the OS for the stack bounds
        during thread setup. Furthermore, we unify all of this into just
        runtime.minit for both cgo and non-cgo binaries and for the main
        thread, other runtime-created threads, and C-created threads.

        Updates #20975.

        Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
        ---
        M src/cmd/link/internal/ld/pe.go
        M src/cmd/vet/all/whitelist/386.txt
        M src/cmd/vet/all/whitelist/amd64.txt
        M src/cmd/vet/all/whitelist/nacl_amd64p32.txt

        M src/runtime/cgo/gcc_windows_386.c
        M src/runtime/cgo/gcc_windows_amd64.c
        M src/runtime/crash_cgo_test.go
        M src/runtime/defs_windows_386.go
        M src/runtime/defs_windows_amd64.go
        M src/runtime/os_windows.go
        M src/runtime/proc.go
        A src/runtime/stubs_x86.go

        M src/runtime/sys_windows_386.s
        M src/runtime/sys_windows_amd64.s
        A src/runtime/testdata/testprogcgo/bigstack_windows.go
        15 files changed, 108 insertions(+), 47 deletions(-)

        To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: go
        Gerrit-Branch: master
        Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
        Gerrit-Change-Number: 120336
        Gerrit-PatchSet: 2
        Gerrit-Owner: Austin Clements <aus...@google.com>
        Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
        Gerrit-Reviewer: Austin Clements <aus...@google.com>
        Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
        Gerrit-CC: Gobot Gobot <go...@golang.org>
        Gerrit-MessageType: newpatchset

        Gobot Gobot (Gerrit)

        unread,
        Jun 21, 2018, 12:31:52 PM6/21/18
        to Austin Clements, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Alex Brainman, golang-co...@googlegroups.com

        TryBots beginning. Status page: https://farmer.golang.org/try?commit=7c655615

        View Change

          To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: go
          Gerrit-Branch: master
          Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
          Gerrit-Change-Number: 120336
          Gerrit-PatchSet: 2
          Gerrit-Owner: Austin Clements <aus...@google.com>
          Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
          Gerrit-Reviewer: Austin Clements <aus...@google.com>
          Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
          Gerrit-CC: Gobot Gobot <go...@golang.org>
          Gerrit-Comment-Date: Thu, 21 Jun 2018 16:31:50 +0000

          Gobot Gobot (Gerrit)

          unread,
          Jun 21, 2018, 12:43:27 PM6/21/18
          to Austin Clements, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Alex Brainman, golang-co...@googlegroups.com

          TryBots are happy.

          Patch set 2:TryBot-Result +1

          View Change

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 2
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-Comment-Date: Thu, 21 Jun 2018 16:43:24 +0000
            Gerrit-HasComments: No
            Gerrit-Has-Labels: Yes
            Gerrit-MessageType: comment

            Ian Lance Taylor (Gerrit)

            unread,
            Jun 21, 2018, 1:43:35 PM6/21/18
            to Austin Clements, goph...@pubsubhelper.golang.org, Gobot Gobot, Alex Brainman, golang-co...@googlegroups.com

            Patch set 2:Code-Review +2

            View Change

            1 comment:

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 2
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-Comment-Date: Thu, 21 Jun 2018 17:43:32 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: Yes
            Gerrit-MessageType: comment

            Austin Clements (Gerrit)

            unread,
            Jun 22, 2018, 3:22:57 PM6/22/18
            to Austin Clements, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Gobot Gobot, Alex Brainman, golang-co...@googlegroups.com

            Alex, if you have a minute to sanity check my VirtualQuery approach to finding the stack base, I would appreciate it. The same technique is used by Firefox (https://dxr.mozilla.org/mozilla-central/source/js/xpconnect/src/XPCJSContext.cpp#939), so I'm pretty sure it's sound.

            View Change

            1 comment:

              • Even though it's not used, it's useful documentation to add a line for this struct to defs_windows. […]

                Done

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 2
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-Comment-Date: Fri, 22 Jun 2018 19:22:54 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: No
            Comment-In-Reply-To: Ian Lance Taylor <ia...@golang.org>
            Gerrit-MessageType: comment

            Austin Clements (Gerrit)

            unread,
            Jun 22, 2018, 3:23:20 PM6/22/18
            to Austin Clements, Ian Lance Taylor, Gobot Gobot, Alex Brainman, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

            Austin Clements uploaded patch set #3 to this change.

            View Change

            runtime: query thread stack size from OS on Windows

            Currently, on Windows, the thread stack size is set or assumed in many
            different places. In non-cgo binaries, both the Go linker and the
            runtime have a copy of the stack size, the Go linker sets the size of
            the main thread stack, and the runtime sets the size of other thread
            stacks. In cgo binaries, the external linker sets the main thread
            stack size, the runtime assumes the size of the main thread stack will
            be the same as used by the Go linker, and the cgo entry code assumes
            the same.

            Furthermore, users can change the main thread stack size using
            editbin, so the runtime doesn't even really know what size it is, and
            user C code can create threads with unknown thread stack sizes, which
            we also assume have the same default stack size.

            This is all a mess.

            Fix the corner cases of this and the duplication of knowledge between
            the linker and the runtime by querying the OS for the stack bounds
            during thread setup. Furthermore, we unify all of this into just
            runtime.minit for both cgo and non-cgo binaries and for the main
            thread, other runtime-created threads, and C-created threads.

            Updates #20975.

            Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            ---
            M src/cmd/link/internal/ld/pe.go
            M src/cmd/vet/all/whitelist/386.txt
            M src/cmd/vet/all/whitelist/amd64.txt
            M src/cmd/vet/all/whitelist/nacl_amd64p32.txt
            M src/runtime/cgo/gcc_windows_386.c
            M src/runtime/cgo/gcc_windows_amd64.c
            M src/runtime/crash_cgo_test.go
            M src/runtime/defs_windows.go

            M src/runtime/defs_windows_386.go
            M src/runtime/defs_windows_amd64.go
            M src/runtime/os_windows.go
            M src/runtime/proc.go
            A src/runtime/stubs_x86.go

            M src/runtime/sys_windows_386.s
            M src/runtime/sys_windows_amd64.s
            A src/runtime/testdata/testprogcgo/bigstack_windows.go
            16 files changed, 109 insertions(+), 47 deletions(-)

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 3
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-MessageType: newpatchset

            Alex Brainman (Gerrit)

            unread,
            Jun 22, 2018, 6:45:09 PM6/22/18
            to Austin Clements, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Gobot Gobot, golang-co...@googlegroups.com

            Alex, if you have a minute to sanity check my VirtualQuery approach to finding the stack base, I would appreciate it. The same technique is used by Firefox (https://dxr.mozilla.org/mozilla-central/source/js/xpconnect/src/XPCJSContext.cpp#939), so I'm pretty sure it's sound.

            I am not sure about your approach, but if you want to do it, do it.

            My biggest concern, is we do not have a test to reproduce the problem that you are fixing. You took away consts that we used everywhere, and now rely on what VirtualQuery returns plus some logic you copied somewhere. It would be nice at least verify the numbers you get are sane.

            As far as I understand your change affects only cgo code, so, hopefully, not many people use cgo.

            Alex

            View Change

            4 comments:

            • File src/runtime/os_windows.go:

              • Patch Set #3, Line 625: stackSizeFromPEHeader

                Introducing stackSizeFromPEHeader const just confuses me. I would just use 0 instead. People will lookup CreateThread documentation to see how it works.

              • Patch Set #3, Line 628: ,

                Why is that OK to replace _STACK_SIZE_PARAM_IS_A_RESERVATION with 0?

              • Patch Set #3, Line 699: throw("VirtualQuery for stack base failed")

                You can call GetLastError to get details about why VirtualQuery failed, if you want. And print it as part of throw message.

              • Patch Set #3, Line 701: base := mbi.allocationBase + 1024

                Why adding 1024. You need some comment to explain.

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 3
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-Comment-Date: Fri, 22 Jun 2018 22:45:03 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: No
            Gerrit-MessageType: comment

            Austin Clements (Gerrit)

            unread,
            Jun 28, 2018, 5:38:43 PM6/28/18
            to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, Gobot Gobot, golang-co...@googlegroups.com

            Patch Set 3:

            (4 comments)

            Alex, if you have a minute to sanity check my VirtualQuery approach to finding the stack base, I would appreciate it. The same technique is used by Firefox (https://dxr.mozilla.org/mozilla-central/source/js/xpconnect/src/XPCJSContext.cpp#939), so I'm pretty sure it's sound.

            I am not sure about your approach, but if you want to do it, do it.

            My biggest concern, is we do not have a test to reproduce the problem that you are fixing. You took away consts that we used everywhere, and now rely on what VirtualQuery returns plus some logic you copied somewhere. It would be nice at least verify the numbers you get are sane.

            I took away consts that weren't really const. :)

            I'm not sure what you mean by "some logic I copied somewhere". My goal was to reduce the amount of copied logic (and to make it more correct).

            I've beefed up the test I added. That test did reproduce the original problem (which was fixed by the previous CL), but the new version more specifically tests this CL.

            And I've added more verification of the numbers from VirtualQuery in addition to the stackcheck().

            As far as I understand your change affects only cgo code, so, hopefully, not many people use cgo.

            Alex

            View Change

            4 comments:

              • Introducing stackSizeFromPEHeader const just confuses me. I would just use 0 instead. […]

                Okay.

              • We're not passing a stack size, so this flag would be a no-op.

              • You can call GetLastError to get details about why VirtualQuery failed, if you want. […]

                Done

              • Done

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 3
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-Comment-Date: Thu, 28 Jun 2018 21:38:40 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: No
            Comment-In-Reply-To: Alex Brainman <alex.b...@gmail.com>
            Gerrit-MessageType: comment

            Austin Clements (Gerrit)

            unread,
            Jun 28, 2018, 5:39:00 PM6/28/18
            to Austin Clements, Ian Lance Taylor, Gobot Gobot, Alex Brainman, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

            Austin Clements uploaded patch set #4 to this change.

            View Change

            runtime: query thread stack size from OS on Windows

            Currently, on Windows, the thread stack size is set or assumed in many
            different places. In non-cgo binaries, both the Go linker and the
            runtime have a copy of the stack size, the Go linker sets the size of
            the main thread stack, and the runtime sets the size of other thread
            stacks. In cgo binaries, the external linker sets the main thread
            stack size, the runtime assumes the size of the main thread stack will
            be the same as used by the Go linker, and the cgo entry code assumes
            the same.

            Furthermore, users can change the main thread stack size using
            editbin, so the runtime doesn't even really know what size it is, and
            user C code can create threads with unknown thread stack sizes, which
            we also assume have the same default stack size.

            This is all a mess.

            Fix the corner cases of this and the duplication of knowledge between
            the linker and the runtime by querying the OS for the stack bounds
            during thread setup. Furthermore, we unify all of this into just
            runtime.minit for both cgo and non-cgo binaries and for the main
            thread, other runtime-created threads, and C-created threads.

            Updates #20975.

            Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            ---
            M src/cmd/link/internal/ld/pe.go
            M src/cmd/vet/all/whitelist/386.txt
            M src/cmd/vet/all/whitelist/amd64.txt
            M src/cmd/vet/all/whitelist/nacl_amd64p32.txt
            M src/runtime/cgo/gcc_windows_386.c
            M src/runtime/cgo/gcc_windows_amd64.c
            M src/runtime/crash_cgo_test.go
            M src/runtime/defs_windows.go

            M src/runtime/defs_windows_386.go
            M src/runtime/defs_windows_amd64.go
            M src/runtime/os_windows.go
            M src/runtime/proc.go
            A src/runtime/stubs_x86.go

            M src/runtime/sys_windows_386.s
            M src/runtime/sys_windows_amd64.s
            A src/runtime/testdata/testprogcgo/bigstack_windows.go
            16 files changed, 142 insertions(+), 50 deletions(-)

            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
            Gerrit-Change-Number: 120336
            Gerrit-PatchSet: 4
            Gerrit-Owner: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
            Gerrit-Reviewer: Austin Clements <aus...@google.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
            Gerrit-MessageType: newpatchset

            Gobot Gobot (Gerrit)

            unread,
            Jun 28, 2018, 5:39:13 PM6/28/18
            to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

            TryBots beginning. Status page: https://farmer.golang.org/try?commit=f2d77670

            View Change

              To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: go
              Gerrit-Branch: master
              Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
              Gerrit-Change-Number: 120336
              Gerrit-PatchSet: 4
              Gerrit-Owner: Austin Clements <aus...@google.com>
              Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
              Gerrit-Reviewer: Austin Clements <aus...@google.com>
              Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
              Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
              Gerrit-Comment-Date: Thu, 28 Jun 2018 21:39:11 +0000

              Gobot Gobot (Gerrit)

              unread,
              Jun 28, 2018, 5:44:16 PM6/28/18
              to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

              Build is still in progress...

              This change failed on windows-386-2008:
              See https://storage.googleapis.com/go-build-log/f2d77670/windows-386-2008_61b69dff.log

              Consult https://build.golang.org/ to see whether it's a new failure. Other builds still in progress; subsequent failure notices suppressed until final report.

              View Change

                To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                Gerrit-Project: go
                Gerrit-Branch: master
                Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                Gerrit-Change-Number: 120336
                Gerrit-PatchSet: 4
                Gerrit-Owner: Austin Clements <aus...@google.com>
                Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                Gerrit-Reviewer: Austin Clements <aus...@google.com>
                Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                Gerrit-Comment-Date: Thu, 28 Jun 2018 21:44:13 +0000

                Gobot Gobot (Gerrit)

                unread,
                Jun 28, 2018, 5:48:58 PM6/28/18
                to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                1 of 19 TryBots failed:
                Failed on windows-386-2008: https://storage.googleapis.com/go-build-log/f2d77670/windows-386-2008_61b69dff.log

                Consult https://build.golang.org/ to see whether they are new failures.

                Patch set 4:TryBot-Result -1

                View Change

                  To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                  Gerrit-Project: go
                  Gerrit-Branch: master
                  Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                  Gerrit-Change-Number: 120336
                  Gerrit-PatchSet: 4
                  Gerrit-Owner: Austin Clements <aus...@google.com>
                  Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                  Gerrit-Reviewer: Austin Clements <aus...@google.com>
                  Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                  Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                  Gerrit-Comment-Date: Thu, 28 Jun 2018 21:48:56 +0000

                  Alex Brainman (Gerrit)

                  unread,
                  Jun 29, 2018, 6:26:45 AM6/29/18
                  to Austin Clements, goph...@pubsubhelper.golang.org, Gobot Gobot, Ian Lance Taylor, golang-co...@googlegroups.com

                  I took away consts that weren't really const. :)

                  This code was written by many people over many years. You cannot blame me for everything. :-)

                  I'm not sure what you mean by "some logic I copied somewhere". My goal was to reduce the amount of copied logic (and to make it more correct).

                  I've beefed up the test I added. That test did reproduce the original problem (which was fixed by the previous CL), but the new version more specifically tests this CL.

                  And I've added more verification of the numbers from VirtualQuery in addition to the stackcheck().

                  Yes, you put more checks in runtime and tests. Thank you very much.

                  Now we just need to work out why test fails. :-)

                  I will try and find some time to debug this on weekend.

                  Alex

                  View Change

                  2 comments:

                    • We're not passing a stack size, so this flag would be a no-op.

                    • I don't think you are correct.

                      From https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createthread
                      ```
                      STACK_SIZE_PARAM_IS_A_RESERVATION

                      The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies the commit size.
                      ```
                      So the fact that STACK_SIZE_PARAM_IS_A_RESERVATION is here, means we are not specifying "stack size" here, but "initial reserve size of the stack".

                      I don't believe we have test for this, so we should be careful changing this flag. This flag controls how much real memory allocated at the start of a thread, and this will affect every Go program memory usage.

                  To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                  Gerrit-Project: go
                  Gerrit-Branch: master
                  Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                  Gerrit-Change-Number: 120336
                  Gerrit-PatchSet: 4
                  Gerrit-Owner: Austin Clements <aus...@google.com>
                  Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                  Gerrit-Reviewer: Austin Clements <aus...@google.com>
                  Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                  Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                  Gerrit-Comment-Date: Fri, 29 Jun 2018 10:26:37 +0000
                  Gerrit-HasComments: Yes
                  Gerrit-Has-Labels: No
                  Comment-In-Reply-To: Alex Brainman <alex.b...@gmail.com>
                  Comment-In-Reply-To: Austin Clements <aus...@google.com>
                  Gerrit-MessageType: comment

                  Alex Brainman (Gerrit)

                  unread,
                  Jun 29, 2018, 7:32:20 AM6/29/18
                  to Austin Clements, goph...@pubsubhelper.golang.org, Gobot Gobot, Ian Lance Taylor, golang-co...@googlegroups.com


                  I will try and find some time to debug this on weekend.

                  Sorry I meant to say I will try to debug your CL 120857 failure.

                  Alex

                  View Change

                    To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                    Gerrit-Project: go
                    Gerrit-Branch: master
                    Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                    Gerrit-Change-Number: 120336
                    Gerrit-PatchSet: 4
                    Gerrit-Owner: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                    Gerrit-Reviewer: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                    Gerrit-Comment-Date: Fri, 29 Jun 2018 11:32:14 +0000

                    Austin Clements (Gerrit)

                    unread,
                    Jun 29, 2018, 10:48:30 AM6/29/18
                    to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Gobot Gobot, Ian Lance Taylor, golang-co...@googlegroups.com

                    Patch Set 4:

                    (2 comments)

                    I took away consts that weren't really const. :)

                    This code was written by many people over many years. You cannot blame me for everything. :-)

                    Oh! I definitely don't blame you. I've been so deep in the UNIX world for so long that dealing with Windows things often feels like I'm feeling around in the dark. I trust you to tell me if I'm about to walk into a wall.

                    I'm not sure what you mean by "some logic I copied somewhere". My goal was to reduce the amount of copied logic (and to make it more correct).

                    I've beefed up the test I added. That test did reproduce the original problem (which was fixed by the previous CL), but the new version more specifically tests this CL.

                    And I've added more verification of the numbers from VirtualQuery in addition to the stackcheck().

                    Yes, you put more checks in runtime and tests. Thank you very much.

                    I'm going to try to add a non-cgo test today as well (based on the DLL-building tests you pointed to in the issue).

                    Now we just need to work out why test fails. :-)

                    I'm a little perplexed by why only the 386 Windows 2008 trybot thinks STACK_SIZE_PARAM_IS_A_RESERVATION isn't defined, but I suppose I can define it if it's not defined without getting into trouble.

                    I will try and find some time to debug this on weekend.

                    Alex

                    View Change

                    2 comments:

                      • You mention issue #20975. […]

                        This CL affects both cgo and non-cgo code since minit runs in both cases. That was intentional, since users may editbin even a non-cgo binary to set a larger stack size if they're calling out to C code using syscall.

                    • File src/runtime/os_windows.go:

                      • I don't think you are correct. […]

                        Interesting. But the documentation on dwStackSize says "If this parameter is zero, the new thread uses the default size for the executable" which is what I want. If I pass both 0 and STACK_SIZE_PARAM_IS_A_RESERVATION it seems like it would either 1) ignore the flag because it's using the defaults from the executable anyway (presumably for both the reserve and commit sizes), or 2) reserve 0 bytes for the stack, which would definitely be bad :)

                    To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                    Gerrit-Project: go
                    Gerrit-Branch: master
                    Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                    Gerrit-Change-Number: 120336
                    Gerrit-PatchSet: 4
                    Gerrit-Owner: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                    Gerrit-Reviewer: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                    Gerrit-Comment-Date: Fri, 29 Jun 2018 14:48:28 +0000

                    Austin Clements (Gerrit)

                    unread,
                    Jun 29, 2018, 10:54:56 AM6/29/18
                    to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Gobot Gobot, Ian Lance Taylor, golang-co...@googlegroups.com

                    View Change

                    1 comment:

                      • Interesting. […]

                        Forgot to add: if I understand what you're saying, we do have tests for it: TestWindowsStackMemory and TestWindowsStackMemoryCgo. Each forces Go to create 100 threads and checks that the committed memory is small. Though TestWindowsStackMemoryCgo is marked as flaky (issue #22575, filed by you, actually :)

                    To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                    Gerrit-Project: go
                    Gerrit-Branch: master
                    Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                    Gerrit-Change-Number: 120336
                    Gerrit-PatchSet: 4
                    Gerrit-Owner: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                    Gerrit-Reviewer: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                    Gerrit-Comment-Date: Fri, 29 Jun 2018 14:54:52 +0000

                    Austin Clements (Gerrit)

                    unread,
                    Jun 29, 2018, 12:47:20 PM6/29/18
                    to Austin Clements, Ian Lance Taylor, Gobot Gobot, Alex Brainman, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

                    Austin Clements uploaded patch set #5 to this change.

                    View Change

                    runtime: query thread stack size from OS on Windows

                    Currently, on Windows, the thread stack size is set or assumed in many
                    different places. In non-cgo binaries, both the Go linker and the
                    runtime have a copy of the stack size, the Go linker sets the size of
                    the main thread stack, and the runtime sets the size of other thread
                    stacks. In cgo binaries, the external linker sets the main thread
                    stack size, the runtime assumes the size of the main thread stack will
                    be the same as used by the Go linker, and the cgo entry code assumes
                    the same.

                    Furthermore, users can change the main thread stack size using
                    editbin, so the runtime doesn't even really know what size it is, and
                    user C code can create threads with unknown thread stack sizes, which
                    we also assume have the same default stack size.

                    This is all a mess.

                    Fix the corner cases of this and the duplication of knowledge between
                    the linker and the runtime by querying the OS for the stack bounds
                    during thread setup. Furthermore, we unify all of this into just
                    runtime.minit for both cgo and non-cgo binaries and for the main
                    thread, other runtime-created threads, and C-created threads.

                    Updates #20975.

                    Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                    ---
                    M src/cmd/link/internal/ld/pe.go
                    M src/cmd/vet/all/whitelist/386.txt
                    M src/cmd/vet/all/whitelist/amd64.txt
                    M src/cmd/vet/all/whitelist/nacl_amd64p32.txt
                    M src/runtime/cgo/gcc_windows_386.c
                    M src/runtime/cgo/gcc_windows_amd64.c
                    M src/runtime/crash_cgo_test.go
                    M src/runtime/defs_windows.go

                    M src/runtime/defs_windows_386.go
                    M src/runtime/defs_windows_amd64.go
                    M src/runtime/os_windows.go
                    M src/runtime/proc.go
                    A src/runtime/stubs_x86.go
                    M src/runtime/sys_windows_386.s
                    M src/runtime/sys_windows_amd64.s
                    M src/runtime/syscall_windows_test.go
                    A src/runtime/testdata/testprogcgo/bigstack_windows.c
                    A src/runtime/testdata/testprogcgo/bigstack_windows.go
                    18 files changed, 208 insertions(+), 50 deletions(-)

                    To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                    Gerrit-Project: go
                    Gerrit-Branch: master
                    Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                    Gerrit-Change-Number: 120336
                    Gerrit-PatchSet: 5
                    Gerrit-Owner: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                    Gerrit-Reviewer: Austin Clements <aus...@google.com>
                    Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                    Gerrit-MessageType: newpatchset

                    Gobot Gobot (Gerrit)

                    unread,
                    Jun 29, 2018, 12:47:31 PM6/29/18
                    to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                    TryBots beginning. Status page: https://farmer.golang.org/try?commit=4de1384b

                    View Change

                      To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                      Gerrit-Project: go
                      Gerrit-Branch: master
                      Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                      Gerrit-Change-Number: 120336
                      Gerrit-PatchSet: 5
                      Gerrit-Owner: Austin Clements <aus...@google.com>
                      Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                      Gerrit-Reviewer: Austin Clements <aus...@google.com>
                      Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                      Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                      Gerrit-Comment-Date: Fri, 29 Jun 2018 16:47:28 +0000

                      Austin Clements (Gerrit)

                      unread,
                      Jun 29, 2018, 12:54:52 PM6/29/18
                      to Austin Clements, goph...@pubsubhelper.golang.org, Gobot Gobot, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                      PS5 adds a non-cgo test for stack size

                      View Change

                        To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                        Gerrit-Project: go
                        Gerrit-Branch: master
                        Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                        Gerrit-Change-Number: 120336
                        Gerrit-PatchSet: 5
                        Gerrit-Owner: Austin Clements <aus...@google.com>
                        Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                        Gerrit-Reviewer: Austin Clements <aus...@google.com>
                        Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                        Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                        Gerrit-Comment-Date: Fri, 29 Jun 2018 16:54:49 +0000

                        Gobot Gobot (Gerrit)

                        unread,
                        Jun 29, 2018, 12:57:49 PM6/29/18
                        to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                        TryBots are happy.

                        Patch set 5:TryBot-Result +1

                        View Change

                          To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: go
                          Gerrit-Branch: master
                          Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                          Gerrit-Change-Number: 120336
                          Gerrit-PatchSet: 5
                          Gerrit-Owner: Austin Clements <aus...@google.com>
                          Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                          Gerrit-Reviewer: Austin Clements <aus...@google.com>
                          Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                          Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                          Gerrit-Comment-Date: Fri, 29 Jun 2018 16:57:47 +0000

                          Alex Brainman (Gerrit)

                          unread,
                          Jun 30, 2018, 3:21:04 AM6/30/18
                          to Austin Clements, goph...@pubsubhelper.golang.org, Gobot Gobot, Ian Lance Taylor, golang-co...@googlegroups.com

                          I'm going to try to add a non-cgo test today as well (based on the DLL-building tests you pointed to in the issue).

                          I can see you have done that.

                          I'm a little perplexed by why only the 386 Windows 2008 trybot thinks STACK_SIZE_PARAM_IS_A_RESERVATION isn't defined, but I suppose I can define it if it's not defined without getting into trouble.

                          Windows does not come with C compiler or build tools. So whatever Brad installed on that builder is what we get. But I agree looks strange that STACK_SIZE_PARAM_IS_A_RESERVATION is not found. Perhaps it is "new" flag. I can see you just defined it, and it seems to work.

                          Sorry for pushing you around, but we have better tests now out of my whinging. Hopefully new tests are not flaky or take too much resources.

                          Thank you.

                          Alex

                          Patch set 5:Code-Review +2

                          View Change

                          2 comments:

                            • Interesting. But the documentation on dwStackSize says "If this parameter is zero, the new thread uses the default size for the executable" which is what I want. If I pass both 0 and STACK_SIZE_PARAM_IS_A_RESERVATION it seems like it would either 1) ignore the flag because it's using the defaults from the executable anyway (presumably for both the reserve and commit sizes), or 2) reserve 0 bytes for the stack, which would definitely be bad :)

                              Sorry I confused you. Your code does look right.

                              Old code reserved 0x200000 bytes for amd64 by explicitly providing 0x200000 with STACK_SIZE_PARAM_IS_A_RESERVATION, and committed 0x1000 bytes (by virtue of using what SizeOfStackCommit says in PE file header).

                              And your new code just asks for values as per what is in PE file header: reserved = 0x200000 and committed 0x1000.

                              From https://docs.microsoft.com/en-us/windows/desktop/ProcThread/thread-stack-size

                              The default size for the reserved and initially committed stack memory is specified in the executable file header.
                              ...
                              To change the initially committed stack space, use the dwStackSize parameter of the CreateThread
                              ...
                              To change the reserved stack size, set the dwCreationFlags parameter of CreateThread or CreateRemoteThread to STACK_SIZE_PARAM_IS_A_RESERVATION and use the dwStackSize parameter.

                            • Forgot to add: if I understand what you're saying, we do have tests for it: TestWindowsStackMemory and TestWindowsStackMemoryCgo. Each forces Go to create 100 threads and checks that the committed memory is small. Though TestWindowsStackMemoryCgo is marked as flaky (issue #22575, filed by you, actually :)

                            • Yes, I was remembering we, probably, had a test like that. I worry too much (and it was Friday evening when I reviewed your code last).

                          To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: go
                          Gerrit-Branch: master
                          Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                          Gerrit-Change-Number: 120336
                          Gerrit-PatchSet: 5
                          Gerrit-Owner: Austin Clements <aus...@google.com>
                          Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                          Gerrit-Reviewer: Austin Clements <aus...@google.com>
                          Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                          Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                          Gerrit-Comment-Date: Sat, 30 Jun 2018 07:20:58 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: Yes

                          Austin Clements (Gerrit)

                          unread,
                          Jul 2, 2018, 10:52:21 AM7/2/18
                          to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Gobot Gobot, Ian Lance Taylor, golang-co...@googlegroups.com

                          Thanks!

                          View Change

                            To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                            Gerrit-Project: go
                            Gerrit-Branch: master
                            Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                            Gerrit-Change-Number: 120336
                            Gerrit-PatchSet: 5
                            Gerrit-Owner: Austin Clements <aus...@google.com>
                            Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                            Gerrit-Reviewer: Austin Clements <aus...@google.com>
                            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                            Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                            Gerrit-Comment-Date: Mon, 02 Jul 2018 14:52:17 +0000

                            Gobot Gobot (Gerrit)

                            unread,
                            Jul 2, 2018, 10:57:49 AM7/2/18
                            to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                            TryBots beginning. Status page: https://farmer.golang.org/try?commit=f38a595a

                            View Change

                              To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                              Gerrit-Project: go
                              Gerrit-Branch: master
                              Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                              Gerrit-Change-Number: 120336
                              Gerrit-PatchSet: 6
                              Gerrit-Owner: Austin Clements <aus...@google.com>
                              Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                              Gerrit-Reviewer: Austin Clements <aus...@google.com>
                              Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                              Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                              Gerrit-Comment-Date: Mon, 02 Jul 2018 14:57:46 +0000

                              Gobot Gobot (Gerrit)

                              unread,
                              Jul 2, 2018, 11:08:28 AM7/2/18
                              to Austin Clements, goph...@pubsubhelper.golang.org, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                              TryBots are happy.

                              Patch set 6:TryBot-Result +1

                              View Change

                                To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                                Gerrit-Project: go
                                Gerrit-Branch: master
                                Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                                Gerrit-Change-Number: 120336
                                Gerrit-PatchSet: 6
                                Gerrit-Owner: Austin Clements <aus...@google.com>
                                Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                                Gerrit-Reviewer: Austin Clements <aus...@google.com>
                                Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                                Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                                Gerrit-Comment-Date: Mon, 02 Jul 2018 15:08:25 +0000

                                Austin Clements (Gerrit)

                                unread,
                                Jul 2, 2018, 11:18:29 AM7/2/18
                                to Austin Clements, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Gobot Gobot, Alex Brainman, Ian Lance Taylor, golang-co...@googlegroups.com

                                Austin Clements merged this change.

                                View Change

                                Approvals: Alex Brainman: Looks good to me, approved Ian Lance Taylor: Looks good to me, approved Austin Clements: Run TryBots Gobot Gobot: TryBots succeeded
                                runtime: query thread stack size from OS on Windows

                                Currently, on Windows, the thread stack size is set or assumed in many
                                different places. In non-cgo binaries, both the Go linker and the
                                runtime have a copy of the stack size, the Go linker sets the size of
                                the main thread stack, and the runtime sets the size of other thread
                                stacks. In cgo binaries, the external linker sets the main thread
                                stack size, the runtime assumes the size of the main thread stack will
                                be the same as used by the Go linker, and the cgo entry code assumes
                                the same.

                                Furthermore, users can change the main thread stack size using
                                editbin, so the runtime doesn't even really know what size it is, and
                                user C code can create threads with unknown thread stack sizes, which
                                we also assume have the same default stack size.

                                This is all a mess.

                                Fix the corner cases of this and the duplication of knowledge between
                                the linker and the runtime by querying the OS for the stack bounds
                                during thread setup. Furthermore, we unify all of this into just
                                runtime.minit for both cgo and non-cgo binaries and for the main
                                thread, other runtime-created threads, and C-created threads.

                                Updates #20975.

                                Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                                Reviewed-on: https://go-review.googlesource.com/120336
                                Run-TryBot: Austin Clements <aus...@google.com>
                                TryBot-Result: Gobot Gobot <go...@golang.org>
                                Reviewed-by: Alex Brainman <alex.b...@gmail.com>
                                Reviewed-by: Ian Lance Taylor <ia...@golang.org>

                                ---
                                M src/cmd/link/internal/ld/pe.go
                                M src/cmd/vet/all/whitelist/386.txt
                                M src/cmd/vet/all/whitelist/amd64.txt
                                M src/cmd/vet/all/whitelist/nacl_amd64p32.txt
                                M src/runtime/cgo/gcc_windows_386.c
                                M src/runtime/cgo/gcc_windows_amd64.c
                                M src/runtime/crash_cgo_test.go
                                M src/runtime/defs_windows.go
                                M src/runtime/defs_windows_386.go
                                M src/runtime/defs_windows_amd64.go
                                M src/runtime/os_windows.go
                                M src/runtime/proc.go
                                A src/runtime/stubs_x86.go
                                M src/runtime/sys_windows_386.s
                                M src/runtime/sys_windows_amd64.s
                                M src/runtime/syscall_windows_test.go
                                A src/runtime/testdata/testprogcgo/bigstack_windows.c
                                A src/runtime/testdata/testprogcgo/bigstack_windows.go
                                18 files changed, 208 insertions(+), 50 deletions(-)

                                diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
                                index 3b7df9a..efd971c 100644
                                --- a/src/cmd/link/internal/ld/pe.go
                                +++ b/src/cmd/link/internal/ld/pe.go
                                @@ -845,15 +845,18 @@
                                // 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
                                + // The default stack reserve size directly 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.
                                - // For these, the reserve must match STACKSIZE in
                                - // runtime/cgo/gcc_windows_{386,amd64}.c and osStackSize in
                                - // runtime/os_windows.go.
                                + // For other threads, the runtime explicitly asks the kernel
                                + // to use the default stack size so that all stacks are
                                + // consistent.
                                + //
                                + // At thread start, in minit, the runtime queries the OS for
                                + // the actual stack bounds so that the stack size doesn't need
                                + // to be hard-coded into the runtime.
                                oh64.SizeOfStackReserve = 0x00200000
                                if !iscgo {
                                oh64.SizeOfStackCommit = 0x00001000
                                diff --git a/src/cmd/vet/all/whitelist/386.txt b/src/cmd/vet/all/whitelist/386.txt
                                index 76e8231..f59094e 100644
                                --- a/src/cmd/vet/all/whitelist/386.txt
                                +++ b/src/cmd/vet/all/whitelist/386.txt
                                @@ -22,5 +22,3 @@

                                runtime/asm_386.s: [386] uint32tofloat64: function uint32tofloat64 missing Go declaration
                                runtime/asm_386.s: [386] float64touint32: function float64touint32 missing Go declaration
                                -
                                -runtime/asm_386.s: [386] stackcheck: function stackcheck missing Go declaration
                                diff --git a/src/cmd/vet/all/whitelist/amd64.txt b/src/cmd/vet/all/whitelist/amd64.txt
                                index 2268b39..20e0d48 100644
                                --- a/src/cmd/vet/all/whitelist/amd64.txt
                                +++ b/src/cmd/vet/all/whitelist/amd64.txt
                                @@ -20,4 +20,3 @@
                                runtime/asm_amd64.s: [amd64] addmoduledata: function addmoduledata missing Go declaration
                                runtime/duff_amd64.s: [amd64] duffzero: function duffzero missing Go declaration
                                runtime/duff_amd64.s: [amd64] duffcopy: function duffcopy missing Go declaration
                                -runtime/asm_amd64.s: [amd64] stackcheck: function stackcheck missing Go declaration
                                diff --git a/src/cmd/vet/all/whitelist/nacl_amd64p32.txt b/src/cmd/vet/all/whitelist/nacl_amd64p32.txt
                                index 9280c68..1ec11f7 100644
                                --- a/src/cmd/vet/all/whitelist/nacl_amd64p32.txt
                                +++ b/src/cmd/vet/all/whitelist/nacl_amd64p32.txt
                                @@ -24,5 +24,3 @@
                                runtime/asm_amd64p32.s: [amd64p32] rt0_go: unknown variable argv

                                runtime/asm_amd64p32.s: [amd64p32] asmcgocall: RET without writing to 4-byte ret+8(FP)
                                -
                                -runtime/asm_amd64p32.s: [amd64p32] stackcheck: function stackcheck missing Go declaration
                                diff --git a/src/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c
                                index e80a564..f2ff710 100644
                                --- a/src/runtime/cgo/gcc_windows_386.c
                                +++ b/src/runtime/cgo/gcc_windows_386.c
                                @@ -11,16 +11,9 @@

                                static void threadentry(void*);

                                -/* 1MB is default stack size for 32-bit Windows.
                                - Allocation granularity on Windows is typically 64 KB.
                                - This constant must match SizeOfStackReserve in ../cmd/link/internal/ld/pe.go. */
                                -#define STACKSIZE (1*1024*1024)
                                -
                                void
                                x_cgo_init(G *g)
                                {
                                - int tmp;
                                - g->stacklo = (uintptr)&tmp - STACKSIZE + 8*1024;
                                }


                                @@ -44,8 +37,7 @@
                                ts = *(ThreadStart*)v;
                                free(v);

                                - ts.g->stackhi = (uintptr)&ts;
                                - ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;
                                + // minit queries stack bounds from the OS.

                                /*
                                * Set specific keys in thread local storage.
                                diff --git a/src/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c
                                index 75a7dc8..511ab44 100644
                                --- a/src/runtime/cgo/gcc_windows_amd64.c
                                +++ b/src/runtime/cgo/gcc_windows_amd64.c
                                @@ -11,16 +11,9 @@

                                static void threadentry(void*);

                                -/* 2MB is default stack size for 64-bit Windows.
                                - Allocation granularity on Windows is typically 64 KB.
                                - This constant must match SizeOfStackReserve in ../cmd/link/internal/ld/pe.go. */
                                -#define STACKSIZE (2*1024*1024)
                                -
                                void
                                x_cgo_init(G *g)
                                {
                                - int tmp;
                                - g->stacklo = (uintptr)&tmp - STACKSIZE + 8*1024;
                                }


                                @@ -44,8 +37,7 @@
                                ts = *(ThreadStart*)v;
                                free(v);

                                - ts.g->stackhi = (uintptr)&ts;
                                - ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;
                                + // minit queries stack bounds from the OS.

                                /*
                                * Set specific keys in thread local storage.
                                diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
                                index d8f75a4..b2ee8df 100644
                                --- a/src/runtime/crash_cgo_test.go
                                +++ b/src/runtime/crash_cgo_test.go
                                @@ -489,3 +489,19 @@
                                t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
                                }
                                }
                                +
                                +// Test that C code called via cgo can use large Windows thread stacks
                                +// and call back in to Go without crashing. See issue #20975.
                                +//
                                +// See also TestBigStackCallbackSyscall.
                                +func TestBigStackCallbackCgo(t *testing.T) {
                                + if runtime.GOOS != "windows" {
                                + t.Skip("skipping windows specific test")
                                + }
                                + t.Parallel()
                                + got := runTestProg(t, "testprogcgo", "BigStack")
                                + want := "OK\n"
                                + if got != want {
                                + t.Errorf("expected %q got %v", want, got)
                                + }
                                +}
                                diff --git a/src/runtime/defs_windows.go b/src/runtime/defs_windows.go
                                index 7ce6797..9bd9107 100644
                                --- a/src/runtime/defs_windows.go
                                +++ b/src/runtime/defs_windows.go
                                @@ -71,3 +71,4 @@
                                type M128a C.M128A
                                type Context C.CONTEXT
                                type Overlapped C.OVERLAPPED
                                +type MemoryBasicInformation C.MEMORY_BASIC_INFORMATION
                                diff --git a/src/runtime/defs_windows_386.go b/src/runtime/defs_windows_386.go
                                index bac6ce7..589a788 100644
                                --- a/src/runtime/defs_windows_386.go
                                +++ b/src/runtime/defs_windows_386.go
                                @@ -129,3 +129,13 @@
                                anon0 [8]byte
                                hevent *byte
                                }
                                +
                                +type memoryBasicInformation struct {
                                + baseAddress uintptr
                                + allocationBase uintptr
                                + allocationProtect uint32
                                + regionSize uintptr
                                + state uint32
                                + protect uint32
                                + type_ uint32
                                +}
                                diff --git a/src/runtime/defs_windows_amd64.go b/src/runtime/defs_windows_amd64.go
                                index 6e04568..1e173e9 100644
                                --- a/src/runtime/defs_windows_amd64.go
                                +++ b/src/runtime/defs_windows_amd64.go
                                @@ -151,3 +151,13 @@
                                anon0 [8]byte
                                hevent *byte
                                }
                                +
                                +type memoryBasicInformation struct {
                                + baseAddress uintptr
                                + allocationBase uintptr
                                + allocationProtect uint32
                                + regionSize uintptr
                                + state uint32
                                + protect uint32
                                + type_ uint32
                                +}
                                diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
                                index 1f3ebf6..bf5baea 100644
                                --- a/src/runtime/os_windows.go
                                +++ b/src/runtime/os_windows.go
                                @@ -45,6 +45,7 @@
                                //go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
                                //go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
                                //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
                                +//go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
                                //go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll"
                                //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
                                //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
                                @@ -92,6 +93,7 @@
                                _SwitchToThread,
                                _VirtualAlloc,
                                _VirtualFree,
                                + _VirtualQuery,
                                _WSAGetOverlappedResult,
                                _WaitForSingleObject,
                                _WriteConsoleW,
                                @@ -291,9 +293,6 @@
                                }
                                }

                                -// osStackSize must match SizeOfStackReserve in ../cmd/link/internal/ld/pe.go.
                                -var osStackSize uintptr = 0x00200000*_64bit + 0x00100000*(1-_64bit)
                                -
                                func osinit() {
                                asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
                                usleep2Addr = unsafe.Pointer(funcPC(usleep2))
                                @@ -322,18 +321,6 @@
                                // equivalent threads that all do a mix of GUI, IO, computations, etc.
                                // In such context dynamic priority boosting does nothing but harm, so we turn it off.
                                stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
                                -
                                - // Fix the entry thread's stack bounds, since runtime entry
                                - // assumed we were on a tiny stack. If this is a cgo binary,
                                - // x_cgo_init already fixed these.
                                - if !iscgo {
                                - // Leave 8K of slop for calling C functions that don't
                                - // have stack checks. We shouldn't be anywhere near
                                - // this bound anyway.
                                - g0.stack.lo = g0.stack.hi - osStackSize + 8*1024
                                - g0.stackguard0 = g0.stack.lo + _StackGuard
                                - g0.stackguard1 = g0.stackguard0
                                - }
                                }

                                func nanotime() int64
                                @@ -634,10 +621,10 @@
                                //go:nowritebarrierrec
                                //go:nosplit
                                func newosproc(mp *m) {
                                - const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
                                - thandle := stdcall6(_CreateThread, 0, osStackSize,
                                + // We pass 0 for the stack size to use the default for this binary.
                                + thandle := stdcall6(_CreateThread, 0, 0,
                                funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
                                - _STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
                                + 0, 0)

                                if thandle == 0 {
                                if atomic.Load(&exiting) != 0 {
                                @@ -702,6 +689,30 @@
                                var thandle uintptr
                                stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
                                atomic.Storeuintptr(&getg().m.thread, thandle)
                                +
                                + // Query the true stack base from the OS. Currently we're
                                + // running on a small assumed stack.
                                + var mbi memoryBasicInformation
                                + res := stdcall3(_VirtualQuery, uintptr(unsafe.Pointer(&mbi)), uintptr(unsafe.Pointer(&mbi)), unsafe.Sizeof(mbi))
                                + if res == 0 {
                                + print("runtime: VirtualQuery failed; errno=", getlasterror(), "\n")
                                + throw("VirtualQuery for stack base failed")
                                + }
                                + // Add 8K of slop for calling C functions that don't have
                                + // stack checks. We shouldn't be anywhere near this bound
                                + // anyway.
                                + base := mbi.allocationBase + 8*1024
                                + // Sanity check the stack bounds.
                                + g0 := getg()
                                + if base > g0.stack.hi || g0.stack.hi-base > 64<<20 {
                                + print("runtime: g0 stack [", hex(base), ",", hex(g0.stack.hi), ")\n")
                                + throw("bad g0 stack")
                                + }
                                + g0.stack.lo = base
                                + g0.stackguard0 = g0.stack.lo + _StackGuard
                                + g0.stackguard1 = g0.stackguard0
                                + // Sanity check the SP.
                                + stackcheck()
                                }

                                // Called from dropm to undo the effect of an minit.
                                diff --git a/src/runtime/proc.go b/src/runtime/proc.go
                                index b548632..f82014e 100644
                                --- a/src/runtime/proc.go
                                +++ b/src/runtime/proc.go
                                @@ -1233,6 +1233,7 @@
                                if osStack {
                                // Initialize stack bounds from system stack.
                                // Cgo may have left stack size in stack.hi.
                                + // minit may update the stack bounds.
                                size := _g_.stack.hi
                                if size == 0 {
                                size = 8192 * sys.StackGuardMultiplier
                                diff --git a/src/runtime/stubs_x86.go b/src/runtime/stubs_x86.go
                                new file mode 100644
                                index 0000000..830c48b
                                --- /dev/null
                                +++ b/src/runtime/stubs_x86.go
                                @@ -0,0 +1,10 @@
                                +// Copyright 2018 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.
                                +
                                +// +build amd64 amd64p32 386
                                +
                                +package runtime
                                +
                                +// stackcheck checks that SP is in range [g->stack.lo, g->stack.hi).
                                +func stackcheck()
                                diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
                                index 56d5cfa..3c091ad 100644
                                --- a/src/runtime/sys_windows_386.s
                                +++ b/src/runtime/sys_windows_386.s
                                @@ -315,8 +315,7 @@
                                // Layout new m scheduler stack on os stack.
                                MOVL SP, AX
                                MOVL AX, (g_stack+stack_hi)(DX)
                                - SUBL runtimeĀ·osStackSize(SB), AX // stack size
                                - ADDL $(8*1024), AX // slop for calling C
                                + SUBL $(64*1024), AX // initial stack size (adjusted later)
                                MOVL AX, (g_stack+stack_lo)(DX)
                                ADDL $const__StackGuard, AX
                                MOVL AX, g_stackguard0(DX)
                                diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
                                index 119e04c..c1449db 100644
                                --- a/src/runtime/sys_windows_amd64.s
                                +++ b/src/runtime/sys_windows_amd64.s
                                @@ -363,8 +363,7 @@
                                // Layout new m scheduler stack on os stack.
                                MOVQ SP, AX
                                MOVQ AX, (g_stack+stack_hi)(DX)
                                - SUBQ runtimeĀ·osStackSize(SB), AX // stack size
                                - ADDQ $(8*1024), AX // slop for calling C
                                + SUBQ $(64*1024), AX // inital stack size (adjusted later)
                                MOVQ AX, (g_stack+stack_lo)(DX)
                                ADDQ $const__StackGuard, AX
                                MOVQ AX, g_stackguard0(DX)
                                diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
                                index 0f5e13f..0882e9c 100644
                                --- a/src/runtime/syscall_windows_test.go
                                +++ b/src/runtime/syscall_windows_test.go
                                @@ -957,6 +957,52 @@
                                }
                                }

                                +// Test that C code called via a DLL can use large Windows thread
                                +// stacks and call back in to Go without crashing. See issue #20975.
                                +//
                                +// See also TestBigStackCallbackCgo.
                                +func TestBigStackCallbackSyscall(t *testing.T) {
                                + if _, err := exec.LookPath("gcc"); err != nil {
                                + t.Skip("skipping test: gcc is missing")
                                + }
                                +
                                + srcname, err := filepath.Abs("testdata/testprogcgo/bigstack_windows.c")
                                + if err != nil {
                                + t.Fatal("Abs failed: ", err)
                                + }
                                +
                                + tmpdir, err := ioutil.TempDir("", "TestBigStackCallback")
                                + if err != nil {
                                + t.Fatal("TempDir failed: ", err)
                                + }
                                + defer os.RemoveAll(tmpdir)
                                +
                                + outname := "mydll.dll"
                                + cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
                                + cmd.Dir = tmpdir
                                + out, err := cmd.CombinedOutput()
                                + if err != nil {
                                + t.Fatalf("failed to build dll: %v - %v", err, string(out))
                                + }
                                + dllpath := filepath.Join(tmpdir, outname)
                                +
                                + dll := syscall.MustLoadDLL(dllpath)
                                + defer dll.Release()
                                +
                                + var ok bool
                                + proc := dll.MustFindProc("bigStack")
                                + cb := syscall.NewCallback(func() uintptr {
                                + // Do something interesting to force stack checks.
                                + forceStackCopy()
                                + ok = true
                                + return 0
                                + })
                                + proc.Call(cb)
                                + if !ok {
                                + t.Fatalf("callback not called")
                                + }
                                +}
                                +
                                // wantLoadLibraryEx reports whether we expect LoadLibraryEx to work for tests.
                                func wantLoadLibraryEx() bool {
                                return testenv.Builder() == "windows-amd64-gce" || testenv.Builder() == "windows-386-gce"
                                diff --git a/src/runtime/testdata/testprogcgo/bigstack_windows.c b/src/runtime/testdata/testprogcgo/bigstack_windows.c
                                new file mode 100644
                                index 0000000..cd85ac8
                                --- /dev/null
                                +++ b/src/runtime/testdata/testprogcgo/bigstack_windows.c
                                @@ -0,0 +1,46 @@
                                +// Copyright 2018 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.
                                +
                                +// This test source is used by both TestBigStackCallbackCgo (linked
                                +// directly into the Go binary) and TestBigStackCallbackSyscall
                                +// (compiled into a DLL).
                                +
                                +#include <windows.h>
                                +#include <stdio.h>
                                +
                                +#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
                                +#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
                                +#endif
                                +
                                +typedef void callback(char*);
                                +
                                +// Allocate a stack that's much larger than the default.
                                +static const int STACK_SIZE = 16<<20;
                                +
                                +static callback *bigStackCallback;
                                +
                                +static void useStack(int bytes) {
                                + // Windows doesn't like huge frames, so we grow the stack 64k at a time.
                                + char x[64<<10];
                                + if (bytes < sizeof x) {
                                + bigStackCallback(x);
                                + } else {
                                + useStack(bytes - sizeof x);
                                + }
                                +}
                                +
                                +static DWORD WINAPI threadEntry(LPVOID lpParam) {
                                + useStack(STACK_SIZE - (128<<10));
                                + return 0;
                                +}
                                +
                                +void bigStack(callback *cb) {
                                + bigStackCallback = cb;
                                + HANDLE hThread = CreateThread(NULL, STACK_SIZE, threadEntry, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
                                + if (hThread == NULL) {
                                + fprintf(stderr, "CreateThread failed\n");
                                + exit(1);
                                + }
                                + WaitForSingleObject(hThread, INFINITE);
                                +}
                                diff --git a/src/runtime/testdata/testprogcgo/bigstack_windows.go b/src/runtime/testdata/testprogcgo/bigstack_windows.go
                                new file mode 100644
                                index 0000000..f58fcf9
                                --- /dev/null
                                +++ b/src/runtime/testdata/testprogcgo/bigstack_windows.go
                                @@ -0,0 +1,27 @@
                                +// Copyright 2018 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 main
                                +
                                +/*
                                +typedef void callback(char*);
                                +extern void goBigStack1(char*);
                                +extern void bigStack(callback*);
                                +*/
                                +import "C"
                                +
                                +func init() {
                                + register("BigStack", BigStack)
                                +}
                                +
                                +func BigStack() {
                                + // Create a large thread stack and call back into Go to test
                                + // if Go correctly determines the stack bounds.
                                + C.bigStack((*C.callback)(C.goBigStack1))
                                +}
                                +
                                +//export goBigStack1
                                +func goBigStack1(x *C.char) {
                                + println("OK")
                                +}

                                To view, visit change 120336. To unsubscribe, or for help writing mail filters, visit settings.

                                Gerrit-Project: go
                                Gerrit-Branch: master
                                Gerrit-Change-Id: I45dbee2b5ea2ae721a85a27680737ff046f9d464
                                Gerrit-Change-Number: 120336
                                Gerrit-PatchSet: 7
                                Gerrit-Owner: Austin Clements <aus...@google.com>
                                Gerrit-Reviewer: Alex Brainman <alex.b...@gmail.com>
                                Gerrit-Reviewer: Austin Clements <aus...@google.com>
                                Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
                                Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
                                Gerrit-MessageType: merged
                                Reply all
                                Reply to author
                                Forward
                                0 new messages