Skip to content

Commit 8ac7186

Browse files
committed
8305416: runtime/Thread/TestAlwaysPreTouchStacks.java failed with "Did not find expected NMT output"
Reviewed-by: dholmes, gziemski
1 parent 984fbbb commit 8ac7186

File tree

2 files changed

+50
-21
lines changed

2 files changed

+50
-21
lines changed

test/hotspot/jtreg/ProblemList.txt

-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64
9999
runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64
100100
runtime/CompressedOops/CompressedClassPointers.java 8305765 generic-all
101101
runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all
102-
runtime/Thread/TestAlwaysPreTouchStacks.java 8305416 generic-all
103102
runtime/ErrorHandling/TestDwarf.java 8305489 linux-all
104103

105104
applications/jcstress/copy.java 8229852 linux-all

test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java

+50-20
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.ArrayList;
3030
import java.util.regex.Matcher;
3131
import java.util.regex.Pattern;
32+
import java.util.concurrent.CyclicBarrier;
3233

3334
/*
3435
* @test
@@ -39,40 +40,59 @@
3940
* @run driver TestAlwaysPreTouchStacks
4041
*/
4142

42-
public class TestAlwaysPreTouchStacks extends Thread {
43+
public class TestAlwaysPreTouchStacks {
4344

44-
static private final Thread createTestThread(int stackSize) {
45+
// We will create a bunch of large-stacked threads to make a significant imprint on combined thread stack size
46+
final static int MB = 1024*1024;
47+
static int memoryCeilingMB = 128;
48+
static int threadStackSizeMB = 8;
49+
static int numThreads = memoryCeilingMB / threadStackSizeMB;
50+
static CyclicBarrier gate = new CyclicBarrier(numThreads + 1);
51+
52+
static private final Thread createTestThread(int num) {
4553
Thread t = new Thread(null,
46-
() -> System.out.println("Alive: " + stackSize),
47-
"Thread-" + stackSize, stackSize);
54+
() -> {
55+
System.out.println("Alive: " + num);
56+
try {
57+
// report aliveness, then sleep until VM death
58+
gate.await();
59+
for (;;) {
60+
Thread.sleep(1000);
61+
}
62+
} catch (Exception e) {
63+
e.printStackTrace();
64+
}
65+
},
66+
"TestThread-" + num, threadStackSizeMB * MB);
67+
t.setDaemon(true);
4868
return t;
4969
}
5070

51-
public static void main(String[] args) throws InterruptedException, IOException {
52-
53-
int[] stackSizes = {
54-
1024 * 256, 1024 * 512, 1024 * 1024 * 3
55-
};
71+
public static void main(String[] args) throws Exception {
5672

5773
if (args.length == 1 && args[0].equals("test")) {
5874

5975
ArrayList<Thread> threads = new ArrayList<>();
6076

61-
for (int s: stackSizes) {
62-
threads.add(createTestThread(s));
77+
// Add a bunch of large-stacked threads to make a significant imprint on combined thread stack size
78+
for (int i = 0; i < numThreads; i++) {
79+
threads.add(createTestThread(i));
6380
}
6481

82+
// Start test threads.
6583
threads.forEach(Thread::start);
66-
for (Thread t: threads) {
67-
t.join();
68-
}
84+
85+
gate.await();
86+
87+
// Stop VM. VM will run PrintNMTStatistics before exiting, and the still-running daemon threads
88+
// should show up with fully - or almost fully - committed thread stacks.
6989

7090
} else {
7191

7292
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
7393
"-XX:+UnlockDiagnosticVMOptions",
7494
"-Xmx100M",
75-
"-XX:+AlwaysPreTouchStacks", "-Xlog:os+thread=trace",
95+
"-XX:+AlwaysPreTouchStacks",
7696
"-XX:NativeMemoryTracking=summary", "-XX:+PrintNMTStatistics",
7797
"TestAlwaysPreTouchStacks",
7898
"test");
@@ -81,12 +101,10 @@ public static void main(String[] args) throws InterruptedException, IOException
81101

82102
output.shouldHaveExitValue(0);
83103

84-
for (int s: stackSizes) {
85-
output.shouldContain("Alive: " + Integer.toString(s));
104+
for (int i = 0; i < numThreads; i++) {
105+
output.shouldContain("Alive: " + i);
86106
}
87107

88-
output.shouldContain("Pretouching thread stack");
89-
90108
// We want to see, in the final NMT printout, a committed thread stack size very close to reserved
91109
// stack size. Like this:
92110
// - Thread (reserved=10332400KB, committed=10284360KB)
@@ -108,9 +126,21 @@ public static void main(String[] args) throws InterruptedException, IOException
108126
long reserved = Long.parseLong(m.group(1));
109127
long committed = Long.parseLong(m.group(2));
110128
System.out.println(">>>>> " + line + ": " + reserved + " - " + committed);
111-
if (committed < (reserved / 2)) {
129+
// This is a bit fuzzy: even with PreTouch we don't commit the full range of what NMT counts
130+
// as thread stack. But without pre-touching, the thread stacks would be committed to about 1/5th
131+
// of their reserved size. Requiring them to be committed for over 3/4th shows that pretouch is
132+
// really working.
133+
if ((double)committed < ((double)reserved * 0.75)) {
112134
throw new RuntimeException("Expected a higher ratio between stack committed and reserved.");
113135
}
136+
// Added sanity tests: we expect our test threads to be still alive when NMT prints its final
137+
// report, so their stacks should dominate the NMT-reported total stack size.
138+
long max_reserved = memoryCeilingMB * 3 * MB;
139+
long min_reserved = memoryCeilingMB * MB;
140+
if (reserved >= max_reserved || reserved < min_reserved) {
141+
throw new RuntimeException("Total reserved stack sizes outside of our expectations (" + reserved +
142+
", expected " + min_reserved + ".." + max_reserved + ")");
143+
}
114144
foundLine = true;
115145
break;
116146
}

0 commit comments

Comments
 (0)