aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/proc.c
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2011-10-06 18:10:14 +0300
committerDmitriy Vyukov <dvyukov@google.com>2011-10-06 18:10:14 +0300
commit56959158331072ed17801aa539a0d6f28064b511 (patch)
tree1420df3557880dd9b7a0bbd343bf3aaedb231b78 /src/pkg/runtime/proc.c
parent504963e6a466bd0c13c6f36f1ca129602151e598 (diff)
downloadgo-56959158331072ed17801aa539a0d6f28064b511.tar.xz
runtime: fix spurious deadlock reporting
Fixes #2337. Unfortunate sequence of events is: 1. maxcpu=2, mcpu=1, grunning=1 2. starttheworld creates an extra M: maxcpu=2, mcpu=2, grunning=1 4. the goroutine calls runtime.GOMAXPROCS(1) maxcpu=1, mcpu=2, grunning=1 5. since it sees mcpu>maxcpu, it calls gosched() 6. schedule() deschedules the goroutine: maxcpu=1, mcpu=1, grunning=0 7. schedule() call getnextandunlock() which fails to pick up the goroutine again, because canaddcpu() fails, because mcpu==maxcpu 8. then it sees that grunning==0, reports deadlock and terminates R=golang-dev, rsc CC=golang-dev https://golang.org/cl/5191044
Diffstat (limited to 'src/pkg/runtime/proc.c')
-rw-r--r--src/pkg/runtime/proc.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 3655412005..5a9d477bc7 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -602,9 +602,9 @@ top:
}
int32
-runtime·helpgc(void)
+runtime·helpgc(bool *extra)
{
- M *m;
+ M *mp;
int32 n, max;
// Figure out how many CPUs to use.
@@ -621,13 +621,15 @@ runtime·helpgc(void)
runtime·lock(&runtime·sched);
n = 0;
- while(n < max && (m = mget(nil)) != nil) {
+ while(n < max && (mp = mget(nil)) != nil) {
n++;
- m->helpgc = 1;
- m->waitnextg = 0;
- runtime·notewakeup(&m->havenextg);
+ mp->helpgc = 1;
+ mp->waitnextg = 0;
+ runtime·notewakeup(&mp->havenextg);
}
runtime·unlock(&runtime·sched);
+ if(extra)
+ *extra = n != max;
return n;
}
@@ -685,9 +687,10 @@ runtime·starttheworld(bool extra)
// initialization work so is definitely running),
// but m is not running a specific goroutine,
// so set the helpgc flag as a signal to m's
- // first schedule(nil) to mcpu--.
+ // first schedule(nil) to mcpu-- and grunning--.
m = startm();
m->helpgc = 1;
+ runtime·sched.grunning++;
}
schedunlock();
}
@@ -833,6 +836,8 @@ schedule(G *gp)
v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift);
if(atomic_mcpu(v) > maxgomaxprocs)
runtime·throw("negative mcpu in scheduler");
+ // Compensate for increment in starttheworld().
+ runtime·sched.grunning--;
m->helpgc = 0;
}