1
0
mirror of https://github.com/golang/go synced 2024-11-19 15:14:45 -07:00

cmd/link: restore windows stack commit size back to 4KB

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 <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
Alex Brainman 2017-10-30 20:00:54 +11:00
parent 25159d3af9
commit 923299a6b8
8 changed files with 164 additions and 4 deletions

View File

@ -848,7 +848,14 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
// runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent // runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent
// CreateThread parameter in runtime.newosproc. // CreateThread parameter in runtime.newosproc.
oh64.SizeOfStackReserve = 0x00200000 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 // 32-bit is trickier since there much less address space to
// work with. Here we use large stacks only in cgo binaries as // work with. Here we use large stacks only in cgo binaries as
@ -858,7 +865,7 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
oh.SizeOfStackCommit = 0x00001000 oh.SizeOfStackCommit = 0x00001000
} else { } else {
oh.SizeOfStackReserve = 0x00100000 oh.SizeOfStackReserve = 0x00100000
oh.SizeOfStackCommit = 0x00100000 - 0x2000 oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages
} }
oh64.SizeOfHeapReserve = 0x00100000 oh64.SizeOfHeapReserve = 0x00100000

View File

@ -4,4 +4,4 @@
package windows 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

View File

@ -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

View File

@ -40,6 +40,7 @@ var (
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
@ -57,6 +58,7 @@ var (
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
) )
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
@ -243,3 +245,15 @@ func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newst
} }
return 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
}

View File

@ -13,6 +13,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"runtime" "runtime"
"strconv"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -452,3 +453,20 @@ func TestCgoLockOSThreadExit(t *testing.T) {
t.Parallel() t.Parallel()
testLockOSThreadExit(t, "testprogcgo") 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"))
}

View File

@ -537,6 +537,10 @@ func TestWERDialogue(t *testing.T) {
cmd.CombinedOutput() cmd.CombinedOutput()
} }
func TestWindowsStackMemory(t *testing.T) {
testWindowsStackMemory(t, runTestProg(t, "testprog", "StackMemory"))
}
var used byte var used byte
func use(buf []byte) { func use(buf []byte) {

View File

@ -4,11 +4,18 @@
package main package main
import "syscall" import (
"internal/syscall/windows"
"runtime"
"sync"
"syscall"
"unsafe"
)
func init() { func init() {
register("RaiseException", RaiseException) register("RaiseException", RaiseException)
register("ZeroDivisionException", ZeroDivisionException) register("ZeroDivisionException", ZeroDivisionException)
register("StackMemory", StackMemory)
} }
func RaiseException() { func RaiseException() {
@ -25,3 +32,39 @@ func ZeroDivisionException() {
z := x / y z := x / y
println(z) 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)
}

View File

@ -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)
}