mirror of
https://github.com/golang/go
synced 2024-11-11 22:50:22 -07:00
runtime: increase stack split limit again
Increase NOSPLIT reservation from 192 to 384 bytes. The problem is that the non-Unix systems (Solaris and Windows) just can't make system calls in a small amount of space, and then worse they do things that are complex enough to warrant calling runtime.throw on failure. We don't have time to rewrite the code to use less stack. I'm not happy about this, but it's still a small amount. The good news is that we're doing this to get to only using copying stacks for stack growth. Once that is true, we can drop the default stack size from 8k to 4k, which should more than make up for the bytes we're losing here. LGTM=r R=iant, r, bradfitz, aram.h CC=golang-codereviews https://golang.org/cl/140350043
This commit is contained in:
parent
7230db9ef8
commit
b6951bcc0b
@ -4,99 +4,7 @@
|
||||
|
||||
package runtime
|
||||
|
||||
/*
|
||||
Stack layout parameters.
|
||||
Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
|
||||
|
||||
The per-goroutine g->stackguard is set to point stackGuard bytes
|
||||
above the bottom of the stack. Each function compares its stack
|
||||
pointer against g->stackguard to check for overflow. To cut one
|
||||
instruction from the check sequence for functions with tiny frames,
|
||||
the stack is allowed to protrude stackSmall bytes below the stack
|
||||
guard. Functions with large frames don't bother with the check and
|
||||
always call morestack. The sequences are (for amd64, others are
|
||||
similar):
|
||||
|
||||
guard = g->stackguard
|
||||
frame = function's stack frame size
|
||||
argsize = size of function arguments (call + return)
|
||||
|
||||
stack frame size <= stackSmall:
|
||||
CMPQ guard, SP
|
||||
JHI 3(PC)
|
||||
MOVQ m->morearg, $(argsize << 32)
|
||||
CALL morestack(SB)
|
||||
|
||||
stack frame size > stackSmall but < stackBig
|
||||
LEAQ (frame-stackSmall)(SP), R0
|
||||
CMPQ guard, R0
|
||||
JHI 3(PC)
|
||||
MOVQ m->morearg, $(argsize << 32)
|
||||
CALL morestack(SB)
|
||||
|
||||
stack frame size >= stackBig:
|
||||
MOVQ m->morearg, $((argsize << 32) | frame)
|
||||
CALL morestack(SB)
|
||||
|
||||
The bottom stackGuard - stackSmall bytes are important: there has
|
||||
to be enough room to execute functions that refuse to check for
|
||||
stack overflow, either because they need to be adjacent to the
|
||||
actual caller's frame (deferproc) or because they handle the imminent
|
||||
stack overflow (morestack).
|
||||
|
||||
For example, deferproc might call malloc, which does one of the
|
||||
above checks (without allocating a full frame), which might trigger
|
||||
a call to morestack. This sequence needs to fit in the bottom
|
||||
section of the stack. On amd64, morestack's frame is 40 bytes, and
|
||||
deferproc's frame is 56 bytes. That fits well within the
|
||||
stackGuard - stackSmall = 128 bytes at the bottom.
|
||||
The linkers explore all possible call traces involving non-splitting
|
||||
functions to make sure that this limit cannot be violated.
|
||||
*/
|
||||
|
||||
const (
|
||||
// stackSystem is a number of additional bytes to add
|
||||
// to each stack below the usual guard area for OS-specific
|
||||
// purposes like signal handling. Used on Windows and on
|
||||
// Plan 9 because they do not use a separate stack.
|
||||
// Defined in os_*.go.
|
||||
|
||||
// The amount of extra stack to allocate beyond the size
|
||||
// needed for the single frame that triggered the split.
|
||||
stackExtra = 2048
|
||||
|
||||
// The minimum stack segment size to allocate.
|
||||
// If the amount needed for the splitting frame + stackExtra
|
||||
// is less than this number, the stack will have this size instead.
|
||||
stackMin = 8192
|
||||
stackSystemRounded = stackSystem + (-stackSystem & (stackMin - 1))
|
||||
Fixedstack = stackMin + stackSystemRounded
|
||||
|
||||
// Functions that need frames bigger than this use an extra
|
||||
// instruction to do the stack split check, to avoid overflow
|
||||
// in case SP - framesize wraps below zero.
|
||||
// This value can be no bigger than the size of the unmapped
|
||||
// space at zero.
|
||||
stackBig = 4096
|
||||
|
||||
// The stack guard is a pointer this many bytes above the
|
||||
// bottom of the stack.
|
||||
stackGuard = 256 + stackSystem
|
||||
|
||||
// After a stack split check the SP is allowed to be this
|
||||
// many bytes below the stack guard. This saves an instruction
|
||||
// in the checking sequence for tiny frames.
|
||||
stackSmall = 64
|
||||
|
||||
// The maximum number of bytes that a chain of NOSPLIT
|
||||
// functions can use.
|
||||
stackLimit = stackGuard - stackSystem - stackSmall
|
||||
|
||||
// The assumed size of the top-of-stack data block.
|
||||
// The actual size can be smaller than this but cannot be larger.
|
||||
// Checked in proc.c's runtime.malg.
|
||||
stackTop = 88
|
||||
|
||||
// Goroutine preemption request.
|
||||
// Stored into g->stackguard0 to cause split stack check failure.
|
||||
// Must be greater than any real sp.
|
||||
|
@ -89,12 +89,12 @@ enum {
|
||||
|
||||
// The stack guard is a pointer this many bytes above the
|
||||
// bottom of the stack.
|
||||
StackGuard = 256 + StackSystem,
|
||||
StackGuard = 512 + StackSystem,
|
||||
|
||||
// After a stack split check the SP is allowed to be this
|
||||
// many bytes below the stack guard. This saves an instruction
|
||||
// in the checking sequence for tiny frames.
|
||||
StackSmall = 64,
|
||||
StackSmall = 128,
|
||||
|
||||
// The maximum number of bytes that a chain of NOSPLIT
|
||||
// functions can use.
|
||||
|
@ -256,11 +256,11 @@ TestCases:
|
||||
name := m[1]
|
||||
size, _ := strconv.Atoi(m[2])
|
||||
|
||||
// The limit was originally 128 but is now 192.
|
||||
// The limit was originally 128 but is now 384.
|
||||
// Instead of rewriting the test cases above, adjust
|
||||
// the first stack frame to use up the extra 32 bytes.
|
||||
if i == 0 {
|
||||
size += 192 - 128
|
||||
size += 384 - 128
|
||||
}
|
||||
|
||||
if goarch == "amd64" && size%8 == 4 {
|
||||
|
Loading…
Reference in New Issue
Block a user