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.go22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go
index 27427af955..e593b8a3a8 100644
--- a/src/runtime/stack1.go
+++ b/src/runtime/stack1.go
@@ -246,13 +246,15 @@ func stackalloc(n uint32) stack {
return stack{uintptr(v), uintptr(v) + uintptr(n)}
}
-func stackfree(stk stack) {
+func stackfree(stk stack, n uintptr) {
gp := getg()
- n := stk.hi - stk.lo
v := (unsafe.Pointer)(stk.lo)
if n&(n-1) != 0 {
throw("stack not a power of 2")
}
+ if stk.lo+n < stk.hi {
+ throw("bad stack size")
+ }
if stackDebug >= 1 {
println("stackfree", v, n)
memclr(v, n) // for testing, clobber stack data
@@ -584,14 +586,16 @@ func copystack(gp *g, newsize uintptr) {
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
// free old stack
if stackPoisonCopy != 0 {
fillstack(old, 0xfc)
}
- if newsize > old.hi-old.lo {
+ if newsize > oldsize {
// growing, free stack immediately
- stackfree(old)
+ stackfree(old, oldsize)
} else {
// shrinking, queue up free operation. We can't actually free the stack
// just yet because we might run into the following situation:
@@ -604,6 +608,7 @@ func copystack(gp *g, newsize uintptr) {
// By not freeing, we prevent step #4 until GC is done.
lock(&stackpoolmu)
*(*stack)(unsafe.Pointer(old.lo)) = stackfreequeue
+ *(*uintptr)(unsafe.Pointer(old.lo + ptrSize)) = oldsize
stackfreequeue = old
unlock(&stackpoolmu)
}
@@ -743,7 +748,7 @@ func newstack() {
}
// Allocate a bigger segment and move the stack.
- oldsize := int(gp.stack.hi - gp.stack.lo)
+ oldsize := int(gp.stackAlloc)
newsize := oldsize * 2
if uintptr(newsize) > maxstacksize {
print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
@@ -786,7 +791,7 @@ func shrinkstack(gp *g) {
if gp.stack.lo != 0 {
// Free whole stack - it will get reallocated
// if G is used again.
- stackfree(gp.stack)
+ stackfree(gp.stack, gp.stackAlloc)
gp.stack.lo = 0
gp.stack.hi = 0
}
@@ -796,7 +801,7 @@ func shrinkstack(gp *g) {
throw("missing stack in shrinkstack")
}
- oldsize := gp.stack.hi - gp.stack.lo
+ oldsize := gp.stackAlloc
newsize := oldsize / 2
if newsize < _FixedStack {
return // don't shrink below the minimum-sized stack
@@ -832,7 +837,8 @@ func shrinkfinish() {
unlock(&stackpoolmu)
for s.lo != 0 {
t := *(*stack)(unsafe.Pointer(s.lo))
- stackfree(s)
+ n := *(*uintptr)(unsafe.Pointer(s.lo + ptrSize))
+ stackfree(s, n)
s = t
}
}