}
}
+// 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)
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)
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;
}
gp->lockedm = nil;
m->lockedg = nil;
}
+ gp->idlem = nil;
unwindstack(gp, nil);
gfput(gp);
if(--runtime·sched.gcount == 0)
bool ispanic;
M* m; // for debuggers, but offset not hard-coded
M* lockedm;
+ M* idlem;
int32 sig;
uintptr sigcode0;
uintptr sigcode1;
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