From 1e112cd59f560129f4dca5e9af7c3cbc445850b6 Mon Sep 17 00:00:00 2001 From: Dmitriy Vyukov Date: Fri, 28 Jun 2013 17:52:17 +0400 Subject: 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 --- src/pkg/runtime/stack.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src/pkg/runtime/stack.c') 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) -- cgit v1.3