Skip to content

Commit 360cbf0

Browse files
author
Zhengyu Gu
committed
Implementation of Safepoint events
1 parent d2b0513 commit 360cbf0

File tree

5 files changed

+177
-5
lines changed

5 files changed

+177
-5
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public enum JfrEvent {
4949
GCPhasePauseLevel1Event("jdk.GCPhasePauseLevel1"),
5050
GCPhasePauseLevel2Event("jdk.GCPhasePauseLevel2"),
5151
GCPhasePauseLevel3Event("jdk.GCPhasePauseLevel3"),
52-
GCPhasePauseLevel4Event("jdk.GCPhasePauseLevel4");
52+
GCPhasePauseLevel4Event("jdk.GCPhasePauseLevel4"),
53+
SafepointBegin("jdk.SafepointBegin"),
54+
SafepointEnd("jdk.SafepointEnd");
5355

5456
private final long id;
5557

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr.events;
28+
29+
import com.oracle.svm.core.annotate.Uninterruptible;
30+
import com.oracle.svm.core.jfr.JfrEvent;
31+
import com.oracle.svm.core.jfr.HasJfrSupport;
32+
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
33+
import com.oracle.svm.core.jfr.JfrNativeEventWriterData;
34+
import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess;
35+
import com.oracle.svm.core.jfr.JfrTicks;
36+
import com.oracle.svm.core.jfr.SubstrateJVM;
37+
38+
import org.graalvm.nativeimage.StackValue;
39+
import org.graalvm.word.UnsignedWord;
40+
41+
public class SafepointBeginEvent extends TimedEvent {
42+
@Uninterruptible(reason = "Accesses a JFR buffer.")
43+
public static void emit(UnsignedWord safepointId, int numOfThreads, long startTicks) {
44+
if (!HasJfrSupport.get()) {
45+
return;
46+
}
47+
48+
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.SafepointBegin)) {
49+
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
50+
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
51+
52+
JfrNativeEventWriter.beginEventWrite(data, false);
53+
JfrNativeEventWriter.putLong(data, JfrEvent.SafepointBegin.getId());
54+
JfrNativeEventWriter.putLong(data, startTicks);
55+
JfrNativeEventWriter.putLong(data, JfrTicks.elapsedTicks() - startTicks);
56+
JfrNativeEventWriter.putEventThread(data);
57+
JfrNativeEventWriter.putLong(data, safepointId.rawValue());
58+
JfrNativeEventWriter.putInt(data, numOfThreads);
59+
JfrNativeEventWriter.putInt(data, 0); // jniCriticalThreadCount
60+
JfrNativeEventWriter.endEventWrite(data, false);
61+
}
62+
}
63+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr.events;
28+
29+
import com.oracle.svm.core.annotate.Uninterruptible;
30+
import com.oracle.svm.core.jfr.JfrEvent;
31+
import com.oracle.svm.core.jfr.HasJfrSupport;
32+
import com.oracle.svm.core.jfr.JfrNativeEventWriter;
33+
import com.oracle.svm.core.jfr.JfrNativeEventWriterData;
34+
import com.oracle.svm.core.jfr.JfrNativeEventWriterDataAccess;
35+
import com.oracle.svm.core.jfr.JfrTicks;
36+
import com.oracle.svm.core.jfr.SubstrateJVM;
37+
38+
import org.graalvm.nativeimage.StackValue;
39+
import org.graalvm.word.UnsignedWord;
40+
41+
public class SafepointEndEvent extends TimedEvent {
42+
@Uninterruptible(reason = "Accesses a JFR buffer.")
43+
public static void emit(UnsignedWord safepointId, long startTick) {
44+
if (!HasJfrSupport.get()) {
45+
return;
46+
}
47+
48+
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.SafepointEnd)) {
49+
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
50+
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);
51+
52+
JfrNativeEventWriter.beginEventWrite(data, false);
53+
JfrNativeEventWriter.putLong(data, JfrEvent.SafepointEnd.getId());
54+
JfrNativeEventWriter.putLong(data, startTick);
55+
JfrNativeEventWriter.putLong(data, JfrTicks.elapsedTicks() - startTick);
56+
JfrNativeEventWriter.putEventThread(data);
57+
JfrNativeEventWriter.putLong(data, safepointId.rawValue());
58+
JfrNativeEventWriter.endEventWrite(data, false);
59+
}
60+
}
61+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jfr.events;
28+
29+
import com.oracle.svm.core.annotate.Uninterruptible;
30+
import com.oracle.svm.core.jfr.HasJfrSupport;
31+
import com.oracle.svm.core.jfr.JfrTicks;
32+
33+
public class TimedEvent {
34+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
35+
public static long getTicks() {
36+
return HasJfrSupport.get() ? JfrTicks.elapsedTicks() : 0;
37+
}
38+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Safepoint.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,8 @@
5757
import com.oracle.svm.core.graal.nodes.KillMemoryNode;
5858
import com.oracle.svm.core.heap.Heap;
5959
import com.oracle.svm.core.jdk.UninterruptibleUtils;
60+
import com.oracle.svm.core.jfr.events.SafepointBeginEvent;
61+
import com.oracle.svm.core.jfr.events.SafepointEndEvent;
6062
import com.oracle.svm.core.log.Log;
6163
import com.oracle.svm.core.nodes.CFunctionEpilogueNode;
6264
import com.oracle.svm.core.nodes.CFunctionPrologueNode;
@@ -612,6 +614,7 @@ private Master() {
612614
protected boolean freeze(String reason) {
613615
assert SubstrateOptions.MultiThreaded.getValue() : "Should only freeze for a safepoint when multi-threaded.";
614616
assert VMOperationControl.mayExecuteVmOperations();
617+
long startTicks = SafepointBeginEvent.getTicks();
615618

616619
/* the current thread may already own the lock for non-safepoint reasons */
617620
boolean lock = !VMThreads.THREAD_MUTEX.isOwner();
@@ -624,11 +627,12 @@ protected boolean freeze(String reason) {
624627
Statistics.setStartNanos();
625628
ImageSingletons.lookup(Heap.class).prepareForSafepoint();
626629
safepointState = SYNCHRONIZING;
627-
requestSafepoints(reason);
630+
int numOfThreads = requestSafepoints(reason);
628631
waitForSafepoints(reason);
629632
Statistics.setFrozenNanos();
630633
safepointState = AT_SAFEPOINT;
631634
safepointId = safepointId.add(1);
635+
SafepointBeginEvent.emit(getSafepointId(), numOfThreads, startTicks);
632636
return lock;
633637
}
634638

@@ -637,9 +641,10 @@ protected boolean freeze(String reason) {
637641
protected void thaw(String reason, boolean unlock) {
638642
assert SubstrateOptions.MultiThreaded.getValue() : "Should only thaw from a safepoint when multi-threaded.";
639643
assert VMOperationControl.mayExecuteVmOperations();
640-
644+
long startTicks = SafepointEndEvent.getTicks();
641645
safepointState = NOT_AT_SAFEPOINT;
642646
releaseSafepoints(reason);
647+
SafepointEndEvent.emit(getSafepointId(), startTicks);
643648
ImageSingletons.lookup(Heap.class).endSafepoint();
644649
Statistics.setThawedNanos();
645650
requestingThread = WordFactory.nullPointer();
@@ -657,15 +662,17 @@ private static boolean isMyself(IsolateThread thread) {
657662
}
658663

659664
/** Send each of the threads (except myself) a request to come to a safepoint. */
660-
private static void requestSafepoints(String reason) {
665+
private static int requestSafepoints(String reason) {
661666
VMThreads.THREAD_MUTEX.assertIsOwner("Must hold mutex while requesting a safepoint.");
662667
final Log trace = Log.noopLog().string("[Safepoint.Master.requestSafepoints: reason: ").string(reason);
668+
int numOfThreads = 0;
663669

664670
// Walk the threads list and ask each thread (except myself) to come to a safepoint.
665671
for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) {
666672
if (isMyself(vmThread)) {
667673
continue;
668674
}
675+
numOfThreads++;
669676
if (SafepointBehavior.ignoresSafepoints(vmThread)) {
670677
/* If safepoints are disabled, do not ask it to stop at safepoints. */
671678
continue;
@@ -677,6 +684,7 @@ private static void requestSafepoints(String reason) {
677684
trace.string(" with requests: ").signed(Statistics.getRequested());
678685
}
679686
trace.string("]").newline();
687+
return numOfThreads;
680688
}
681689

682690
/**

0 commit comments

Comments
 (0)