aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/stack1.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/stack1.go')
-rw-r--r--src/runtime/stack1.go23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go
index e593b8a3a8..f77e87cdf9 100644
--- a/src/runtime/stack1.go
+++ b/src/runtime/stack1.go
@@ -175,7 +175,7 @@ func stackcache_clear(c *mcache) {
unlock(&stackpoolmu)
}
-func stackalloc(n uint32) stack {
+func stackalloc(n uint32) (stack, []stkbar) {
// Stackalloc must be called on scheduler stack, so that we
// never try to grow the stack during the code that stackalloc runs.
// Doing so would cause a deadlock (issue 1547).
@@ -190,12 +190,18 @@ func stackalloc(n uint32) stack {
print("stackalloc ", n, "\n")
}
+ // Compute the size of stack barrier array.
+ maxstkbar := gcMaxStackBarriers(int(n))
+ nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar)
+
if debug.efence != 0 || stackFromSystem != 0 {
v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
if v == nil {
throw("out of memory (stackalloc)")
}
- return stack{uintptr(v), uintptr(v) + uintptr(n)}
+ top := uintptr(n) - nstkbar
+ stkbarSlice := slice{add(v, top), 0, maxstkbar}
+ return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
}
// Small stacks are allocated with a fixed-size free-list allocator.
@@ -243,7 +249,9 @@ func stackalloc(n uint32) stack {
if stackDebug >= 1 {
print(" allocated ", v, "\n")
}
- return stack{uintptr(v), uintptr(v) + uintptr(n)}
+ top := uintptr(n) - nstkbar
+ stkbarSlice := slice{add(v, top), 0, maxstkbar}
+ return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
}
func stackfree(stk stack, n uintptr) {
@@ -556,7 +564,7 @@ func copystack(gp *g, newsize uintptr) {
used := old.hi - gp.sched.sp
// allocate new stack
- new := stackalloc(uint32(newsize))
+ new, newstkbar := stackalloc(uint32(newsize))
if stackPoisonCopy != 0 {
fillstack(new, 0xfd)
}
@@ -582,12 +590,17 @@ func copystack(gp *g, newsize uintptr) {
}
memmove(unsafe.Pointer(new.hi-used), unsafe.Pointer(old.hi-used), used)
+ // copy old stack barriers to new stack barrier array
+ newstkbar = newstkbar[:len(gp.stkbar)]
+ copy(newstkbar, gp.stkbar)
+
// Swap out old stack for new one
gp.stack = new
gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request
gp.sched.sp = new.hi - used
oldsize := gp.stackAlloc
gp.stackAlloc = newsize
+ gp.stkbar = newstkbar
// free old stack
if stackPoisonCopy != 0 {
@@ -794,6 +807,8 @@ func shrinkstack(gp *g) {
stackfree(gp.stack, gp.stackAlloc)
gp.stack.lo = 0
gp.stack.hi = 0
+ gp.stkbar = nil
+ gp.stkbarPos = 0
}
return
}