aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/stack.c
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2013-06-28 17:52:17 +0400
committerDmitriy Vyukov <dvyukov@google.com>2013-06-28 17:52:17 +0400
commit1e112cd59f560129f4dca5e9af7c3cbc445850b6 (patch)
tree8f4607e22d36f17f179fc6c28fdcc025c5caabb5 /src/pkg/runtime/stack.c
parentab1270bcfc2410c8b4637a2e3b530a8f51494de1 (diff)
downloadgo-1e112cd59f560129f4dca5e9af7c3cbc445850b6.tar.xz
runtime: preempt goroutines for GC
The last patch for preemptive scheduler, with this change stoptheworld issues preemption requests every 100us. Update #543. R=golang-dev, daniel.morsing, rsc CC=golang-dev https://golang.org/cl/10264044
Diffstat (limited to 'src/pkg/runtime/stack.c')
-rw-r--r--src/pkg/runtime/stack.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c
index 16dfa041a0..2150d5ec1f 100644
--- a/src/pkg/runtime/stack.c
+++ b/src/pkg/runtime/stack.c
@@ -211,7 +211,10 @@ runtime·newstack(void)
gp->status = Gwaiting;
gp->waitreason = "stack split";
reflectcall = framesize==1;
+ if(reflectcall)
+ framesize = 0;
+ // For reflectcall the context already points to beginning of reflect·call.
if(!reflectcall)
runtime·rewindmorestack(&gp->sched);
@@ -238,9 +241,24 @@ runtime·newstack(void)
runtime·throw("runtime: stack split argsize");
}
- reflectcall = framesize==1;
- if(reflectcall)
- framesize = 0;
+ if(gp->stackguard0 == StackPreempt) {
+ if(gp == m->g0)
+ runtime·throw("runtime: preempt g0");
+ if(oldstatus == Grunning && (m->p == nil || m->p->status != Prunning))
+ runtime·throw("runtime: g is running but p is not");
+ // Be conservative about where we preempt.
+ // We are interested in preempting user Go code, not runtime code.
+ if(oldstatus != Grunning || m->locks || m->mallocing || m->gcing) {
+ // Let the goroutine keep running for now.
+ // TODO(dvyukov): remember but delay the preemption.
+ gp->stackguard0 = gp->stackguard;
+ gp->status = oldstatus;
+ runtime·gogo(&gp->sched); // never return
+ }
+ // Act like goroutine called runtime.Gosched.
+ gp->status = oldstatus;
+ runtime·gosched0(gp); // never return
+ }
if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->stackguard) {
// special case: called from reflect.call (framesize==1)