Skip to content

Commit dbcfed9

Browse files
committed
runtime: fix scheduler race condition
In starttheworld() we assume that P's with local work are situated in the beginning of idle P list. However, once we start the first M, it can execute all local G's and steal G's from other P's. That breaks the assumption above. Thus starttheworld() will fail to start some P's with local work. It seems that it can not lead to very bad things, but still it's wrong and breaks other assumtions (e.g. we can have a spinning M with local work). The fix is to collect all P's with local work first, and only then start them. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/10051045
1 parent e5cbebc commit dbcfed9

1 file changed

Lines changed: 17 additions & 12 deletions

File tree

src/pkg/runtime/proc.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -420,16 +420,9 @@ runtime·starttheworld(void)
420420
pidleput(p);
421421
break;
422422
}
423-
mp = mget();
424-
if(mp == nil) {
425-
p->link = p1;
426-
p1 = p;
427-
continue;
428-
}
429-
if(mp->nextp)
430-
runtime·throw("starttheworld: inconsistent mp->nextp");
431-
mp->nextp = p;
432-
runtime·notewakeup(&mp->park);
423+
p->m = mget();
424+
p->link = p1;
425+
p1 = p;
433426
}
434427
if(runtime·sched.sysmonwait) {
435428
runtime·sched.sysmonwait = false;
@@ -440,8 +433,18 @@ runtime·starttheworld(void)
440433
while(p1) {
441434
p = p1;
442435
p1 = p1->link;
443-
add = false;
444-
newm(nil, p);
436+
if(p->m) {
437+
mp = p->m;
438+
p->m = nil;
439+
if(mp->nextp)
440+
runtime·throw("starttheworld: inconsistent mp->nextp");
441+
mp->nextp = p;
442+
runtime·notewakeup(&mp->park);
443+
} else {
444+
// Start M to run P. Do not start another M below.
445+
newm(nil, p);
446+
add = false;
447+
}
445448
}
446449

447450
if(add) {
@@ -1154,6 +1157,8 @@ schedule(void)
11541157
}
11551158

11561159
gp = runqget(m->p);
1160+
if(gp && m->spinning)
1161+
runtime·throw("schedule: spinning with local work");
11571162
if(gp == nil)
11581163
gp = findrunnable();
11591164

0 commit comments

Comments
 (0)