ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/ForkJoinPool.java
(Generate patch)

Comparing jsr166/src/jsr166y/ForkJoinPool.java (file contents):
Revision 1.125 by jsr166, Tue Feb 21 00:19:23 2012 UTC vs.
Revision 1.134 by jsr166, Sun Oct 21 06:40:20 2012 UTC

# Line 629 | Line 629 | public class ForkJoinPool extends Abstra
629          final ForkJoinPool pool;   // the containing pool (may be null)
630          final ForkJoinWorkerThread owner; // owning thread or null if shared
631          volatile Thread parker;    // == owner during call to park; else null
632 <        ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
632 >        volatile ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
633          ForkJoinTask<?> currentSteal; // current non-local task being executed
634          // Heuristic padding to ameliorate unfortunate memory placements
635          Object p00, p01, p02, p03, p04, p05, p06, p07;
# Line 721 | Line 721 | public class ForkJoinPool extends Abstra
721           * version of this method because it is never needed.)
722           */
723          final ForkJoinTask<?> pop() {
724 <            ForkJoinTask<?> t; int m;
725 <            ForkJoinTask<?>[] a = array;
726 <            if (a != null && (m = a.length - 1) >= 0) {
724 >            ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
725 >            if ((a = array) != null && (m = a.length - 1) >= 0) {
726                  for (int s; (s = top - 1) - base >= 0;) {
727 <                    int j = ((m & s) << ASHIFT) + ABASE;
728 <                    if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) == null)
727 >                    long j = ((m & s) << ASHIFT) + ABASE;
728 >                    if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
729                          break;
730                      if (U.compareAndSwapObject(a, j, t, null)) {
731                          top = s;
# Line 830 | Line 829 | public class ForkJoinPool extends Abstra
829          }
830  
831          /**
833         * If present, removes from queue and executes the given task, or
834         * any other cancelled task. Returns (true) immediately on any CAS
835         * or consistency check failure so caller can retry.
836         *
837         * @return false if no progress can be made
838         */
839        final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
840            boolean removed = false, empty = true, progress = true;
841            ForkJoinTask<?>[] a; int m, s, b, n;
842            if ((a = array) != null && (m = a.length - 1) >= 0 &&
843                (n = (s = top) - (b = base)) > 0) {
844                for (ForkJoinTask<?> t;;) {           // traverse from s to b
845                    int j = ((--s & m) << ASHIFT) + ABASE;
846                    t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
847                    if (t == null)                    // inconsistent length
848                        break;
849                    else if (t == task) {
850                        if (s + 1 == top) {           // pop
851                            if (!U.compareAndSwapObject(a, j, task, null))
852                                break;
853                            top = s;
854                            removed = true;
855                        }
856                        else if (base == b)           // replace with proxy
857                            removed = U.compareAndSwapObject(a, j, task,
858                                                             new EmptyTask());
859                        break;
860                    }
861                    else if (t.status >= 0)
862                        empty = false;
863                    else if (s + 1 == top) {          // pop and throw away
864                        if (U.compareAndSwapObject(a, j, t, null))
865                            top = s;
866                        break;
867                    }
868                    if (--n == 0) {
869                        if (!empty && base == b)
870                            progress = false;
871                        break;
872                    }
873                }
874            }
875            if (removed)
876                task.doExec();
877            return progress;
878        }
879
880        /**
832           * Initializes or doubles the capacity of array. Call either
833           * by owner or with lock held -- it is OK for base, but not
834           * top, to move while resizings are in progress.
# Line 939 | Line 890 | public class ForkJoinPool extends Abstra
890          // Execution methods
891  
892          /**
893 <         * Removes and runs tasks until empty, using local mode
894 <         * ordering. Normally called only after checking for apparent
895 <         * non-emptiness.
896 <         */
897 <        final void runLocalTasks() {
898 <            // hoist checks from repeated pop/poll
899 <            ForkJoinTask<?>[] a; int m;
900 <            if ((a = array) != null && (m = a.length - 1) >= 0) {
901 <                if (mode == 0) {
902 <                    for (int s; (s = top - 1) - base >= 0;) {
903 <                        int j = ((m & s) << ASHIFT) + ABASE;
904 <                        ForkJoinTask<?> t =
905 <                            (ForkJoinTask<?>)U.getObjectVolatile(a, j);
955 <                        if (t != null) {
956 <                            if (U.compareAndSwapObject(a, j, t, null)) {
957 <                                top = s;
958 <                                t.doExec();
959 <                            }
960 <                        }
961 <                        else
962 <                            break;
963 <                    }
893 >         * Pops and runs tasks until empty.
894 >         */
895 >        private void popAndExecAll() {
896 >            // A bit faster than repeated pop calls
897 >            ForkJoinTask<?>[] a; int m, s; long j; ForkJoinTask<?> t;
898 >            while ((a = array) != null && (m = a.length - 1) >= 0 &&
899 >                   (s = top - 1) - base >= 0 &&
900 >                   (t = ((ForkJoinTask<?>)
901 >                         U.getObject(a, j = ((m & s) << ASHIFT) + ABASE)))
902 >                   != null) {
903 >                if (U.compareAndSwapObject(a, j, t, null)) {
904 >                    top = s;
905 >                    t.doExec();
906                  }
907 <                else {
908 <                    for (int b; (b = base) - top < 0;) {
909 <                        int j = ((m & b) << ASHIFT) + ABASE;
910 <                        ForkJoinTask<?> t =
911 <                            (ForkJoinTask<?>)U.getObjectVolatile(a, j);
912 <                        if (t != null) {
913 <                            if (base == b &&
914 <                                U.compareAndSwapObject(a, j, t, null)) {
915 <                                base = b + 1;
916 <                                t.doExec();
917 <                            }
918 <                        } else if (base == b) {
919 <                            if (b + 1 == top)
907 >            }
908 >        }
909 >
910 >        /**
911 >         * Polls and runs tasks until empty.
912 >         */
913 >        private void pollAndExecAll() {
914 >            for (ForkJoinTask<?> t; (t = poll()) != null;)
915 >                t.doExec();
916 >        }
917 >
918 >        /**
919 >         * If present, removes from queue and executes the given task, or
920 >         * any other cancelled task. Returns (true) immediately on any CAS
921 >         * or consistency check failure so caller can retry.
922 >         *
923 >         * @return 0 if no progress can be made, else positive
924 >         * (this unusual convention simplifies use with tryHelpStealer.)
925 >         */
926 >        final int tryRemoveAndExec(ForkJoinTask<?> task) {
927 >            int stat = 1;
928 >            boolean removed = false, empty = true;
929 >            ForkJoinTask<?>[] a; int m, s, b, n;
930 >            if ((a = array) != null && (m = a.length - 1) >= 0 &&
931 >                (n = (s = top) - (b = base)) > 0) {
932 >                for (ForkJoinTask<?> t;;) {           // traverse from s to b
933 >                    int j = ((--s & m) << ASHIFT) + ABASE;
934 >                    t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
935 >                    if (t == null)                    // inconsistent length
936 >                        break;
937 >                    else if (t == task) {
938 >                        if (s + 1 == top) {           // pop
939 >                            if (!U.compareAndSwapObject(a, j, task, null))
940                                  break;
941 <                            Thread.yield(); // wait for lagging update
941 >                            top = s;
942 >                            removed = true;
943                          }
944 +                        else if (base == b)           // replace with proxy
945 +                            removed = U.compareAndSwapObject(a, j, task,
946 +                                                             new EmptyTask());
947 +                        break;
948 +                    }
949 +                    else if (t.status >= 0)
950 +                        empty = false;
951 +                    else if (s + 1 == top) {          // pop and throw away
952 +                        if (U.compareAndSwapObject(a, j, t, null))
953 +                            top = s;
954 +                        break;
955 +                    }
956 +                    if (--n == 0) {
957 +                        if (!empty && base == b)
958 +                            stat = 0;
959 +                        break;
960                      }
961                  }
962              }
963 +            if (removed)
964 +                task.doExec();
965 +            return stat;
966          }
967  
968          /**
969           * Executes a top-level task and any local tasks remaining
970           * after execution.
989         *
990         * @return true unless terminating
971           */
972 <        final boolean runTask(ForkJoinTask<?> t) {
993 <            boolean alive = true;
972 >        final void runTask(ForkJoinTask<?> t) {
973              if (t != null) {
974                  currentSteal = t;
975                  t.doExec();
976 <                if (top != base)        // conservative guard
977 <                    runLocalTasks();
976 >                if (top != base) {       // process remaining local tasks
977 >                    if (mode == 0)
978 >                        popAndExecAll();
979 >                    else
980 >                        pollAndExecAll();
981 >                }
982                  ++nsteals;
983                  currentSteal = null;
984              }
1002            else if (runState < 0)      // terminating
1003                alive = false;
1004            return alive;
985          }
986  
987          /**
# Line 1124 | Line 1104 | public class ForkJoinPool extends Abstra
1104      private static final RuntimePermission modifyThreadPermission;
1105  
1106      /**
1107 <     * Per-thread submission bookeeping. Shared across all pools
1107 >     * Per-thread submission bookkeeping. Shared across all pools
1108       * to reduce ThreadLocal pollution and because random motion
1109       * to avoid contention in one pool is likely to hold for others.
1110       */
# Line 1160 | Line 1140 | public class ForkJoinPool extends Abstra
1140       * traversal parameters at the expense of sometimes blocking when
1141       * we could be helping.
1142       */
1143 <    private static final int MAX_HELP = 32;
1143 >    private static final int MAX_HELP = 64;
1144  
1145      /**
1146       * Secondary time-based bound (in nanosecs) for helping attempts
# Line 1170 | Line 1150 | public class ForkJoinPool extends Abstra
1150       * value should roughly approximate the time required to create
1151       * and/or activate a worker thread.
1152       */
1153 <    private static final long COMPENSATION_DELAY = 100L * 1000L; // 0.1 millisec
1153 >    private static final long COMPENSATION_DELAY = 1L << 18; // ~0.25 millisec
1154  
1155      /**
1156       * Increment for seed generators. See class ThreadLocal for
# Line 1327 | Line 1307 | public class ForkJoinPool extends Abstra
1307          try {
1308              WorkQueue[] ws = workQueues;
1309              if (w != null && ws != null) {          // skip on shutdown/failure
1310 <                int rs, n;
1331 <                while ((n = ws.length) <            // ensure can hold total
1332 <                       (parallelism + (short)(ctl >>> TC_SHIFT) << 1))
1333 <                    workQueues = ws = Arrays.copyOf(ws, n << 1);
1334 <                int m = n - 1;
1310 >                int rs, n = ws.length, m = n - 1;
1311                  int s = nextSeed += SEED_INCREMENT; // rarely-colliding sequence
1312                  w.seed = (s == 0) ? 1 : s;          // ensure non-zero seed
1313                  int r = (s << 1) | 1;               // use odd-numbered indices
1314 <                while (ws[r &= m] != null)          // step by approx half size
1315 <                    r += ((n >>> 1) & SQMASK) + 2;
1314 >                if (ws[r &= m] != null) {           // collision
1315 >                    int probes = 0;                 // step by approx half size
1316 >                    int step = (n <= 4) ? 2 : ((n >>> 1) & SQMASK) + 2;
1317 >                    while (ws[r = (r + step) & m] != null) {
1318 >                        if (++probes >= n) {
1319 >                            workQueues = ws = Arrays.copyOf(ws, n <<= 1);
1320 >                            m = n - 1;
1321 >                            probes = 0;
1322 >                        }
1323 >                    }
1324 >                }
1325                  w.eventCount = w.poolIndex = r;     // establish before recording
1326                  ws[r] = w;                          // also update seq
1327                  runState = ((rs = runState) & SHUTDOWN) | ((rs + 2) & ~SHUTDOWN);
# Line 1483 | Line 1468 | public class ForkJoinPool extends Abstra
1468          }
1469      }
1470  
1486
1471      // Scanning for tasks
1472  
1473      /**
# Line 1491 | Line 1475 | public class ForkJoinPool extends Abstra
1475       */
1476      final void runWorker(WorkQueue w) {
1477          w.growArray(false);         // initialize queue array in this thread
1478 <        do {} while (w.runTask(scan(w)));
1478 >        do { w.runTask(scan(w)); } while (w.runState >= 0);
1479      }
1480  
1481      /**
# Line 1534 | Line 1518 | public class ForkJoinPool extends Abstra
1518       * awaiting signal,
1519       *
1520       * @param w the worker (via its WorkQueue)
1521 <     * @return a task or null of none found
1521 >     * @return a task or null if none found
1522       */
1523      private final ForkJoinTask<?> scan(WorkQueue w) {
1524          WorkQueue[] ws;                       // first update random seed
# Line 1551 | Line 1535 | public class ForkJoinPool extends Abstra
1535                      t = (ForkJoinTask<?>)U.getObjectVolatile(a, i);
1536                      if (q.base == b && ec >= 0 && t != null &&
1537                          U.compareAndSwapObject(a, i, t, null)) {
1538 <                        q.base = b + 1;       // specialization of pollAt
1538 >                        if (q.top - (q.base = b + 1) > 1)
1539 >                            signalWork();    // help pushes signal
1540                          return t;
1541                      }
1542 <                    else if ((t != null || b + 1 != q.top) &&
1558 <                             (ec < 0 || j <= m)) {
1542 >                    else if (ec < 0 || j <= m) {
1543                          rs = 0;               // mark scan as imcomplete
1544                          break;                // caller can retry after release
1545                      }
# Line 1563 | Line 1547 | public class ForkJoinPool extends Abstra
1547                  if (--j < 0)
1548                      break;
1549              }
1550 +
1551              long c = ctl; int e = (int)c, a = (int)(c >> AC_SHIFT), nr, ns;
1552              if (e < 0)                        // decode ctl on empty scan
1553                  w.runState = -1;              // pool is terminating
# Line 1630 | Line 1615 | public class ForkJoinPool extends Abstra
1615       */
1616      private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) {
1617          if (w.eventCount < 0 && !tryTerminate(false, false) &&
1618 <            (int)prevCtl != 0 && ctl == currentCtl) {
1618 >            (int)prevCtl != 0 && !hasQueuedSubmissions() && ctl == currentCtl) {
1619              Thread wt = Thread.currentThread();
1620              Thread.yield();            // yield before block
1621              while (ctl == currentCtl) {
# Line 1665 | Line 1650 | public class ForkJoinPool extends Abstra
1650       * leaves hints in workers to speed up subsequent calls. The
1651       * implementation is very branchy to cope with potential
1652       * inconsistencies or loops encountering chains that are stale,
1653 <     * unknown, or so long that they are likely cyclic.  All of these
1669 <     * cases are dealt with by just retrying by caller.
1653 >     * unknown, or so long that they are likely cyclic.
1654       *
1655       * @param joiner the joining worker
1656       * @param task the task to join
1657 <     * @return true if found or ran a task (and so is immediately retryable)
1657 >     * @return 0 if no progress can be made, negative if task
1658 >     * known complete, else positive
1659       */
1660 <    private boolean tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
1661 <        WorkQueue[] ws;
1662 <        int m, depth = MAX_HELP;                // remaining chain depth
1663 <        boolean progress = false;
1664 <        if ((ws = workQueues) != null && (m = ws.length - 1) > 0 &&
1665 <            task.status >= 0) {
1666 <            ForkJoinTask<?> subtask = task;     // current target
1667 <            outer: for (WorkQueue j = joiner;;) {
1668 <                WorkQueue stealer = null;       // find stealer of subtask
1669 <                WorkQueue v = ws[j.stealHint & m]; // try hint
1670 <                if (v != null && v.currentSteal == subtask)
1671 <                    stealer = v;
1672 <                else {                          // scan
1673 <                    for (int i = 1; i <= m; i += 2) {
1674 <                        if ((v = ws[i]) != null && v.currentSteal == subtask &&
1675 <                            v != joiner) {
1676 <                            stealer = v;
1677 <                            j.stealHint = i;    // save hint
1678 <                            break;
1660 >    private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
1661 >        int stat = 0, steps = 0;                    // bound to avoid cycles
1662 >        if (joiner != null && task != null) {       // hoist null checks
1663 >            restart: for (;;) {
1664 >                ForkJoinTask<?> subtask = task;     // current target
1665 >                for (WorkQueue j = joiner, v;;) {   // v is stealer of subtask
1666 >                    WorkQueue[] ws; int m, s, h;
1667 >                    if ((s = task.status) < 0) {
1668 >                        stat = s;
1669 >                        break restart;
1670 >                    }
1671 >                    if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
1672 >                        break restart;              // shutting down
1673 >                    if ((v = ws[h = (j.stealHint | 1) & m]) == null ||
1674 >                        v.currentSteal != subtask) {
1675 >                        for (int origin = h;;) {    // find stealer
1676 >                            if (((h = (h + 2) & m) & 15) == 1 &&
1677 >                                (subtask.status < 0 || j.currentJoin != subtask))
1678 >                                continue restart;   // occasional staleness check
1679 >                            if ((v = ws[h]) != null &&
1680 >                                v.currentSteal == subtask) {
1681 >                                j.stealHint = h;    // save hint
1682 >                                break;
1683 >                            }
1684 >                            if (h == origin)
1685 >                                break restart;      // cannot find stealer
1686                          }
1687                      }
1688 <                    if (stealer == null)
1689 <                        break;
1690 <                }
1691 <
1692 <                for (WorkQueue q = stealer;;) { // try to help stealer
1693 <                    ForkJoinTask[] a; ForkJoinTask<?> t; int b;
1694 <                    if (task.status < 0)
1695 <                        break outer;
1696 <                    if ((b = q.base) - q.top < 0 && (a = q.array) != null) {
1697 <                        progress = true;
1698 <                        int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
1699 <                        t = (ForkJoinTask<?>)U.getObjectVolatile(a, i);
1700 <                        if (subtask.status < 0) // must recheck before taking
1701 <                            break outer;
1702 <                        if (t != null &&
1703 <                            q.base == b &&
1704 <                            U.compareAndSwapObject(a, i, t, null)) {
1705 <                            q.base = b + 1;
1706 <                            joiner.runSubtask(t);
1688 >                    for (;;) { // help stealer or descend to its stealer
1689 >                        ForkJoinTask[] a;  int b;
1690 >                        if (subtask.status < 0)     // surround probes with
1691 >                            continue restart;       //   consistency checks
1692 >                        if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
1693 >                            int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
1694 >                            ForkJoinTask<?> t =
1695 >                                (ForkJoinTask<?>)U.getObjectVolatile(a, i);
1696 >                            if (subtask.status < 0 || j.currentJoin != subtask ||
1697 >                                v.currentSteal != subtask)
1698 >                                continue restart;   // stale
1699 >                            stat = 1;               // apparent progress
1700 >                            if (t != null && v.base == b &&
1701 >                                U.compareAndSwapObject(a, i, t, null)) {
1702 >                                v.base = b + 1;     // help stealer
1703 >                                joiner.runSubtask(t);
1704 >                            }
1705 >                            else if (v.base == b && ++steps == MAX_HELP)
1706 >                                break restart;      // v apparently stalled
1707 >                        }
1708 >                        else {                      // empty -- try to descend
1709 >                            ForkJoinTask<?> next = v.currentJoin;
1710 >                            if (subtask.status < 0 || j.currentJoin != subtask ||
1711 >                                v.currentSteal != subtask)
1712 >                                continue restart;   // stale
1713 >                            else if (next == null || ++steps == MAX_HELP)
1714 >                                break restart;      // dead-end or maybe cyclic
1715 >                            else {
1716 >                                subtask = next;
1717 >                                j = v;
1718 >                                break;
1719 >                            }
1720                          }
1716                        else if (q.base == b)
1717                            break outer;        // possibly stalled
1718                    }
1719                    else {                      // descend
1720                        ForkJoinTask<?> next = stealer.currentJoin;
1721                        if (--depth <= 0 || subtask.status < 0 ||
1722                            next == null || next == subtask)
1723                            break outer;        // stale, dead-end, or cyclic
1724                        subtask = next;
1725                        j = stealer;
1726                        break;
1721                      }
1722                  }
1723              }
1724          }
1725 <        return progress;
1725 >        return stat;
1726      }
1727  
1728      /**
# Line 1761 | Line 1755 | public class ForkJoinPool extends Abstra
1755       * check requires a full scan, it is worthwhile in reducing false
1756       * alarms.
1757       *
1758 <     * @param task if nonnull, a task being waited for
1759 <     * @param blocker if nonnull, a blocker being waited for
1758 >     * @param task if non-null, a task being waited for
1759 >     * @param blocker if non-null, a blocker being waited for
1760       * @return true if the caller can block, else should recheck and retry
1761       */
1762      final boolean tryCompensate(ForkJoinTask<?> task, ManagedBlocker blocker) {
# Line 1821 | Line 1815 | public class ForkJoinPool extends Abstra
1815      }
1816  
1817      /**
1818 <     * Helps and/or blocks until the given task is done
1818 >     * Helps and/or blocks until the given task is done.
1819       *
1820       * @param joiner the joining worker
1821       * @param task the task
1822       * @return task status on exit
1823       */
1824      final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
1825 <        ForkJoinTask<?> prevJoin = joiner.currentJoin;
1826 <        joiner.currentJoin = task;
1827 <        long startTime = 0L;
1828 <        for (int k = 0, s; ; ++k) {
1829 <            if ((joiner.isEmpty() ?                  // try to help
1830 <                 !tryHelpStealer(joiner, task) :
1831 <                 !joiner.tryRemoveAndExec(task))) {
1832 <                if (k == 0) {
1833 <                    startTime = System.nanoTime();
1834 <                    tryPollForAndExec(joiner, task); // check uncommon case
1835 <                }
1836 <                else if ((k & (MAX_HELP - 1)) == 0 &&
1837 <                         System.nanoTime() - startTime >= COMPENSATION_DELAY &&
1838 <                         tryCompensate(task, null)) {
1839 <                    if (task.trySetSignal() && task.status >= 0) {
1840 <                        synchronized (task) {
1841 <                            if (task.status >= 0) {
1842 <                                try {                // see ForkJoinTask
1843 <                                    task.wait();     //  for explanation
1844 <                                } catch (InterruptedException ie) {
1825 >        int s;
1826 >        if ((s = task.status) >= 0) {
1827 >            ForkJoinTask<?> prevJoin = joiner.currentJoin;
1828 >            joiner.currentJoin = task;
1829 >            long startTime = 0L;
1830 >            for (int k = 0;;) {
1831 >                if ((s = (joiner.isEmpty() ?           // try to help
1832 >                          tryHelpStealer(joiner, task) :
1833 >                          joiner.tryRemoveAndExec(task))) == 0 &&
1834 >                    (s = task.status) >= 0) {
1835 >                    if (k == 0) {
1836 >                        startTime = System.nanoTime();
1837 >                        tryPollForAndExec(joiner, task); // check uncommon case
1838 >                    }
1839 >                    else if ((k & (MAX_HELP - 1)) == 0 &&
1840 >                             System.nanoTime() - startTime >=
1841 >                             COMPENSATION_DELAY &&
1842 >                             tryCompensate(task, null)) {
1843 >                        if (task.trySetSignal()) {
1844 >                            synchronized (task) {
1845 >                                if (task.status >= 0) {
1846 >                                    try {                // see ForkJoinTask
1847 >                                        task.wait();     //  for explanation
1848 >                                    } catch (InterruptedException ie) {
1849 >                                    }
1850                                  }
1851 +                                else
1852 +                                    task.notifyAll();
1853                              }
1853                            else
1854                                task.notifyAll();
1854                          }
1855 +                        long c;                          // re-activate
1856 +                        do {} while (!U.compareAndSwapLong
1857 +                                     (this, CTL, c = ctl, c + AC_UNIT));
1858                      }
1857                    long c;                          // re-activate
1858                    do {} while (!U.compareAndSwapLong
1859                                 (this, CTL, c = ctl, c + AC_UNIT));
1859                  }
1860 +                if (s < 0 || (s = task.status) < 0) {
1861 +                    joiner.currentJoin = prevJoin;
1862 +                    break;
1863 +                }
1864 +                else if ((k++ & (MAX_HELP - 1)) == MAX_HELP >>> 1)
1865 +                    Thread.yield();                     // for politeness
1866              }
1862            if ((s = task.status) < 0) {
1863                joiner.currentJoin = prevJoin;
1864                return s;
1865            }
1866            else if ((k & (MAX_HELP - 1)) == MAX_HELP >>> 1)
1867                Thread.yield();                     // for politeness
1867          }
1868 +        return s;
1869      }
1870  
1871      /**
# Line 1882 | Line 1882 | public class ForkJoinPool extends Abstra
1882          while ((s = task.status) >= 0 &&
1883                 (joiner.isEmpty() ?
1884                  tryHelpStealer(joiner, task) :
1885 <                joiner.tryRemoveAndExec(task)))
1885 >                joiner.tryRemoveAndExec(task)) != 0)
1886              ;
1887          return s;
1888      }
# Line 1914 | Line 1914 | public class ForkJoinPool extends Abstra
1914          }
1915      }
1916  
1917 +
1918      /**
1919       * Runs tasks until {@code isQuiescent()}. We piggyback on
1920       * active count ctl maintenance, but rather than blocking
# Line 1922 | Line 1923 | public class ForkJoinPool extends Abstra
1923       */
1924      final void helpQuiescePool(WorkQueue w) {
1925          for (boolean active = true;;) {
1926 <            if (w.base - w.top < 0)
1927 <                w.runLocalTasks();  // exhaust local queue
1926 >            ForkJoinTask<?> localTask; // exhaust local queue
1927 >            while ((localTask = w.nextLocalTask()) != null)
1928 >                localTask.doExec();
1929              WorkQueue q = findNonEmptyStealQueue(w);
1930              if (q != null) {
1931                  ForkJoinTask<?> t; int b;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines