From 7cc2dd1a0d0e8cd413fc0b636e2adafe6c9871bd Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Tue, 16 Dec 2025 14:06:14 -0500
Subject: [PATCH] Relax orderings in push
---
.../java/util/concurrent/ForkJoinPool.java | 49 +++++++++----------
1 file changed, 23 insertions(+), 26 deletions(-)
diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index 481a6cc13ff..e504f5fc908 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -1254,55 +1254,52 @@ public class ForkJoinPool extends AbstractExecutorService
* @throws RejectedExecutionException if array could not be resized
*/
final void push(ForkJoinTask> task, ForkJoinPool pool, boolean internal) {
- int s = top, b = base, m, cap, room; ForkJoinTask>[] a;
- if ((a = array) != null && (cap = a.length) > 0) { // else disabled
- if ((room = (m = cap - 1) - (s - b)) >= 0) {
- top = s + 1;
- long pos = slotOffset(m & s);
- if (!internal)
- U.putReference(a, pos, task); // inside lock
- else
- U.getAndSetReference(a, pos, task); // fully fenced
- if (room == 0)
- growArray(a, cap, s);
- }
+ int s = top++; // back out on failure
+ ForkJoinTask>[] a = array;
+ int size = s - base + 1, m;
+ if (((a != null && a.length > size) || (a = growArray(a, s)) != null) &&
+ (m = a.length - 1) >= 0) {
+ a[m & s] = task;
if (!internal)
unlockPhase();
- if (room < 0)
- throw new RejectedExecutionException("Queue capacity exceeded");
- if (pool != null &&
- (room == 0 ||
- U.getReferenceAcquire(a, slotOffset(m & (s - 1))) == null))
- pool.signalWork(this, s); // may have appeared empty
+ if (U.getReferenceAcquire(a, slotOffset(m & (s - 1))) == null &&
+ pool != null)
+ pool.signalWork(this, s); // may have appeared empty
}
}
/**
* Resizes the queue array unless out of memory.
* @param a old array
- * @param cap old array capacity
* @param s current top
+ * @return new array (or throws on OOME)
*/
- private void growArray(ForkJoinTask>[] a, int cap, int s) {
- int newCap = (cap >= 1 << 16) ? cap << 1 : cap << 2;
- ForkJoinTask>[] newArray = null;
- if (a != null && a.length == cap && cap > 0 && newCap > 0) {
+ private ForkJoinTask>[] growArray(ForkJoinTask>[] a, int s) {
+ int cap, newCap;
+ if (a != null && (cap = a.length) > 0 &&
+ (newCap = (cap >= 1 << 16) ? cap << 1 : cap << 2) > 0) {
+ ForkJoinTask>[] newArray = null;
try {
newArray = new ForkJoinTask>[newCap];
} catch (OutOfMemoryError ex) {
}
- if (newArray != null) { // else throw on next push
+ if (newArray != null) {
int mask = cap - 1, newMask = newCap - 1;
- for (int k = s, j = cap; j > 0; --j, --k) {
+ for (int k = s - 1, j = cap; j > 0; --j, --k) {
ForkJoinTask> u; // poll old, push to new
if ((u = (ForkJoinTask>)U.getAndSetReference(
a, slotOffset(k & mask), null)) == null)
break; // lost to pollers
newArray[k & newMask] = u;
}
- updateArray(newArray); // fully fenced
+ updateArray(newArray); // fully fenced
+ return newArray;
}
}
+ top = s; // back out
+ if ((phase & 1) == 0) // unlock if external
+ unlockPhase();
+ throw new RejectedExecutionException("Queue capacity exceeded");
}
/**