// Finds a runnable goroutine to execute.
// Tries to steal from other P's, get g from global queue, poll network.
static G*
-findrunnable1(void)
+findrunnable(void)
{
G *gp;
P *p;
goto top;
}
-static G*
-findrunnable(void)
-{
- G *gp;
- int32 nmspinning;
-
- gp = findrunnable1(); // blocks until work is available
- if(m->spinning) {
- m->spinning = false;
- nmspinning = runtime·xadd(&runtime·sched.nmspinning, -1);
- if(nmspinning < 0)
- runtime·throw("findrunnable: negative nmspinning");
- } else
- nmspinning = runtime·atomicload(&runtime·sched.nmspinning);
-
- // M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
- // so see if we need to wakeup another P here.
- if (nmspinning == 0 && runtime·atomicload(&runtime·sched.npidle) > 0)
- wakep();
-
- return gp;
-}
-
// Injects the list of runnable G's into the scheduler.
// Can run concurrently with GC.
static void
runtime·throw("schedule: spinning with local work");
}
if(gp == nil)
- gp = findrunnable(); // blocks until work is available
+ gp = findrunnable();
+
+ if(m->spinning) {
+ m->spinning = false;
+ runtime·xadd(&runtime·sched.nmspinning, -1);
+ }
+
+ // M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
+ // so see if we need to wakeup another M here.
+ if (m->p->runqhead != m->p->runqtail &&
+ runtime·atomicload(&runtime·sched.nmspinning) == 0 &&
+ runtime·atomicload(&runtime·sched.npidle) > 0) // TODO: fast atomic
+ wakep();
if(gp->lockedm) {
- // Hands off own p to the locked m,
- // then blocks waiting for a new p.
startlockedm(gp);
goto top;
}
<-c
}
-func TestGoroutineParallelism(t *testing.T) {
- const P = 4
- defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
- for try := 0; try < 10; try++ {
- done := make(chan bool)
- x := uint32(0)
- for p := 0; p < P; p++ {
- // Test that all P goroutines are scheduled at the same time
- go func(p int) {
- for i := 0; i < 3; i++ {
- expected := uint32(P*i + p)
- for atomic.LoadUint32(&x) != expected {
- }
- atomic.StoreUint32(&x, expected+1)
- }
- done <- true
- }(p)
- }
- for p := 0; p < P; p++ {
- <-done
- }
- }
-}
-
func TestBlockLocked(t *testing.T) {
const N = 10
c := make(chan bool)