Commit cb945ba6 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: fix deadlock

The deadlock episodically occurs on misc/cgo/test/TestCthread.
The problem is that starttheworld() leaves some P's with local work
without M's. Then all active M's enter into syscalls, but reject to
wake another M's due to the following check (both in entersyscallblock() and in retake()):
if(p->runqhead == p->runqtail &&
        runtime·atomicload(&runtime·sched.nmspinning) +
        runtime·atomicload(&runtime·sched.npidle) > 0)
        continue;

R=rsc
CC=golang-dev
https://golang.org/cl/7424054
parent 60f783d9
......@@ -392,7 +392,7 @@ mhelpgc(void)
void
runtime·starttheworld(void)
{
P *p;
P *p, *p1;
M *mp;
bool add;
......@@ -405,6 +405,7 @@ runtime·starttheworld(void)
procresize(runtime·gomaxprocs);
runtime·gcwaiting = 0;
p1 = nil;
while(p = pidleget()) {
// procresize() puts p's with work at the beginning of the list.
// Once we reach a p without a run queue, the rest don't have one either.
......@@ -414,8 +415,9 @@ runtime·starttheworld(void)
}
mp = mget();
if(mp == nil) {
pidleput(p);
break;
p->link = p1;
p1 = p;
continue;
}
if(mp->nextp)
runtime·throw("starttheworld: inconsistent mp->nextp");
......@@ -428,6 +430,13 @@ runtime·starttheworld(void)
}
runtime·unlock(&runtime·sched);
while(p1) {
p = p1;
p1 = p1->link;
add = false;
newm(nil, p);
}
if(add) {
// If GC could have used another helper proc, start one now,
// in the hope that it will be available next time.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment