Skip to content

Commit

Permalink
8279398: jdk/jfr/api/recording/time/TestTimeMultiple.java failed with…
Browse files Browse the repository at this point in the history
… "RuntimeException: getStopTime() > afterStop"

Backport-of: 40df5df95edb67331d39d829b895094e961fe21f
  • Loading branch information
GoeLin committed Sep 19, 2022
1 parent 3880076 commit 8c5cb31
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 30 deletions.
33 changes: 7 additions & 26 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -269,9 +269,12 @@ synchronized Instant setOutput(String filename) {
if (staleMetadata) {
storeDescriptorInJVM();
}
awaitUniqueTimestamp();
jvm.setOutput(filename);
long nanos = jvm.getChunkStartNanos();
// Each chunk needs a unique start timestamp and
// if the clock resolution is low, two chunks may
// get the same timestamp. Utils.getChunkStartNanos()
// ensures the timestamp is unique for the next chunk
long chunkStart = Utils.getChunkStartNanos();
if (filename != null) {
RepositoryFiles.notifyNewFile();
}
Expand All @@ -282,29 +285,7 @@ synchronized Instant setOutput(String filename) {
}
unregistered = false;
}
return Utils.epochNanosToInstant(nanos);
}

// Each chunk needs a unique start timestamp and
// if the clock resolution is low, two chunks may
// get the same timestamp.
private void awaitUniqueTimestamp() {
if (outputChange == null) {
outputChange = Instant.now();
return;
}
while (true) {
Instant time = Instant.now();
if (!time.equals(outputChange)) {
outputChange = time;
return;
}
try {
Thread.sleep(0, 100);
} catch (InterruptedException iex) {
// ignore
}
}
return Utils.epochNanosToInstant(chunkStart);
}

private void unregisterUnloaded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ synchronized long start(PlatformRecording recording) {
}
currentChunk = newChunk;
jvm.beginRecording();
startNanos = jvm.getChunkStartNanos();
startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos);
if (currentChunk != null) {
currentChunk.setStartTime(startTime);
Expand All @@ -270,7 +270,7 @@ synchronized long start(PlatformRecording recording) {
startTime = MetadataRepository.getInstance().setOutput(p);
newChunk.setStartTime(startTime);
}
startNanos = jvm.getChunkStartNanos();
startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos);
recording.setStartTime(startTime);
recording.setState(RecordingState.RUNNING);
Expand Down Expand Up @@ -317,7 +317,7 @@ synchronized void stop(PlatformRecording recording) {
}
}
OldObjectSample.emit(recording);
recording.setFinalStartnanos(jvm.getChunkStartNanos());
recording.setFinalStartnanos(Utils.getChunkStartNanos());

if (endPhysical) {
RequestEngine.doChunkEnd();
Expand Down
29 changes: 28 additions & 1 deletion src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -96,6 +96,7 @@ public final class Utils {
* The possible data race is benign and is worth of not introducing any contention here.
*/
private static Metrics[] metrics;
private static Instant lastTimestamp;

public static void checkAccessFlightRecorder() throws SecurityException {
@SuppressWarnings("removal")
Expand Down Expand Up @@ -841,4 +842,30 @@ public static Instant epochNanosToInstant(long epochNanos) {
public static long timeToNanos(Instant timestamp) {
return timestamp.getEpochSecond() * 1_000_000_000L + timestamp.getNano();
}

public static long getChunkStartNanos() {
long nanos = JVM.getJVM().getChunkStartNanos();
// JVM::getChunkStartNanos() may return a bumped timestamp, +1 ns or +2 ns.
// Spin here to give Instant.now() a chance to catch up.
awaitUniqueTimestamp();
return nanos;
}

private static void awaitUniqueTimestamp() {
if (lastTimestamp == null) {
lastTimestamp = Instant.now(); // lazy initialization
}
while (true) {
Instant time = Instant.now();
if (!time.equals(lastTimestamp)) {
lastTimestamp = time;
return;
}
try {
Thread.sleep(0, 100);
} catch (InterruptedException iex) {
// ignore
}
}
}
}

1 comment on commit 8c5cb31

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.