Skip to content

Commit 0f099a4

Browse files
aclementsgopherbot
authored andcommitted
runtime, cmd: rationalize StackLimit and StackGuard
The current definitions of StackLimit and StackGuard only indirectly specify the NOSPLIT stack limit and duplicate a literal constant (928). Currently, they define the stack guard delta, and from there compute the NOSPLIT limit. Rationalize these by defining a new constant, abi.StackNosplitBase, which consolidates and directly specifies the NOSPLIT stack limit (in the default case). From this we then compute the stack guard delta, inverting the relationship between these two constants. While we're here, we rename StackLimit to StackNosplit to make it clearer what's being limited. This change does not affect the values of these constants in the default configuration. It does slightly change how StackGuardMultiplier values other than 1 affect the constants, but this multiplier is a pretty rough heuristic anyway. before after stackNosplit 800 800 _StackGuard 928 928 stackNosplit -race 1728 1600 _StackGuard -race 1856 1728 For #59670. Change-Id: Ia94094c5e47897e7c088d24b4a5e33f5c2768db5 Reviewed-on: https://go-review.googlesource.com/c/go/+/486976 Auto-Submit: Austin Clements <[email protected]> Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 03ad1f1 commit 0f099a4

File tree

6 files changed

+25
-34
lines changed

6 files changed

+25
-34
lines changed

src/cmd/internal/objabi/stack.go

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,9 @@ import (
99
"internal/buildcfg"
1010
)
1111

12-
// For the linkers. Must match Go definitions.
13-
14-
const (
15-
STACKSYSTEM = 0
16-
StackSystem = STACKSYSTEM
17-
)
18-
19-
func StackLimit(race bool) int {
20-
// This arithmetic must match that in runtime/stack.go:{_StackGuard,_StackLimit}.
21-
stackGuard := 928*stackGuardMultiplier(race) + StackSystem
22-
stackLimit := stackGuard - StackSystem - abi.StackSmall
23-
return stackLimit
12+
func StackNosplit(race bool) int {
13+
// This arithmetic must match that in runtime/stack.go:stackNosplit.
14+
return abi.StackNosplitBase * stackGuardMultiplier(race)
2415
}
2516

2617
// stackGuardMultiplier returns a multiplier to apply to the default

src/cmd/link/internal/ld/stackcheck.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (ctxt *Link) doStackCheck() {
6161
// The call to morestack in every splittable function ensures
6262
// that there are at least StackLimit bytes available below SP
6363
// when morestack returns.
64-
limit := objabi.StackLimit(*flagRace) - sc.callSize
64+
limit := objabi.StackNosplit(*flagRace) - sc.callSize
6565
if buildcfg.GOARCH == "arm64" {
6666
// Need an extra 8 bytes below SP to save FP.
6767
limit -= 8

src/internal/abi/stack.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
package abi
66

77
const (
8+
// StackNosplitBase is the base maximum number of bytes that a chain of
9+
// NOSPLIT functions can use.
10+
//
11+
// This value must be multiplied by the stack guard multiplier, so do not
12+
// use it directly. See runtime/stack.go:stackNosplit and
13+
// cmd/internal/objabi/stack.go:StackNosplit.
14+
StackNosplitBase = 800
15+
816
// We have three different sequences for stack bounds checks, depending on
917
// whether the stack frame of a function is small, big, or huge.
1018

src/runtime/preempt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ func init() {
320320
total += funcMaxSPDelta(f)
321321
// Add some overhead for return PCs, etc.
322322
asyncPreemptStack = uintptr(total) + 8*goarch.PtrSize
323-
if asyncPreemptStack > _StackLimit {
323+
if asyncPreemptStack > stackNosplit {
324324
// We need more than the nosplit limit. This isn't
325325
// unsafe, but it may limit asynchronous preemption.
326326
//

src/runtime/stack.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,18 @@ const (
8585
_FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16)
8686
_FixedStack = _FixedStack6 + 1
8787

88+
// stackNosplit is the maximum number of bytes that a chain of NOSPLIT
89+
// functions can use.
90+
// This arithmetic must match that in cmd/internal/objabi/stack.go:StackNosplit.
91+
stackNosplit = abi.StackNosplitBase * sys.StackGuardMultiplier
92+
8893
// The stack guard is a pointer this many bytes above the
8994
// bottom of the stack.
9095
//
91-
// The guard leaves enough room for one _StackSmall frame plus
92-
// a _StackLimit chain of NOSPLIT calls plus _StackSystem
93-
// bytes for the OS.
94-
// This arithmetic must match that in cmd/internal/objabi/stack.go:StackLimit.
95-
_StackGuard = 928*sys.StackGuardMultiplier + _StackSystem
96-
97-
// The maximum number of bytes that a chain of NOSPLIT
98-
// functions can use.
96+
// The guard leaves enough room for a stackNosplit chain of NOSPLIT calls
97+
// plus one stackSmall frame plus stackSystem bytes for the OS.
9998
// This arithmetic must match that in cmd/internal/objabi/stack.go:StackLimit.
100-
_StackLimit = _StackGuard - _StackSystem - abi.StackSmall
99+
_StackGuard = stackNosplit + _StackSystem + abi.StackSmall
101100
)
102101

103102
const (
@@ -1211,7 +1210,7 @@ func shrinkstack(gp *g) {
12111210
// down to the SP plus the stack guard space that ensures
12121211
// there's room for nosplit functions.
12131212
avail := gp.stack.hi - gp.stack.lo
1214-
if used := gp.stack.hi - gp.sched.sp + _StackLimit; used >= avail/4 {
1213+
if used := gp.stack.hi - gp.sched.sp + stackNosplit; used >= avail/4 {
12151214
return
12161215
}
12171216

test/nosplit.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -342,22 +342,15 @@ TestCases:
342342
nosplit := m[3]
343343
body := m[4]
344344

345-
// The limit was originally 128 but is now 800 (928-128).
345+
// The limit was originally 128 but is now 800.
346346
// Instead of rewriting the test cases above, adjust
347347
// the first nosplit frame to use up the extra bytes.
348348
// This isn't exactly right because we could have
349349
// nosplit -> split -> nosplit, but it's good enough.
350350
if !adjusted && nosplit != "" {
351+
const stackNosplitBase = 800 // internal/abi.StackNosplitBase
351352
adjusted = true
352-
size += (928 - 128) - 128
353-
// Noopt builds have a larger stackguard.
354-
// See ../src/cmd/dist/buildruntime.go:stackGuardMultiplier
355-
// This increase is included in objabi.StackGuard
356-
for _, s := range strings.Split(os.Getenv("GO_GCFLAGS"), " ") {
357-
if s == "-N" {
358-
size += 928
359-
}
360-
}
353+
size += stackNosplitBase - 128
361354
}
362355

363356
if nosplit != "" {

0 commit comments

Comments
 (0)