runtime: 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.
R=r, r2
CC=golang-dev
https://golang.org/cl/4254041
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 455a39e..ba16f48 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -166,6 +166,18 @@
}
}
+// 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 @@
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 @@
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 @@
gp->lockedm = nil;
m->lockedg = nil;
}
+ gp->idlem = nil;
unwindstack(gp, nil);
gfput(gp);
if(--runtime·sched.gcount == 0)
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 4456e9b..5db86a1 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -197,6 +197,7 @@
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 @@
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