changeset 8253:bc2e1d97cdd3

sync with jsr166 repo
author mduigou
date Thu, 18 Apr 2013 18:03:09 -0700
parents 43a585e1e1ab
children 93e2fccee8f2
files src/share/classes/java/util/concurrent/ConcurrentHashMap.java src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java src/share/classes/java/util/concurrent/ForkJoinPool.java
diffstat 3 files changed, 264 insertions(+), 373 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Apr 18 18:02:43 2013 -0700
+++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Apr 18 18:03:09 2013 -0700
@@ -37,6 +37,8 @@
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.CountedCompleter;
 import java.util.Spliterator;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
 import java.util.function.*;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -655,7 +657,7 @@
         if ((cmpc = Comparable.class).isAssignableFrom(c)) {
             while (cmpc.isAssignableFrom(s = c.getSuperclass()))
                 c = s; // find topmost comparable class
-            if ((ts  = c.getGenericInterfaces()) != null) {
+            if ((ts = c.getGenericInterfaces()) != null) {
                 for (int i = 0; i < ts.length; ++i) {
                     if (((t = ts[i]) instanceof ParameterizedType) &&
                         ((p = (ParameterizedType)t).getRawType() == cmpc) &&
@@ -792,7 +794,7 @@
         @SuppressWarnings("unchecked") final TreeNode<V> getTreeNode
             (int h, Object k, TreeNode<V> p, Class<?> cc) {
             while (p != null) {
-                int dir, ph;  Object pk;
+                int dir, ph; Object pk;
                 if ((ph = p.hash) != h)
                     dir = (h < ph) ? -1 : 1;
                 else if ((pk = p.key) == k || k.equals(pk))
@@ -2510,7 +2512,7 @@
          * anyway.
          */
         final int preSplit() {
-            int b;  ForkJoinPool pool;
+            int b; ForkJoinPool pool;
             if ((b = batch) < 0) { // force initialization
                 int sp = (((pool = getPool()) == null) ?
                           ForkJoinPool.getCommonPoolParallelism() :
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Apr 18 18:02:43 2013 -0700
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Apr 18 18:03:09 2013 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent;
 import java.util.*;
+import java.util.stream.Stream;
+import java.util.Spliterator;
+import java.util.stream.Streams;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.BiFunction;
@@ -3604,7 +3607,7 @@
                 return Spliterator.DISTINCT | Spliterator.ORDERED |
                     Spliterator.SORTED;
             }
-            public final Comparator<? super K>  getComparator() {
+            public final Comparator<? super K> getComparator() {
                 return SubMap.this.comparator();
             }
         }
@@ -3839,10 +3842,10 @@
 
         @SuppressWarnings("unchecked")
         public Spliterator<K> trySplit() {
-            Node<K,V> e;
+            Node<K,V> e; K ek;
             Comparator<? super K> cmp = comparator;
             K f = fence;
-            if ((e = current) != null) {
+            if ((e = current) != null && (ek = e.key) != null) {
                 for (Index<K,V> q = row; q != null; q = row = q.down) {
                     Index<K,V> s; Node<K,V> n; K sk;
                     if ((s = q.right) != null) {
@@ -3853,9 +3856,13 @@
                             n.helpDelete(b, n.next);
                         }
                         if (n != null && (sk = n.key) != null &&
+                            (cmp != null ?
+                             (cmp.compare(sk, ek) > 0) :
+                             ((Comparable<? super K>)sk).compareTo(ek) > 0) &&
                             (f == null ||
-                             (cmp != null ? (cmp.compare(f, sk) > 0) :
-                              (((Comparable<? super K>)f).compareTo(sk) > 0)))) {
+                             (cmp != null ?
+                              (cmp.compare(sk, f) < 0) :
+                              ((Comparable<? super K>)sk).compareTo(f) < 0))) {
                             current = n;
                             Index<K,V> r = q.down;
                             row = (s.right != null) ? s : s.down;
@@ -3913,7 +3920,7 @@
                 Spliterator.NONNULL;
         }
 
-        public final Comparator<? super K>  getComparator() {
+        public final Comparator<? super K> getComparator() {
             return comparator;
         }
     }
@@ -3928,10 +3935,10 @@
 
         @SuppressWarnings("unchecked")
         public Spliterator<V> trySplit() {
-            Node<K,V> e;
+            Node<K,V> e; K ek;
             Comparator<? super K> cmp = comparator;
             K f = fence;
-            if ((e = current) != null) {
+            if ((e = current) != null && (ek = e.key) != null) {
                 for (Index<K,V> q = row; q != null; q = row = q.down) {
                     Index<K,V> s; Node<K,V> n; K sk;
                     if ((s = q.right) != null) {
@@ -3942,9 +3949,13 @@
                             n.helpDelete(b, n.next);
                         }
                         if (n != null && (sk = n.key) != null &&
+                            (cmp != null ?
+                             (cmp.compare(sk, ek) > 0) :
+                             ((Comparable<? super K>)sk).compareTo(ek) > 0) &&
                             (f == null ||
-                             (cmp != null ? (cmp.compare(f, sk) > 0) :
-                              (((Comparable<? super K>)f).compareTo(sk) > 0)))) {
+                             (cmp != null ?
+                              (cmp.compare(sk, f) < 0) :
+                              ((Comparable<? super K>)sk).compareTo(f) < 0))) {
                             current = n;
                             Index<K,V> r = q.down;
                             row = (s.right != null) ? s : s.down;
@@ -4015,10 +4026,10 @@
 
         @SuppressWarnings("unchecked")
         public Spliterator<Map.Entry<K,V>> trySplit() {
-            Node<K,V> e;
+            Node<K,V> e; K ek;
             Comparator<? super K> cmp = comparator;
             K f = fence;
-            if ((e = current) != null) {
+            if ((e = current) != null && (ek = e.key) != null) {
                 for (Index<K,V> q = row; q != null; q = row = q.down) {
                     Index<K,V> s; Node<K,V> n; K sk;
                     if ((s = q.right) != null) {
@@ -4029,10 +4040,13 @@
                             n.helpDelete(b, n.next);
                         }
                         if (n != null && (sk = n.key) != null &&
+                            (cmp != null ?
+                             (cmp.compare(sk, ek) > 0) :
+                             ((Comparable<? super K>)sk).compareTo(ek) > 0) &&
                             (f == null ||
                              (cmp != null ?
-                              (cmp.compare(f, sk) > 0) :
-                              (((Comparable<? super K>)f).compareTo(sk) > 0)))) {
+                              (cmp.compare(sk, f) < 0) :
+                              ((Comparable<? super K>)sk).compareTo(f) < 0))) {
                             current = n;
                             Index<K,V> r = q.down;
                             row = (s.right != null) ? s : s.down;
@@ -4045,7 +4059,7 @@
             return null;
         }
 
-        public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) {
+        public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
             if (action == null) throw new NullPointerException();
             K f = fence;
             Comparator<? super K> cmp = comparator;
@@ -4096,10 +4110,11 @@
                 Spliterator.NONNULL;
         }
 
-        public Comparator<Map.Entry<K,V>> getComparator() {
+        public final Comparator<Map.Entry<K,V>> getComparator() {
             return comparator == null ? null :
-                   Comparators.byKey(comparator);
+                Comparators.byKey(comparator);
         }
+
     }
 
     // Unsafe mechanics
--- a/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Apr 18 18:02:43 2013 -0700
+++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Apr 18 18:03:09 2013 -0700
@@ -157,6 +157,7 @@
  * @since 1.7
  * @author Doug Lea
  */
+@sun.misc.Contended
 public class ForkJoinPool extends AbstractExecutorService {
 
     /*
@@ -337,33 +338,28 @@
      * has not yet entered the wait queue. We solve this by requiring
      * a full sweep of all workers (via repeated calls to method
      * scan()) both before and after a newly waiting worker is added
-     * to the wait queue. During a rescan, the worker might release
-     * some other queued worker rather than itself, which has the same
-     * net effect. Because enqueued workers may actually be rescanning
-     * rather than waiting, we set and clear the "parker" field of
-     * WorkQueues to reduce unnecessary calls to unpark.  (This
-     * requires a secondary recheck to avoid missed signals.)  Note
-     * the unusual conventions about Thread.interrupts surrounding
-     * parking and other blocking: Because interrupts are used solely
-     * to alert threads to check termination, which is checked anyway
-     * upon blocking, 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.
+     * to the wait queue.  Because enqueued workers may actually be
+     * rescanning rather than waiting, we set and clear the "parker"
+     * field of WorkQueues to reduce unnecessary calls to unpark.
+     * (This requires a secondary recheck to avoid missed signals.)
+     * Note the unusual conventions about Thread.interrupts
+     * surrounding parking and other blocking: Because interrupts are
+     * used solely to alert threads to check termination, which is
+     * checked anyway upon blocking, 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.
      *
      * Signalling.  We create or wake up workers only when there
      * appears to be at least one task they might be able to find and
-     * execute. However, many other threads may notice the same task
-     * and each signal to wake up a thread that might take it. So in
-     * general, pools will be over-signalled.  When a submission is
-     * added or another worker adds a task to a queue that has fewer
-     * than two tasks, they signal waiting workers (or trigger
-     * creation of new ones if fewer than the given parallelism level
-     * -- signalWork), and may leave a hint to the unparked worker to
-     * help signal others upon wakeup).  These primary signals are
-     * buttressed by others (see method helpSignal) whenever other
-     * threads scan for work or do not have a task to process.  On
-     * most platforms, signalling (unpark) overhead time is noticeably
+     * execute.  When a submission is added or another worker adds a
+     * task to a queue that has fewer than two tasks, they signal
+     * waiting workers (or trigger creation of new ones if fewer than
+     * the given parallelism level -- signalWork).  These primary
+     * signals are buttressed by others whenever other threads remove
+     * a task from a queue and notice that there are other tasks there
+     * as well.  So in general, pools will be over-signalled. On most
+     * platforms, signalling (unpark) overhead time is noticeably
      * long, and the time between signalling a thread and it actually
      * making progress can be very noticeably long, so it is worth
      * offloading these delays from critical paths as much as
@@ -480,7 +476,7 @@
      * Common Pool
      * ===========
      *
-     * The static commonPool always exists after static
+     * The static common pool always exists after static
      * initialization.  Since it (or any other created pool) need
      * never be used, we minimize initial construction overhead and
      * footprint to the setup of about a dozen fields, with no nested
@@ -489,7 +485,7 @@
      *
      * When external threads submit to the common pool, they can
      * perform subtask processing (see externalHelpJoin and related
-     * methods).  This caller-helps policymakes it sensible to set
+     * methods).  This caller-helps policy makes it sensible to set
      * common pool parallelism level to one (or more) less than the
      * total number of available cores, or even zero for pure
      * caller-runs.  We do not need to record whether external
@@ -637,18 +633,10 @@
      * do not want multiple WorkQueue instances or multiple queue
      * arrays sharing cache lines. (It would be best for queue objects
      * and their arrays to share, but there is nothing available to
-     * help arrange that).  Unfortunately, because they are recorded
-     * in a common array, WorkQueue instances are often moved to be
-     * adjacent by garbage collectors. To reduce impact, we use field
-     * padding that works OK on common platforms; this effectively
-     * trades off slightly slower average field access for the sake of
-     * avoiding really bad worst-case access. (Until better JVM
-     * support is in place, this padding is dependent on transient
-     * properties of JVM field layout rules.) We also take care in
-     * allocating, sizing and resizing the array. Non-shared queue
-     * arrays are initialized by workers before use. Others are
-     * allocated on first use.
+     * help arrange that). The @Contended annotation alerts JVMs to
+     * try to keep instances apart.
      */
+    @sun.misc.Contended
     static final class WorkQueue {
         /**
          * Capacity of work-stealing queue array upon initialization.
@@ -670,9 +658,6 @@
          */
         static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
 
-        // Heuristic padding to ameliorate unfortunate memory placements
-        volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
-
         int seed;                  // for random scanning; initialize nonzero
         volatile int eventCount;   // encoded inactivation count; < 0 if inactive
         int nextWait;              // encoded record of next event waiter
@@ -690,9 +675,6 @@
         volatile ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
         ForkJoinTask<?> currentSteal; // current non-local task being executed
 
-        volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
-        volatile Object pad18, pad19, pad1a, pad1b, pad1c, pad1d;
-
         WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
                   int seed) {
             this.pool = pool;
@@ -738,7 +720,7 @@
             ForkJoinTask<?>[] a; ForkJoinPool p;
             int s = top, m, n;
             if ((a = array) != null) {    // ignore if queue removed
-                int j = (((m = a.length - 1) & s) << ASHIFT) + ABASE;
+                long j = (((m = a.length - 1) & s) << ASHIFT) + ABASE;
                 U.putOrderedObject(a, j, task);
                 if ((n = (top = s + 1) - base) <= 2) {
                     if ((p = pool) != null)
@@ -803,13 +785,15 @@
          * appear in ForkJoinPool methods scan and tryHelpStealer.
          */
         final ForkJoinTask<?> pollAt(int b) {
-            ForkJoinTask<?> t; ForkJoinTask<?>[] a;
+            ForkJoinTask<?> t; ForkJoinTask<?>[] a; ForkJoinPool p;
             if ((a = array) != null) {
                 int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
                 if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
                     base == b &&
                     U.compareAndSwapObject(a, j, t, null)) {
-                    base = b + 1;
+                    U.putOrderedInt(this, QBASE, b + 1);
+                    if (top - b > 1 && (p = pool) != null)
+                        p.signalWork(this);
                     return t;
                 }
             }
@@ -820,14 +804,16 @@
          * Takes next task, if one exists, in FIFO order.
          */
         final ForkJoinTask<?> poll() {
-            ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;
+            ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t; ForkJoinPool p;
             while ((b = base) - top < 0 && (a = array) != null) {
                 int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
                 t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
                 if (t != null) {
                     if (base == b &&
                         U.compareAndSwapObject(a, j, t, null)) {
-                        base = b + 1;
+                        U.putOrderedInt(this, QBASE, b + 1);
+                        if (top - b > 1 && (p = pool) != null)
+                            p.signalWork(this);
                         return t;
                     }
                 }
@@ -978,9 +964,10 @@
          * Polls for and executes the given task or any other task in
          * its CountedCompleter computation.
          */
-        final boolean pollAndExecCC(ForkJoinTask<?> root) {
+        final boolean pollAndExecCC(ForkJoinTask<?> root, ForkJoinPool spool) {
             ForkJoinTask<?>[] a; int b; Object o;
-            outer: while ((b = base) - top < 0 && (a = array) != null) {
+            outer: while (root.status >= 0 && (b = base) - top < 0 &&
+                          (a = array) != null) {
                 long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
                 if ((o = U.getObject(a, j)) == null ||
                     !(o instanceof CountedCompleter))
@@ -989,7 +976,9 @@
                     if (r == root) {
                         if (base == b &&
                             U.compareAndSwapObject(a, j, t, null)) {
-                            base = b + 1;
+                            U.putOrderedInt(this, QBASE, b + 1);
+                            if (spool != null && top - b > 1)
+                                spool.signalWork(this);
                             t.doExec();
                             return true;
                         }
@@ -1046,6 +1035,7 @@
 
         // Unsafe mechanics
         private static final sun.misc.Unsafe U;
+        private static final long QBASE;
         private static final long QLOCK;
         private static final int ABASE;
         private static final int ASHIFT;
@@ -1054,6 +1044,8 @@
                 U = sun.misc.Unsafe.getUnsafe();
                 Class<?> k = WorkQueue.class;
                 Class<?> ak = ForkJoinTask[].class;
+                QBASE = U.objectFieldOffset
+                    (k.getDeclaredField("base"));
                 QLOCK = U.objectFieldOffset
                     (k.getDeclaredField("qlock"));
                 ABASE = U.arrayBaseOffset(ak);
@@ -1233,22 +1225,10 @@
     static final int FIFO_QUEUE          =  1;
     static final int SHARED_QUEUE        = -1;
 
-    // bounds for #steps in scan loop -- must be power 2 minus 1
-    private static final int MIN_SCAN    = 0x1ff;   // cover estimation slop
-    private static final int MAX_SCAN    = 0x1ffff; // 4 * max workers
+    // Mininum number of scans before blocking in scan() and related methods
+    private static final int MIN_RESCANS = 0x0fff;
 
     // Instance fields
-
-    /*
-     * Field layout of this class tends to matter more than one would
-     * like. Runtime layout order is only loosely related to
-     * declaration order and may differ across JVMs, but the following
-     * empirically works OK on current JVMs.
-     */
-
-    // Heuristic padding to ameliorate unfortunate memory placements
-    volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
-
     volatile long stealCount;                  // collects worker counts
     volatile long ctl;                         // main pool control
     volatile int plock;                        // shutdown status and seqLock
@@ -1259,9 +1239,6 @@
     final UncaughtExceptionHandler ueh;        // per-worker UEH
     final String workerNamePrefix;             // to create worker name string
 
-    volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
-    volatile Object pad18, pad19, pad1a, pad1b;
-
     /**
      * Acquires the plock lock to protect worker array and related
      * updates. This method is called only if an initial CAS on plock
@@ -1475,13 +1452,14 @@
             (ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
             (q = ws[m & z & SQMASK]) != null &&
             U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
-            int b = q.base, s = q.top, n, an;
-            if ((a = q.array) != null && (an = a.length) > (n = s + 1 - b)) {
-                int j = (((an - 1) & s) << ASHIFT) + ABASE;
+            int s, am, n;
+            if ((a = q.array) != null &&
+                (am = a.length - 1) > (n = (s = q.top) - q.base)) {
+                int j = ((am & s) << ASHIFT) + ABASE;
                 U.putOrderedObject(a, j, task);
                 q.top = s + 1;                     // push on to deque
                 q.qlock = 0;
-                if (n <= 2)
+                if (n <= 1)
                     signalWork(q);
                 return;
             }
@@ -1512,7 +1490,7 @@
         if ((r = ThreadLocalRandom.getProbe()) == 0) {
             ThreadLocalRandom.localInit();
             r = ThreadLocalRandom.getProbe();
-            }
+        }
         for (;;) {
             WorkQueue[] ws; WorkQueue q; int ps, m, k;
             boolean move = false;
@@ -1543,7 +1521,7 @@
                     try {                      // locked version of push
                         if ((a != null && a.length > s + 1 - q.base) ||
                             (a = q.growArray()) != null) {   // must presize
-                            int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
+                            long j = (((a.length - 1) & s) << ASHIFT) + ABASE;
                             U.putOrderedObject(a, j, task);
                             q.top = s + 1;
                             submitted = true;
@@ -1589,35 +1567,33 @@
     /**
      * Tries to create or activate a worker if too few are active.
      *
-     * @param q the (non-null) queue holding tasks to be signalled
+     * @param q if non-null, the queue holding tasks to be processed
      */
     final void signalWork(WorkQueue q) {
-        int hint = q.poolIndex;
-        long c; int e, u, i, n; WorkQueue[] ws; WorkQueue w; Thread p;
-        while ((u = (int)((c = ctl) >>> 32)) < 0) {
-            if ((e = (int)c) > 0) {
-                if ((ws = workQueues) != null && ws.length > (i = e & SMASK) &&
-                    (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
-                    long nc = (((long)(w.nextWait & E_MASK)) |
-                               ((long)(u + UAC_UNIT) << 32));
-                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                        w.hint = hint;
-                        w.eventCount = (e + E_SEQ) & E_MASK;
-                        if ((p = w.parker) != null)
-                            U.unpark(p);
-                        break;
-                    }
-                    if (q.top - q.base <= 0)
-                        break;
-                }
-                else
-                    break;
-            }
-            else {
+        for (;;) {
+            long c; int e, u, i; WorkQueue[] ws; WorkQueue w; Thread p;
+            if ((u = (int)((c = ctl) >>> 32)) >= 0)
+                break;
+            if ((e = (int)c) <= 0) {
                 if ((short)u < 0)
                     tryAddWorker();
                 break;
             }
+            if ((ws = workQueues) == null || ws.length <= (i = e & SMASK) ||
+                (w = ws[i]) == null)
+                break;
+            int wec = w.eventCount;
+            long nc = (((long)(w.nextWait & E_MASK)) |
+                       ((long)(u + UAC_UNIT) << 32));
+            if (wec == (e | INT_SIGN) &&
+                U.compareAndSwapLong(this, CTL, c, nc)) {
+                w.eventCount = (e + E_SEQ) & E_MASK;
+                if ((p = w.parker) != null)
+                    U.unpark(p);
+                break;
+            }
+            if (q == null || q.base - q.top >= 0) // quit if empty
+                break;
         }
     }
 
@@ -1645,114 +1621,59 @@
      * The scan terminates upon either finding a non-empty queue, or
      * completing the sweep. If the worker is not inactivated, it
      * takes and returns a task from this queue. Otherwise, if not
-     * activated, it signals workers (that may include itself) and
-     * returns so caller can retry. Also returns for true if the
-     * worker array may have changed during an empty scan.  On failure
-     * to find a task, we take one of the following actions, after
-     * which the caller will retry calling this method unless
-     * terminated.
-     *
-     * * If pool is terminating, terminate the worker.
-     *
-     * * If not already enqueued, try to inactivate and enqueue the
-     * worker on wait queue. Or, if inactivating has caused the pool
-     * to be quiescent, relay to idleAwaitWork to possibly shrink
-     * pool.
-     *
-     * * If already enqueued and none of the above apply, possibly
-     * park awaiting signal, else lingering to help scan and signal.
-     *
-     * * If a non-empty queue discovered or left as a hint,
-     * help wake up other workers before return.
+     * activated, it tries to activate itself or some other worker by
+     * signalling. Also indicates retry if the worker array may have
+     * changed during an empty scan.  On failure to find a task, if
+     * not already enqueued, tries to inactivate and enqueue the
+     * worker on wait queue and then rescan. Otherwise relays to one
+     * of the actions in onEmptyScan.
      *
      * @param w the worker (via its WorkQueue)
      * @return a task or null if none found
      */
     private final ForkJoinTask<?> scan(WorkQueue w) {
         WorkQueue[] ws; int m;
-        int ps = plock;                          // read plock before ws
+        int ps = plock;                              // read plock before ws
         if (w != null && (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
-            int ec = w.eventCount;               // ec is negative if inactive
+            int ec = w.eventCount;                   // ec negative if inactive
             int r = w.seed; r ^= r << 13; r ^= r >>> 17; w.seed = r ^= r << 5;
-            w.hint = -1;                         // update seed and clear hint
-            int j = ((m + m + 1) | MIN_SCAN) & MAX_SCAN;
-            do {
-                WorkQueue q; ForkJoinTask<?>[] a; int b;
-                if ((q = ws[(r + j) & m]) != null && (b = q.base) - q.top < 0 &&
-                    (a = q.array) != null) {     // probably nonempty
-                    int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
-                    ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getObjectVolatile(a, i);
-                    if (q.base == b && ec >= 0 && t != null &&
+            for (int j = (m << 1) | (ec < 0 ? MIN_RESCANS : 0xf);;) {
+                WorkQueue q; int b, s; ForkJoinTask<?>[] a;
+                if ((q = ws[(r - j) & m]) != null && // probably nonempty
+                    (b = q.base) - (s = q.top) < 0 && (a = q.array) != null) {
+                    long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                    ForkJoinTask<?> t =
+                        (ForkJoinTask<?>)U.getObjectVolatile(a, i);
+                    if ((ec >= 0 || (ec = w.eventCount) >= 0) &&
+                        q.base == b && t != null &&
                         U.compareAndSwapObject(a, i, t, null)) {
-                        if ((q.base = b + 1) - q.top < 0)
+                        U.putOrderedInt(q, QBASE, b + 1);
+                        if (q.top - b > 1)
                             signalWork(q);
-                        return t;                // taken
+                        return t;
                     }
-                    else if ((ec < 0 || j < m) && (int)(ctl >> AC_SHIFT) <= 0) {
-                        w.hint = (r + j) & m;    // help signal below
-                        break;                   // cannot take
+                    if (--j < m) {                   // restart to revisit
+                        if (ec < 0)                  // help activate
+                            signalWork(q);
+                        break;
                     }
                 }
-            } while (--j >= 0);
-
-            int h, e, ns; long c, sc; WorkQueue q;
-            if ((ns = w.nsteals) != 0) {
-                if (U.compareAndSwapLong(this, STEALCOUNT,
-                                         sc = stealCount, sc + ns))
-                    w.nsteals = 0;               // collect steals and rescan
-            }
-            else if (plock != ps)                // consistency check
-                ;                                // skip
-            else if ((e = (int)(c = ctl)) < 0)
-                w.qlock = -1;                    // pool is terminating
-            else {
-                if ((h = w.hint) < 0) {
-                    if (ec >= 0) {               // try to enqueue/inactivate
-                        long nc = (((long)ec |
-                                    ((c - AC_UNIT) & (AC_MASK|TC_MASK))));
-                        w.nextWait = e;          // link and mark inactive
-                        w.eventCount = ec | INT_SIGN;
-                        if (ctl != c || !U.compareAndSwapLong(this, CTL, c, nc))
-                            w.eventCount = ec;   // unmark on CAS failure
-                        else if ((int)(c >> AC_SHIFT) == 1 - (config & SMASK))
-                            idleAwaitWork(w, nc, c);
+                else if (--j < 0) {
+                    long c = ctl; int e;
+                    long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
+                    if (plock == ps) {
+                        if ((e = (int)c) < 0)
+                            w.qlock = -1;            // pool is terminating
+                        else if (ec >= 0) {
+                            w.nextWait = e;          // try to enqueue/inactivate
+                            w.eventCount = ec | INT_SIGN;
+                            if (!U.compareAndSwapLong(this, CTL, c, nc))
+                                w.eventCount = ec;   // unmark on CAS failure
+                        }
+                        else
+                            onEmptyScan(w, c);
                     }
-                    else if (w.eventCount < 0 && ctl == c) {
-                        Thread wt = Thread.currentThread();
-                        Thread.interrupted();    // clear status
-                        U.putObject(wt, PARKBLOCKER, this);
-                        w.parker = wt;           // emulate LockSupport.park
-                        if (w.eventCount < 0)    // recheck
-                            U.park(false, 0L);   // block
-                        w.parker = null;
-                        U.putObject(wt, PARKBLOCKER, null);
-                    }
-                }
-                if ((h >= 0 || (h = w.hint) >= 0) &&
-                    (ws = workQueues) != null && h < ws.length &&
-                    (q = ws[h]) != null) {      // signal others before retry
-                    WorkQueue v; Thread p; int u, i, s;
-                    for (int n = (config & SMASK) - 1;;) {
-                        int idleCount = (w.eventCount < 0) ? 0 : -1;
-                        if (((s = idleCount - q.base + q.top) <= n &&
-                             (n = s) <= 0) ||
-                            (u = (int)((c = ctl) >>> 32)) >= 0 ||
-                            (e = (int)c) <= 0 || m < (i = e & SMASK) ||
-                            (v = ws[i]) == null)
-                            break;
-                        long nc = (((long)(v.nextWait & E_MASK)) |
-                                   ((long)(u + UAC_UNIT) << 32));
-                        if (v.eventCount != (e | INT_SIGN) ||
-                            !U.compareAndSwapLong(this, CTL, c, nc))
-                            break;
-                        v.hint = h;
-                        v.eventCount = (e + E_SEQ) & E_MASK;
-                        if ((p = v.parker) != null)
-                            U.unpark(p);
-                        if (--n <= 0)
-                            break;
-                    }
+                    break;
                 }
             }
         }
@@ -1760,7 +1681,8 @@
     }
 
     /**
-     * If inactivating worker w has caused the pool to become
+     * A continuation of scan(), possibly blocking or terminating
+     * worker w. ALso, if inactivating w has caused the pool to become
      * quiescent, checks for pool termination, and, so long as this is
      * not the only worker, waits for event for up to a given
      * duration.  On timeout, if ctl has not changed, terminates the
@@ -1768,74 +1690,41 @@
      * repeat this process.
      *
      * @param w the calling worker
-     * @param currentCtl the ctl value triggering possible quiescence
-     * @param prevCtl the ctl value to restore if thread is terminated
+     * @param c the ctl value triggering possible quiescence
      */
-    private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) {
-        if (w != null && w.eventCount < 0 &&
-            !tryTerminate(false, false) && (int)prevCtl != 0 &&
-            ctl == currentCtl) {
-            int dc = -(short)(currentCtl >>> TC_SHIFT);
-            long parkTime = dc < 0 ? FAST_IDLE_TIMEOUT: (dc + 1) * IDLE_TIMEOUT;
-            long deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
-            Thread wt = Thread.currentThread();
-            while (ctl == currentCtl) {
-                Thread.interrupted();  // timed variant of version in scan()
+    private final void onEmptyScan(WorkQueue w, long c) {
+        int ec, ns;
+        int d = (int)(c >> AC_SHIFT) + (config & SMASK); // 0 if quiescent
+        if (w != null && (ec = w.eventCount) < 0 &&
+            (d != 0 || !tryTerminate(false, false))) {
+            long pc = 0L, parkTime = 0L, deadline = 0L;
+            if (d == 0 && ec == (((int)c) | INT_SIGN) &&
+                (pc = (((long)(w.nextWait & E_MASK)) |
+                       ((long)(((int)(c >>> 32)) + UAC_UNIT) << 32))) != 0) {
+                int dc = -(short)(c >>> TC_SHIFT);
+                parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT:
+                            (dc + 1) * IDLE_TIMEOUT);
+                deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
+            }
+            if ((ns = w.nsteals) != 0) {
+                long sc = stealCount;
+                if (U.compareAndSwapLong(this, STEALCOUNT, sc, sc + ns))
+                    w.nsteals = 0;                // collect steals and rescan
+            }
+            else if (w.eventCount < 0) {
+                Thread wt = Thread.currentThread();
+                Thread.interrupted();             // clear status
                 U.putObject(wt, PARKBLOCKER, this);
-                w.parker = wt;
-                if (ctl == currentCtl)
-                    U.park(false, parkTime);
+                w.parker = wt;                    // emulate LockSupport.park
+                if (w.eventCount < 0)             // recheck
+                    U.park(false, parkTime);      // block
                 w.parker = null;
                 U.putObject(wt, PARKBLOCKER, null);
-                if (ctl != currentCtl)
-                    break;
-                if (deadline - System.nanoTime() <= 0L &&
-                    U.compareAndSwapLong(this, CTL, currentCtl, prevCtl)) {
+                if (parkTime != 0L && w.eventCount < 0 && ctl == c &&
+                    deadline - System.nanoTime() <= 0L &&
+                    U.compareAndSwapLong(this, CTL, c, pc)) {
                     w.eventCount = (w.eventCount + E_SEQ) | E_MASK;
-                    w.hint = -1;
                     w.qlock = -1;   // shrink
-                    break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Scans through queues looking for work while joining a task; if
-     * any present, signals. May return early if more signalling is
-     * detectably unneeded.
-     *
-     * @param task return early if done
-     * @param origin an index to start scan
-     */
-    private void helpSignal(ForkJoinTask<?> task, int origin) {
-        WorkQueue[] ws; WorkQueue w; Thread p; long c; int m, u, e, i, s;
-        if (task != null && task.status >= 0 &&
-            (u = (int)(ctl >>> 32)) < 0 && (u >> UAC_SHIFT) < 0 &&
-            (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
-            outer: for (int k = origin, j = m; j >= 0; --j) {
-                WorkQueue q = ws[k++ & m];
-                for (int n = m;;) { // limit to at most m signals
-                    if (task.status < 0)
-                        break outer;
-                    if (q == null ||
-                        ((s = -q.base + q.top) <= n && (n = s) <= 0))
-                        break;
-                    if ((u = (int)((c = ctl) >>> 32)) >= 0 ||
-                        (e = (int)c) <= 0 || m < (i = e & SMASK) ||
-                        (w = ws[i]) == null)
-                        break outer;
-                    long nc = (((long)(w.nextWait & E_MASK)) |
-                               ((long)(u + UAC_UNIT) << 32));
-                    if (w.eventCount != (e | INT_SIGN))
-                        break outer;
-                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                        w.eventCount = (e + E_SEQ) & E_MASK;
-                        if ((p = w.parker) != null)
-                            U.unpark(p);
-                        if (--n <= 0)
-                            break;
-                    }
                 }
             }
         }
@@ -1888,7 +1777,7 @@
                         }
                     }
                     for (;;) { // help stealer or descend to its stealer
-                        ForkJoinTask[] a;  int b;
+                        ForkJoinTask[] a; int b;
                         if (subtask.status < 0)     // surround probes with
                             continue restart;       //   consistency checks
                         if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
@@ -1901,7 +1790,9 @@
                             stat = 1;               // apparent progress
                             if (t != null && v.base == b &&
                                 U.compareAndSwapObject(a, i, t, null)) {
-                                v.base = b + 1;     // help stealer
+                                U.putOrderedInt(v, QBASE, b + 1);
+                                if (v.top - b > 1)
+                                    signalWork(v);
                                 joiner.runSubtask(t);
                             }
                             else if (v.base == b && ++steps == MAX_HELP)
@@ -1932,23 +1823,20 @@
      * and run tasks within the target's computation.
      *
      * @param task the task to join
-     * @param mode if shared, exit upon completing any task
-     * if all workers are active
      */
-    private int helpComplete(ForkJoinTask<?> task, int mode) {
-        WorkQueue[] ws; WorkQueue q; int m, n, s, u;
+    private int helpComplete(ForkJoinTask<?> task, ForkJoinPool spool) {
+        WorkQueue[] ws; int m;
         if (task != null && (ws = workQueues) != null &&
             (m = ws.length - 1) >= 0) {
-            for (int j = 1, origin = j;;) {
+            for (int j = 1, k = m;;) {
+                WorkQueue q; int s;
                 if ((s = task.status) < 0)
                     return s;
-                if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
-                    origin = j;
-                    if (mode == SHARED_QUEUE &&
-                        ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0))
-                        break;
-                }
-                else if ((j = (j + 2) & m) == origin)
+                if ((q = ws[j & m]) != null && q.pollAndExecCC(task, spool))
+                    k = m;
+                else if (--k >= 0)
+                    j += 2;
+                else
                     break;
             }
         }
@@ -2019,18 +1907,14 @@
             joiner.currentJoin = task;
             do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
                          joiner.tryRemoveAndExec(task)); // process local tasks
-            if (s >= 0 && (s = task.status) >= 0) {
-                helpSignal(task, joiner.poolIndex);
-                if ((s = task.status) >= 0 &&
-                    (task instanceof CountedCompleter))
-                    s = helpComplete(task, LIFO_QUEUE);
-            }
+            if (s >= 0 && (s = task.status) >= 0 &&
+                (task instanceof CountedCompleter))
+                s = helpComplete(task, this);
             while (s >= 0 && (s = task.status) >= 0) {
                 if ((!joiner.isEmpty() ||           // try helping
                      (s = tryHelpStealer(joiner, task)) == 0) &&
                     (s = task.status) >= 0) {
-                    helpSignal(task, joiner.poolIndex);
-                    if ((s = task.status) >= 0 && tryCompensate()) {
+                    if (tryCompensate()) {
                         if (task.trySetSignal() && (s = task.status) >= 0) {
                             synchronized (task) {
                                 if (task.status >= 0) {
@@ -2043,7 +1927,8 @@
                                     task.notifyAll();
                             }
                         }
-                        long c;                          // re-activate
+                        // reactivate
+                        long c;
                         do {} while (!U.compareAndSwapLong
                                      (this, CTL, c = ctl, c + AC_UNIT));
                     }
@@ -2069,12 +1954,9 @@
             joiner.currentJoin = task;
             do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
                          joiner.tryRemoveAndExec(task));
-            if (s >= 0 && (s = task.status) >= 0) {
-                helpSignal(task, joiner.poolIndex);
-                if ((s = task.status) >= 0 &&
-                    (task instanceof CountedCompleter))
-                    s = helpComplete(task, LIFO_QUEUE);
-            }
+            if (s >= 0 && (s = task.status) >= 0 &&
+                (task instanceof CountedCompleter))
+                s = helpComplete(task, this);
             if (s >= 0 && joiner.isEmpty()) {
                 do {} while (task.status >= 0 &&
                              tryHelpStealer(joiner, task) > 0);
@@ -2096,11 +1978,11 @@
                 for (int j = (m + 1) << 2; j >= 0; --j) {
                     if ((q = ws[(((r + j) << 1) | 1) & m]) != null &&
                         q.base - q.top < 0)
-                    return q;
+                        return q;
                 }
             }
-                    if (plock == ps)
-                        return null;
+            if (plock == ps)
+                return null;
         }
     }
 
@@ -2113,23 +1995,17 @@
     final void helpQuiescePool(WorkQueue w) {
         for (boolean active = true;;) {
             long c; WorkQueue q; ForkJoinTask<?> t; int b;
-            while ((t = w.nextLocalTask()) != null) {
-                if (w.base - w.top < 0)
-                    signalWork(w);
+            while ((t = w.nextLocalTask()) != null)
                 t.doExec();
-            }
             if ((q = findNonEmptyStealQueue(w.nextSeed())) != null) {
                 if (!active) {      // re-establish active count
                     active = true;
                     do {} while (!U.compareAndSwapLong
                                  (this, CTL, c = ctl, c + AC_UNIT));
                 }
-                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
-                    if (q.base - q.top < 0)
-                        signalWork(q);
+                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
                     w.runSubtask(t);
             }
-                }
             else if (active) {       // decrement active count without queuing
                 long nc = (c = ctl) - AC_UNIT;
                 if ((int)(nc >> AC_SHIFT) + (config & SMASK) == 0)
@@ -2155,13 +2031,10 @@
                 return t;
             if ((q = findNonEmptyStealQueue(w.nextSeed())) == null)
                 return null;
-            if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
-                if (q.base - q.top < 0)
-                    signalWork(q);
+            if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
                 return t;
         }
     }
-    }
 
     /**
      * Returns a cheap heuristic guide for task partitioning when
@@ -2255,15 +2128,15 @@
                 releasePlock(nps);
         }
         for (long c;;) {
-            if (((c = ctl) & STOP_BIT) != 0) {      // already terminating
+            if (((c = ctl) & STOP_BIT) != 0) {     // already terminating
                 if ((short)(c >>> TC_SHIFT) == -(config & SMASK)) {
                     synchronized (this) {
-                        notifyAll();                // signal when 0 workers
+                        notifyAll();               // signal when 0 workers
                     }
                 }
                 return true;
             }
-            if (!now) {                             // check if idle & no tasks
+            if (!now) {                            // check if idle & no tasks
                 WorkQueue[] ws; WorkQueue w;
                 if ((int)(c >> AC_SHIFT) != -(config & SMASK))
                     return false;
@@ -2272,8 +2145,8 @@
                         if ((w = ws[i]) != null) {
                             if (!w.isEmpty()) {    // signal unprocessed tasks
                                 signalWork(w);
-                            return false;
-                    }
+                                return false;
+                            }
                             if ((i & 1) != 0 && w.eventCount >= 0)
                                 return false;      // unqueued inactive worker
                         }
@@ -2344,7 +2217,7 @@
      */
     static boolean tryExternalUnpush(ForkJoinTask<?> t) {
         ForkJoinPool p; WorkQueue[] ws; WorkQueue q;
-        ForkJoinTask<?>[] a;  int m, s, z;
+        ForkJoinTask<?>[] a; int m, s, z;
         if (t != null &&
             (z = ThreadLocalRandom.getProbe()) != 0 &&
             (p = common) != null &&
@@ -2374,12 +2247,14 @@
      * other queues via helpComplete.
      */
     private void externalHelpComplete(WorkQueue q, ForkJoinTask<?> root) {
-        ForkJoinTask<?>[] a; int m;
-        if (q != null && (a = q.array) != null && (m = (a.length - 1)) >= 0 &&
-            root != null && root.status >= 0) {
-            for (;;) {
-                int s, u; Object o; CountedCompleter<?> task = null;
-                if ((s = q.top) - q.base > 0) {
+        ForkJoinTask<?>[] a; int m; WorkQueue[] ws;
+        if (root != null && q != null && (a = q.array) != null &&
+            (m = (a.length - 1)) >= 0) {
+            outer: for (;;) {
+                int s, b, u; Object o;
+                if (root.status < 0)
+                    return;
+                if ((s = q.top) - q.base > 0) { // try pop
                     long j = ((m & (s - 1)) << ASHIFT) + ABASE;
                     if ((o = U.getObject(a, j)) != null &&
                         (o instanceof CountedCompleter)) {
@@ -2390,28 +2265,43 @@
                                     if (q.array == a && q.top == s &&
                                         U.compareAndSwapObject(a, j, t, null)) {
                                         q.top = s - 1;
-                                        task = t;
+                                        q.qlock = 0;
+                                        t.doExec();
                                     }
-                                    q.qlock = 0;
+                                    else
+                                        q.qlock = 0;
                                 }
-                                break;
+                                continue outer;
                             }
                         } while ((r = r.completer) != null);
                     }
                 }
-                if (task != null)
-                    task.doExec();
-                if (root.status < 0 ||
-                    (config != 0 &&
-                     ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0)))
+                if ((b = q.base) - q.top < 0) { // try poll
+                    if (root.status < 0)
+                        return;
+                    long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                    if ((o = U.getObject(a, j)) == null ||
+                        !(o instanceof CountedCompleter))
+                        break;
+                    CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;
+                    for (;;) {
+                        if (r == root) {
+                            if (q.base == b &&
+                                U.compareAndSwapObject(a, j, t, null)) {
+                                U.putOrderedInt(q, QBASE, b + 1);
+                                t.doExec();
+                            }
+                            break;
+                        }
+                        if ((r = r.completer) == null)
+                            break outer;
+                    }
+                }
+                else
                     break;
-                if (task == null) {
-                    helpSignal(root, q.poolIndex);
-                    if (root.status >= 0)
-                        helpComplete(root, SHARED_QUEUE);
-                    break;
-                }
             }
+            if (root.status >= 0)
+                helpComplete(root, null);
         }
     }
 
@@ -2422,7 +2312,7 @@
     static void externalHelpJoin(ForkJoinTask<?> t) {
         // Some hard-to-avoid overlap with tryExternalUnpush
         ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w;
-        ForkJoinTask<?>[] a;  int m, s, n, z;
+        ForkJoinTask<?>[] a; int m, s, n, z;
         if (t != null &&
             (z = ThreadLocalRandom.getProbe()) != 0 &&
             (p = common) != null &&
@@ -2445,12 +2335,8 @@
                         q.qlock = 0;
                 }
             }
-            if (t.status >= 0) {
-                if (t instanceof CountedCompleter)
-                    p.externalHelpComplete(q, t);
-                else
-                    p.helpSignal(t, q.poolIndex);
-            }
+            if (t.status >= 0 && (t instanceof CountedCompleter))
+                p.externalHelpComplete(q, t);
         }
     }
 
@@ -2547,7 +2433,7 @@
      * makeCommonPool.
      */
     private ForkJoinPool(int parallelism,
-                 ForkJoinWorkerThreadFactory factory,
+                         ForkJoinWorkerThreadFactory factory,
                          UncaughtExceptionHandler handler,
                          boolean asyncMode,
                          String workerNamePrefix) {
@@ -3165,11 +3051,8 @@
                 ForkJoinTask<?> t; WorkQueue q; int b;
                 if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) {
                     found = true;
-                    if ((t = q.pollAt(b)) != null) {
-                        if (q.base - q.top < 0)
-                            signalWork(q);
+                    if ((t = q.pollAt(b)) != null)
                         t.doExec();
-                    }
                     break;
                 }
             }
@@ -3284,20 +3167,7 @@
         Thread t = Thread.currentThread();
         if (t instanceof ForkJoinWorkerThread) {
             ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
-            while (!blocker.isReleasable()) { // variant of helpSignal
-                WorkQueue[] ws; WorkQueue q; int m, u;
-                if ((ws = p.workQueues) != null && (m = ws.length - 1) >= 0) {
-                    for (int i = 0; i <= m; ++i) {
-                        if (blocker.isReleasable())
-                            return;
-                        if ((q = ws[i]) != null && q.base - q.top < 0) {
-                            p.signalWork(q);
-                            if ((u = (int)(p.ctl >>> 32)) >= 0 ||
-                                (u >> UAC_SHIFT) >= 0)
-                                break;
-                        }
-                    }
-                }
+            while (!blocker.isReleasable()) {
                 if (p.tryCompensate()) {
                     try {
                         do {} while (!blocker.isReleasable() &&
@@ -3336,6 +3206,7 @@
     private static final long STEALCOUNT;
     private static final long PLOCK;
     private static final long INDEXSEED;
+    private static final long QBASE;
     private static final long QLOCK;
 
     static {
@@ -3355,6 +3226,8 @@
             PARKBLOCKER = U.objectFieldOffset
                 (tk.getDeclaredField("parkBlocker"));
             Class<?> wk = WorkQueue.class;
+            QBASE = U.objectFieldOffset
+                (wk.getDeclaredField("base"));
             QLOCK = U.objectFieldOffset
                 (wk.getDeclaredField("qlock"));
             Class<?> ak = ForkJoinTask[].class;
@@ -3398,15 +3271,16 @@
                 parallelism = Integer.parseInt(pp);
             if (fp != null)
                 factory = ((ForkJoinWorkerThreadFactory)ClassLoader.
-                       getSystemClassLoader().loadClass(fp).newInstance());
+                           getSystemClassLoader().loadClass(fp).newInstance());
             if (hp != null)
                 handler = ((UncaughtExceptionHandler)ClassLoader.
                            getSystemClassLoader().loadClass(hp).newInstance());
         } catch (Exception ignore) {
         }
 
-        if (parallelism < 0)
-            parallelism = Runtime.getRuntime().availableProcessors();
+        if (parallelism < 0 && // default 1 less than #cores
+            (parallelism = Runtime.getRuntime().availableProcessors() - 1) < 0)
+            parallelism = 0;
         if (parallelism > MAX_CAP)
             parallelism = MAX_CAP;
         return new ForkJoinPool(parallelism, factory, handler, false,