]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: idle goroutine
authorRuss Cox <rsc@golang.org>
Mon, 28 Feb 2011 04:32:42 +0000 (23:32 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 28 Feb 2011 04:32:42 +0000 (23:32 -0500)
This functionality might be used in environments
where programs are limited to a single thread,
to simulate a select-driven network server.  It is
not exposed via the standard runtime API.

R=r, r2
CC=golang-dev
https://golang.org/cl/4254041

src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h

index 455a39e22b6613c9dccc0e0adedb6d2b0c05d835..ba16f48bbc0a309b42d4ecd83ed566274e8e3f6f 100644 (file)
@@ -166,6 +166,18 @@ runtime·tracebackothers(G *me)
        }
 }
 
+// Mark this g as m's idle goroutine.
+// This functionality might be used in environments where programs
+// are limited to a single thread, to simulate a select-driven
+// network server.  It is not exposed via the standard runtime API.
+void
+runtime·idlegoroutine(void)
+{
+       if(g->idlem != nil)
+               runtime·throw("g is already an idle goroutine");
+       g->idlem = m;
+}
+
 // Put on `g' queue.  Sched must be locked.
 static void
 gput(G *g)
@@ -177,6 +189,18 @@ gput(G *g)
                mnextg(m, g);
                return;
        }
+       
+       // If g is the idle goroutine for an m, hand it off.
+       if(g->idlem != nil) {
+               if(g->idlem->idleg != nil) {
+                       runtime·printf("m%d idle out of sync: g%d g%d\n",
+                               g->idlem->id,
+                               g->idlem->idleg->goid, g->goid);
+                       runtime·throw("runtime: double idle");
+               }
+               g->idlem->idleg = g;
+               return;
+       }
 
        g->schedlink = nil;
        if(runtime·sched.ghead == nil)
@@ -199,6 +223,9 @@ gget(void)
                if(runtime·sched.ghead == nil)
                        runtime·sched.gtail = nil;
                runtime·sched.gwait--;
+       } else if(m->idleg != nil) {
+               g = m->idleg;
+               m->idleg = nil;
        }
        return g;
 }
@@ -532,6 +559,7 @@ scheduler(void)
                                gp->lockedm = nil;
                                m->lockedg = nil;
                        }
+                       gp->idlem = nil;
                        unwindstack(gp, nil);
                        gfput(gp);
                        if(--runtime·sched.gcount == 0)
index 4456e9b8d4eaecbaa6a1356a829b51178d4b1d64..5db86a177123edda848a1a394401d18c6b03d2b7 100644 (file)
@@ -197,6 +197,7 @@ struct      G
        bool    ispanic;
        M*      m;              // for debuggers, but offset not hard-coded
        M*      lockedm;
+       M*      idlem;
        int32   sig;
        uintptr sigcode0;
        uintptr sigcode1;
@@ -233,6 +234,7 @@ struct      M
        uint32  machport;       // Return address for Mach IPC (OS X)
        MCache  *mcache;
        G*      lockedg;
+       G*      idleg;
        uint32  freglo[16];     // D[i] lsb and F[i]
        uint32  freghi[16];     // D[i] msb and F[i+16]
        uint32  fflag;          // floating point compare flags