Skip to content

Commit 92e9ac6

Browse files
author
Doug Lea
committed
8345294: test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java timeout with JTREG_TEST_THREAD_FACTORY=Virtual
Reviewed-by: alanb
1 parent b42d79e commit 92e9ac6

File tree

2 files changed

+97
-14
lines changed

2 files changed

+97
-14
lines changed

src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -610,12 +610,11 @@ public class ForkJoinPool extends AbstractExecutorService {
610610
* it tries to deactivate()), giving up (and rescanning) on "ctl"
611611
* contention. To avoid missed signals during deactivation, the
612612
* method rescans and reactivates if there may have been a missed
613-
* (external) signal during deactivation. To reduce false-alarm
614-
* reactivations while doing so, we scan multiple times
615-
* (analogously to method quiescent()) before trying to
616-
* reactivate. Because idle workers are often not yet blocked
617-
* (parked), we use a WorkQueue field to advertise that a waiter
618-
* actually needs unparking upon signal.
613+
* signal during deactivation. To reduce false-alarm reactivations
614+
* while doing so, we scan multiple times (analogously to method
615+
* quiescent()) before trying to reactivate. Because idle workers
616+
* are often not yet blocked (parked), we use a WorkQueue field to
617+
* advertise that a waiter actually needs unparking upon signal.
619618
*
620619
* Quiescence. Workers scan looking for work, giving up when they
621620
* don't find any, without being sure that none are available.
@@ -1996,7 +1995,7 @@ private int deactivate(WorkQueue w, int phase) {
19961995
return IDLE;
19971996
int p = phase | IDLE, activePhase = phase + (IDLE << 1);
19981997
long pc = ctl, qc = (activePhase & LMASK) | ((pc - RC_UNIT) & UMASK);
1999-
w.stackPred = (int)pc; // set ctl stack link
1998+
int sp = w.stackPred = (int)pc; // set ctl stack link
20001999
w.phase = p;
20012000
if (!compareAndSetCtl(pc, qc)) // try to enqueue
20022001
return w.phase = phase; // back out on possible signal
@@ -2006,18 +2005,18 @@ private int deactivate(WorkQueue w, int phase) {
20062005
(qs = queues) == null || (n = qs.length) <= 0)
20072006
return IDLE; // terminating
20082007
int prechecks = Math.min(ac, 2); // reactivation threshold
2009-
for (int k = Math.max(n + (n << 1), SPIN_WAITS << 1);;) {
2010-
WorkQueue q; int cap; ForkJoinTask<?>[] a;
2008+
for (int k = Math.max(n << 2, SPIN_WAITS << 1);;) {
2009+
WorkQueue q; int cap; ForkJoinTask<?>[] a; long c;
20112010
if (w.phase == activePhase)
20122011
return activePhase;
20132012
if (--k < 0)
20142013
return awaitWork(w, p); // block, drop, or exit
2015-
if ((k & 1) != 0)
2016-
Thread.onSpinWait(); // interleave spins and rechecks
2017-
else if ((q = qs[k & (n - 1)]) != null &&
2018-
(a = q.array) != null && (cap = a.length) > 0 &&
2014+
if ((q = qs[k & (n - 1)]) == null)
2015+
Thread.onSpinWait();
2016+
else if ((a = q.array) != null && (cap = a.length) > 0 &&
20192017
a[q.base & (cap - 1)] != null && --prechecks < 0 &&
2020-
ctl == qc && compareAndSetCtl(qc, pc))
2018+
(int)(c = ctl) == activePhase &&
2019+
compareAndSetCtl(c, (sp & LMASK) | ((c + RC_UNIT) & UMASK)))
20212020
return w.phase = activePhase; // reactivate
20222021
}
20232022
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/* @test
25+
* @library /test/lib
26+
* @bug 8345294
27+
* @run main/othervm --enable-native-access=ALL-UNNAMED Starvation 100000
28+
*/
29+
30+
import java.time.Duration;
31+
import java.time.Instant;
32+
import java.util.ArrayList;
33+
import java.util.concurrent.CountDownLatch;
34+
import java.util.concurrent.atomic.AtomicReference;
35+
import jdk.test.lib.thread.VThreadPinner;
36+
37+
public class Starvation {
38+
public static void main(String[] args) throws Exception {
39+
int iterations = Integer.parseInt(args[0]);
40+
41+
for (int i = 0; i < iterations; i++) {
42+
var exRef = new AtomicReference<Exception>();
43+
Thread thread = Thread.startVirtualThread(() -> {
44+
try {
45+
runTest();
46+
} catch (Exception e) {
47+
exRef.set(e);
48+
}
49+
});
50+
while (!thread.join(Duration.ofSeconds(1))) {
51+
System.out.format("%s iteration %d waiting for %s%n", Instant.now(), i, thread);
52+
}
53+
Exception ex = exRef.get();
54+
if (ex != null) {
55+
throw ex;
56+
}
57+
}
58+
}
59+
60+
static void runTest() throws InterruptedException {
61+
int nprocs = Runtime.getRuntime().availableProcessors();
62+
63+
var threads = new ArrayList<Thread>();
64+
Object lock = new Object();
65+
synchronized (lock) {
66+
for (int i = 0; i < nprocs - 1; i++) {
67+
var started = new CountDownLatch(1);
68+
Thread thread = Thread.startVirtualThread(() -> {
69+
started.countDown();
70+
VThreadPinner.runPinned(() -> {
71+
synchronized (lock) {
72+
}
73+
});
74+
});
75+
started.await();
76+
threads.add(thread);
77+
}
78+
}
79+
80+
for (Thread t : threads) {
81+
t.join();
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)