Skip to content

Commit

Permalink
cmd/link: restore windows stack commit size back to 4KB
Browse files Browse the repository at this point in the history
CL 49331 increased windows stack commit size to 2MB by mistake.
Revert that change.

Fixes #22439

Change-Id: I919e549e87da326f4ba45890b4d32f6d7046186f
Reviewed-on: https://go-review.googlesource.com/74490
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Austin Clements <[email protected]>
  • Loading branch information
alexbrainman committed Nov 3, 2017
1 parent 25159d3 commit 923299a
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 4 deletions.
11 changes: 9 additions & 2 deletions src/cmd/link/internal/ld/pe.go
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,14 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
// runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent
// CreateThread parameter in runtime.newosproc.
oh64.SizeOfStackReserve = 0x00200000
oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
if !iscgo {
oh64.SizeOfStackCommit = 0x00001000
} else {
// TODO(brainman): Maybe remove optional header writing altogether for cgo.
// For cgo it is the external linker that is building final executable.
// And it probably does not use any information stored in optional header.
oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
}

// 32-bit is trickier since there much less address space to
// work with. Here we use large stacks only in cgo binaries as
Expand All @@ -858,7 +865,7 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
oh.SizeOfStackCommit = 0x00001000
} else {
oh.SizeOfStackReserve = 0x00100000
oh.SizeOfStackCommit = 0x00100000 - 0x2000
oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages
}

oh64.SizeOfHeapReserve = 0x00100000
Expand Down
2 changes: 1 addition & 1 deletion src/internal/syscall/windows/mksyscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

package windows

//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go
20 changes: 20 additions & 0 deletions src/internal/syscall/windows/psapi_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2017 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 windows

type PROCESS_MEMORY_COUNTERS struct {
CB uint32
PageFaultCount uint32
PeakWorkingSetSize uintptr
WorkingSetSize uintptr
QuotaPeakPagedPoolUsage uintptr
QuotaPagedPoolUsage uintptr
QuotaPeakNonPagedPoolUsage uintptr
QuotaNonPagedPoolUsage uintptr
PagefileUsage uintptr
PeakPagefileUsage uintptr
}

//sys GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) = psapi.GetProcessMemoryInfo
14 changes: 14 additions & 0 deletions src/internal/syscall/windows/zsyscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var (
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))

procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
Expand All @@ -57,6 +58,7 @@ var (
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
)

func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
Expand Down Expand Up @@ -243,3 +245,15 @@ func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newst
}
return
}

func GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) {
r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(memCounters)), uintptr(cb))
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
18 changes: 18 additions & 0 deletions src/runtime/crash_cgo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -452,3 +453,20 @@ func TestCgoLockOSThreadExit(t *testing.T) {
t.Parallel()
testLockOSThreadExit(t, "testprogcgo")
}

func testWindowsStackMemory(t *testing.T, o string) {
stackUsage, err := strconv.Atoi(o)
if err != nil {
t.Fatalf("Failed to read stack usage: %v", err)
}
if expected, got := 100<<10, stackUsage; got > expected {
t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
}
}

func TestWindowsStackMemoryCgo(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("skipping windows specific test")
}
testWindowsStackMemory(t, runTestProg(t, "testprogcgo", "StackMemory"))
}
4 changes: 4 additions & 0 deletions src/runtime/syscall_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,10 @@ func TestWERDialogue(t *testing.T) {
cmd.CombinedOutput()
}

func TestWindowsStackMemory(t *testing.T) {
testWindowsStackMemory(t, runTestProg(t, "testprog", "StackMemory"))
}

var used byte

func use(buf []byte) {
Expand Down
45 changes: 44 additions & 1 deletion src/runtime/testdata/testprog/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@

package main

import "syscall"
import (
"internal/syscall/windows"
"runtime"
"sync"
"syscall"
"unsafe"
)

func init() {
register("RaiseException", RaiseException)
register("ZeroDivisionException", ZeroDivisionException)
register("StackMemory", StackMemory)
}

func RaiseException() {
Expand All @@ -25,3 +32,39 @@ func ZeroDivisionException() {
z := x / y
println(z)
}

func getPagefileUsage() (uintptr, error) {
p, err := syscall.GetCurrentProcess()
if err != nil {
return 0, err
}
var m windows.PROCESS_MEMORY_COUNTERS
err = windows.GetProcessMemoryInfo(p, &m, uint32(unsafe.Sizeof(m)))
if err != nil {
return 0, err
}
return m.PagefileUsage, nil
}

func StackMemory() {
mem1, err := getPagefileUsage()
if err != nil {
panic(err)
}
const threadCount = 100
var wg sync.WaitGroup
for i := 0; i < threadCount; i++ {
wg.Add(1)
go func() {
runtime.LockOSThread()
wg.Done()
select {}
}()
}
wg.Wait()
mem2, err := getPagefileUsage()
if err != nil {
panic(err)
}
print((mem2 - mem1) / threadCount)
}
54 changes: 54 additions & 0 deletions src/runtime/testdata/testprogcgo/stack_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2015 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

import "C"
import (
"internal/syscall/windows"
"runtime"
"sync"
"syscall"
"unsafe"
)

func init() {
register("StackMemory", StackMemory)
}

func getPagefileUsage() (uintptr, error) {
p, err := syscall.GetCurrentProcess()
if err != nil {
return 0, err
}
var m windows.PROCESS_MEMORY_COUNTERS
err = windows.GetProcessMemoryInfo(p, &m, uint32(unsafe.Sizeof(m)))
if err != nil {
return 0, err
}
return m.PagefileUsage, nil
}

func StackMemory() {
mem1, err := getPagefileUsage()
if err != nil {
panic(err)
}
const threadCount = 100
var wg sync.WaitGroup
for i := 0; i < threadCount; i++ {
wg.Add(1)
go func() {
runtime.LockOSThread()
wg.Done()
select {}
}()
}
wg.Wait()
mem2, err := getPagefileUsage()
if err != nil {
panic(err)
}
print((mem2 - mem1) / threadCount)
}

0 comments on commit 923299a

Please sign in to comment.