diff options
| author | Dmitriy Vyukov <dvyukov@google.com> | 2011-10-06 18:10:14 +0300 |
|---|---|---|
| committer | Dmitriy Vyukov <dvyukov@google.com> | 2011-10-06 18:10:14 +0300 |
| commit | 56959158331072ed17801aa539a0d6f28064b511 (patch) | |
| tree | 1420df3557880dd9b7a0bbd343bf3aaedb231b78 /src/pkg/runtime/proc.c | |
| parent | 504963e6a466bd0c13c6f36f1ca129602151e598 (diff) | |
| download | go-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.c | 19 |
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; } |
