diff options
| author | Dmitriy Vyukov <dvyukov@google.com> | 2013-06-28 17:52:17 +0400 |
|---|---|---|
| committer | Dmitriy Vyukov <dvyukov@google.com> | 2013-06-28 17:52:17 +0400 |
| commit | 1e112cd59f560129f4dca5e9af7c3cbc445850b6 (patch) | |
| tree | 8f4607e22d36f17f179fc6c28fdcc025c5caabb5 /src/pkg/runtime/stack.c | |
| parent | ab1270bcfc2410c8b4637a2e3b530a8f51494de1 (diff) | |
| download | go-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.c | 24 |
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) |
