aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-07-18 12:26:47 -0400
committerRuss Cox <rsc@golang.org>2013-07-18 12:26:47 -0400
commitef12bbfc9ddbb168fcd2ab0ad0bd364e40a1ab7f (patch)
treee27bce91a05d14e669fac7203d0258ef1f64cd07 /src/pkg/runtime
parent8166b2da192919679cd4583c4edb34becbe36e8c (diff)
downloadgo-ef12bbfc9ddbb168fcd2ab0ad0bd364e40a1ab7f.tar.xz
runtime: disable preemption during deferreturn
Deferreturn is synthesizing a new call frame. It must not be interrupted between copying the args there and fixing up the program counter, or else the stack will be in an inconsistent state, one that will confuse the garbage collector. R=golang-dev, dvyukov CC=golang-dev https://golang.org/cl/11522043
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/panic.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c
index 120f7706e7..5692c537a0 100644
--- a/src/pkg/runtime/panic.c
+++ b/src/pkg/runtime/panic.c
@@ -175,10 +175,19 @@ runtime·deferreturn(uintptr arg0, ...)
argp = (byte*)&arg0;
if(d->argp != argp)
return;
+
+ // Moving arguments around.
+ // Do not allow preemption here, because the garbage collector
+ // won't know the form of the arguments until the jmpdefer can
+ // flip the PC over to fn.
+ m->locks++;
runtime·memmove(argp, d->args, d->siz);
fn = d->fn;
popdefer();
freedefer(d);
+ m->locks--;
+ if(m->locks == 0 && g->preempt)
+ g->stackguard0 = StackPreempt;
runtime·jmpdefer(fn, argp);
}