Strengthen some orderings

This commit is contained in:
Doug Lea 2026-01-03 10:46:15 -05:00
parent 556c5201e4
commit f077eb9eb0

View File

@ -1249,16 +1249,16 @@ public class ForkJoinPool extends AbstractExecutorService
*/
final void push(ForkJoinTask<?> task, ForkJoinPool pool, int unlock) {
ForkJoinTask<?>[] a = array;
int b = base, s = top, m;
int b = base, s = top, room, m;
if (a != null &&
(a.length > s + 1 - b || (a = growArray()) != null) &&
((room = a.length - (s + 1 - b)) > 0 || (a = growArray()) != null) &&
(m = a.length - 1) >= 0) { // else rejected or disabled
top = s + 1;
U.putReferenceVolatile(a, slotOffset(m & s), task);
if (unlock != 1) // release external lock
U.putInt(this, PHASE, unlock);
if (U.getReferenceAcquire(a, slotOffset(m & (s - 1))) == null &&
pool != null)
phase = unlock;
if ((U.getReferenceAcquire(a, slotOffset(m & (s - 1))) == null ||
room <= 0) && pool != null)
pool.signalWork(this, s); // may have appeared empty
}
}
@ -1307,13 +1307,16 @@ public class ForkJoinPool extends AbstractExecutorService
if (a != null && s - b >= 0 && (cap = a.length) > 0) {
if (fifo == 0) {
if ((t = (ForkJoinTask<?>)U.getAndSetReference(
a, slotOffset((cap - 1) & s), null)) != null)
a, slotOffset((cap - 1) & s), null)) != null) {
top = s;
U.storeFence();
}
} else {
do {
if ((t = (ForkJoinTask<?>)U.getAndSetReference(
a, slotOffset((cap - 1) & b), null)) != null) {
base = b + 1;
U.storeFence();
break;
}
if (b == s)
@ -1330,10 +1333,7 @@ public class ForkJoinPool extends AbstractExecutorService
* Takes next task, if one exists, using configured mode.
*/
final ForkJoinTask<?> nextLocalTask() {
U.loadFence(); // ensure ordering for external callers
ForkJoinTask<?> t= nextLocalTask(config & FIFO);
U.storeFence();
return t;
return nextLocalTask(config & FIFO);
}
/**
@ -1350,10 +1350,11 @@ public class ForkJoinPool extends AbstractExecutorService
(internal || (lock = tryLockPhase()) != 1)) {
if (top == p && U.compareAndSetReference(a, k, task, null)) {
taken = true;
U.putIntOpaque(this, TOP, s);
top = s;
U.storeFence();
}
if (!internal)
U.putIntRelease(this, PHASE, lock + NEXTIDLE);
phase = lock + NEXTIDLE;
}
return taken;
}
@ -1413,6 +1414,7 @@ public class ForkJoinPool extends AbstractExecutorService
/**
* Runs the given task, as well as remaining local tasks
*/
// @jdk.internal.vm.annotation.DontInline
final void topLevelExec(ForkJoinTask<?> task, int fifo) {
while (task != null) {
task.doExec();
@ -1452,9 +1454,10 @@ public class ForkJoinPool extends AbstractExecutorService
a, slotOffset(s & m), null));
top = s;
}
U.storeFence();
}
if (!internal)
U.putIntRelease(this, PHASE, lock + NEXTIDLE);
phase = lock + NEXTIDLE;
if (taken)
task.doExec();
break;
@ -1498,10 +1501,12 @@ public class ForkJoinPool extends AbstractExecutorService
break;
if (taken =
(top == p &&
U.compareAndSetReference(a, k, t, null)))
U.compareAndSetReference(a, k, t, null))) {
top = s;
U.storeFence();
}
if (!internal)
U.putIntRelease(this, PHASE, lock + NEXTIDLE);
phase = lock + NEXTIDLE;
if (!taken)
break;
t.doExec();
@ -1537,6 +1542,7 @@ public class ForkJoinPool extends AbstractExecutorService
if (base == b && t != null &&
U.compareAndSetReference(a, k, t, null)) {
base = b + 1;
U.storeFence();
t.doExec();
}
}
@ -2015,16 +2021,23 @@ public class ForkJoinPool extends AbstractExecutorService
}
long sp = (phase + NEXTIDLE) & LMASK, pc = ctl;
U.putInt(w, WorkQueue.PHASE, phase | IDLE);
for (long c;;) { // try to enqueue
for (;;) { // try to enqueue
long c, e;
w.stackPred = (int)pc;
if (pc == (pc = U.compareAndExchangeLong(
this, CTL, pc, c = ((pc - RC_UNIT) & UMASK) | sp))) {
idle = IDLE;
if ((c & RC_MASK) == 0L)
quiescent(); // check quiescent termination
if (((e = runState) & STOP) == 0L &&
((e & SHUTDOWN) == 0L || (c & RC_MASK) > 0L ||
quiescent() <= 0)) { // spin for approx 1 scan cost
int tc = (short)(c >>> TC_SHIFT);
int spins = Math.max((tc << 1) + tc, SPIN_WAITS);
while ((idle = w.phase & IDLE) != 0 && --spins != 0)
Thread.onSpinWait();
}
break;
}
else if ((c & RC_MASK) <= (pc & RC_MASK)) {
else if ((c & RC_MASK) < (pc & RC_MASK)) {
w.phase = phase; // back out if lost to signal
break;
}