Mercurial > hg > openjdk > jdk7 > jdk
changeset 3989:8fbd15bd6149
7035020: ForkJoinPool.invoke may deadlock if parallelism = 1
Reviewed-by: chegar
author | dl |
---|---|
date | Fri, 08 Apr 2011 10:33:14 +0100 |
parents | 9c29dd06e138 |
children | 4de90f390a48 |
files | src/share/classes/java/util/concurrent/ForkJoinPool.java |
diffstat | 1 files changed, 17 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/util/concurrent/ForkJoinPool.java Fri Apr 08 02:00:09 2011 -0700 +++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java Fri Apr 08 10:33:14 2011 +0100 @@ -791,18 +791,19 @@ /** * Tries to enqueue worker w in wait queue and await change in - * worker's eventCount. If the pool is quiescent, possibly - * terminates worker upon exit. Otherwise, before blocking, - * rescans queues to avoid missed signals. Upon finding work, - * releases at least one worker (which may be the current - * worker). Rescans restart upon detected staleness or failure to - * release due to contention. Note the unusual conventions about - * Thread.interrupt here and elsewhere: Because interrupts are - * used solely to alert threads to check termination, which is - * checked here anyway, we clear status (using Thread.interrupted) - * before any call to park, so that park does not immediately - * return due to status being set via some other unrelated call to - * interrupt in user code. + * worker's eventCount. If the pool is quiescent and there is + * more than one worker, possibly terminates worker upon exit. + * Otherwise, before blocking, rescans queues to avoid missed + * signals. Upon finding work, releases at least one worker + * (which may be the current worker). Rescans restart upon + * detected staleness or failure to release due to + * contention. Note the unusual conventions about Thread.interrupt + * here and elsewhere: Because interrupts are used solely to alert + * threads to check termination, which is checked here anyway, we + * clear status (using Thread.interrupted) before any call to + * park, so that park does not immediately return due to status + * being set via some other unrelated call to interrupt in user + * code. * * @param w the calling worker * @param c the ctl value on entry @@ -823,7 +824,7 @@ else if (w.eventCount != v) return true; // update next time } - if (parallelism + (int)(nc >> AC_SHIFT) == 0 && + if ((int)c != 0 && parallelism + (int)(nc >> AC_SHIFT) == 0 && blockedCount == 0 && quiescerCount == 0) idleAwaitWork(w, nc, c, v); // quiescent for (boolean rescanned = false;;) { @@ -893,7 +894,8 @@ w.parked = false; if (w.eventCount != v) break; - else if (System.nanoTime() - startTime < SHRINK_RATE) + else if (System.nanoTime() - startTime < + SHRINK_RATE - (SHRINK_RATE / 10)) // timing slop Thread.interrupted(); // spurious wakeup else if (UNSAFE.compareAndSwapLong(this, ctlOffset, currentCtl, prevCtl)) { @@ -1175,7 +1177,7 @@ ws[k] = w; nextWorkerIndex = k + 1; int m = g & SMASK; - g = k >= m? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1); + g = k > m? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1); } } finally { scanGuard = g;