Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
481f81c
add JFR event unit tests for thread sleep and monitor enter
roberttoyonaga Sep 9, 2022
d0f03cf
add java monitor wait
roberttoyonaga Sep 12, 2022
98e3ac9
make tests more robust
roberttoyonaga Sep 12, 2022
06a3c9f
add monitor wait interrupt test. checkstyle, format
roberttoyonaga Sep 12, 2022
c7b5486
fix hiding field and exceptions
roberttoyonaga Sep 12, 2022
5bdeff6
remove unused try catch blocks
roberttoyonaga Sep 12, 2022
727adae
use spinlocks for synchronization. Refactor.
roberttoyonaga Oct 7, 2022
ed0f1ff
filter in getEvents and checkstyle
roberttoyonaga Oct 7, 2022
5b37c49
fixes for gate check
roberttoyonaga Oct 7, 2022
4e26325
more fixes for gate
roberttoyonaga Oct 7, 2022
417d9f7
set flag before blocking/waiting
roberttoyonaga Oct 11, 2022
2902c0b
update wait tests
roberttoyonaga Oct 11, 2022
156cee1
Merge branch 'master' of github.com:roberttoyonaga/graal into add-jfr…
roberttoyonaga Oct 11, 2022
8a3d0ee
fix conflicts
roberttoyonaga Oct 11, 2022
4955e21
fix error and checkstyle
roberttoyonaga Oct 11, 2022
cd40dc2
update visibility
roberttoyonaga Oct 11, 2022
656ddfd
rename variable. Have child threads start eachother
roberttoyonaga Oct 12, 2022
a5995e7
Cleanups.
christianhaeubl Oct 14, 2022
ade229e
Merge with master.
christianhaeubl Oct 20, 2022
7e9ea6b
Support JFR mirror events (e.g., thread sleep event on JDK 19).
christianhaeubl Nov 7, 2022
c1d3b00
Various fixes for JFR stack traces.
christianhaeubl Nov 17, 2022
ae84ff8
Further fixes.
christianhaeubl Nov 21, 2022
63ef9c5
Merge with master.
christianhaeubl Nov 21, 2022
738bc19
Minor fix.
christianhaeubl Nov 21, 2022
c3fbeb6
Merge with master.
christianhaeubl Nov 28, 2022
c05529b
Merge with master.
christianhaeubl Nov 29, 2022
ede2bfc
Minor fixes.
christianhaeubl Nov 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@
],
"requiresConcealed" : {
"java.base" : [
"jdk.internal.event",
"jdk.internal.misc",
"jdk.internal.vm.annotation",
"jdk.internal.org.objectweb.asm",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

package com.oracle.svm.core.posix;

import java.util.function.BooleanSupplier;

import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand All @@ -47,7 +49,7 @@
import com.oracle.svm.core.posix.headers.Time;
import com.oracle.svm.core.sampler.SubstrateSigprofHandler;

@AutomaticallyRegisteredImageSingleton(SubstrateSigprofHandler.class)
@AutomaticallyRegisteredImageSingleton(value = SubstrateSigprofHandler.class, onlyWith = LinuxOnly.class)
public class PosixSubstrateSigprofHandler extends SubstrateSigprofHandler {

public static final long INTERVAL_S = 0;
Expand Down Expand Up @@ -134,3 +136,10 @@ protected IsolateThread getThreadLocalKeyValue(UnsignedWord key) {
return (IsolateThread) Pthread.pthread_getspecific((Pthread.pthread_key_t) key);
}
}

class LinuxOnly implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return Platform.includedIn(Platform.LINUX.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.oracle.svm.core.jfr.traceid.JfrTraceIdEpoch;
import com.oracle.svm.core.os.RawFileOperationSupport;
import com.oracle.svm.core.sampler.SamplerBuffersAccess;
import com.oracle.svm.core.sampler.SubstrateSigprofHandler;
import com.oracle.svm.core.thread.JavaVMOperation;
import com.oracle.svm.core.thread.VMOperation;
import com.oracle.svm.core.thread.VMOperationControl;
Expand Down Expand Up @@ -384,8 +385,7 @@ protected void operate() {
*/
@Uninterruptible(reason = "Prevent pollution of the current thread's thread local JFR buffer.")
private void changeEpoch() {
/* Process all unprocessed sampler buffers before changing the epoch. */
SamplerBuffersAccess.processSamplerBuffers();
processSamplerBuffers();

// Write unflushed data from the thread local buffers but do *not* reinitialize them
// The thread local code will handle space reclamation on their own time
Expand Down Expand Up @@ -413,6 +413,24 @@ private void changeEpoch() {
// Now that the epoch changed, re-register all running threads for the new epoch.
SubstrateJVM.getThreadRepo().registerRunningThreads();
}

/**
* The VM is at a safepoint, so all other threads have a native state. However, the SIGPROF
* handler may still be executed at any time for any thread (including the current thread).
* To prevent races, we need to ensure that there are no threads that execute the SIGPROF
* handler while we are accessing the currently active buffers of other threads.
*/
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private void processSamplerBuffers() {
SubstrateSigprofHandler.preventThreadsFromEnteringSigProfHandler();
try {
SubstrateSigprofHandler.waitUntilAllThreadsExitedSignalHandler();
SamplerBuffersAccess.processActiveBuffers();
SamplerBuffersAccess.processFullBuffers();
} finally {
SubstrateSigprofHandler.allowThreadsInSigProfHandler();
}
}
}

public long getChunkStartNanos() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,14 @@
*/
package com.oracle.svm.core.jfr;

import java.util.function.BooleanSupplier;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.jdk.JDK17OrEarlier;
import com.oracle.svm.util.ReflectionUtil;

/**
* The event IDs depend on the metadata.xml and therefore vary between JDK versions.
* This file contains the VM-level events that Native Image supports on all JDK versions. The event
* IDs depend on the JDK version-specific metadata.xml file.
*/
public final class JfrEvent {
public static final JfrEvent ThreadStart = create("jdk.ThreadStart");
Expand All @@ -60,26 +56,15 @@ public final class JfrEvent {
public static final JfrEvent SafepointEnd = create("jdk.SafepointEnd");
public static final JfrEvent ExecuteVMOperation = create("jdk.ExecuteVMOperation");
public static final JfrEvent JavaMonitorEnter = create("jdk.JavaMonitorEnter");
public static final JfrEvent ThreadSleep = create("jdk.ThreadSleep", JDK17OrEarlier.class);
public static final JfrEvent ThreadPark = create("jdk.ThreadPark");
public static final JfrEvent JavaMonitorWait = create("jdk.JavaMonitorWait");

private final long id;
private final String name;

@Platforms(Platform.HOSTED_ONLY.class)
private static JfrEvent create(String name) {
return create(name, TargetClass.AlwaysIncluded.class);
}

@Platforms(Platform.HOSTED_ONLY.class)
private static JfrEvent create(String name, Class<? extends BooleanSupplier> onlyWith) {
BooleanSupplier onlyWithProvider = ReflectionUtil.newInstance(onlyWith);
if (onlyWithProvider.getAsBoolean()) {
return new JfrEvent(name);
} else {
return null;
}
public static JfrEvent create(String name) {
return new JfrEvent(name);
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import com.sun.management.internal.PlatformMBeanProviderImpl;

import jdk.jfr.Configuration;
import jdk.jfr.Event;
import jdk.jfr.internal.JVM;
import jdk.jfr.internal.jfc.JFC;

Expand All @@ -59,9 +58,9 @@
*
* There are two different kinds of JFR events:
* <ul>
* <li>Java-level events are defined by a Java class that extends {@link Event} and that is
* annotated with JFR-specific annotations. Those events are typically triggered by the Java
* application and a Java {@code EventWriter} object is used when writing the event to a
* <li>Java-level events are defined by a Java class that extends {@link jdk.internal.event.Event}
* and that is annotated with JFR-specific annotations. Those events are typically triggered by the
* Java application and a Java {@code EventWriter} object is used when writing the event to a
* buffer.</li>
* <li>Native events are triggered by the JVM itself and are defined in the JFR metadata.xml file.
* For writing such an event to a buffer, we call into {@link JfrNativeEventWriter} and pass a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,31 @@

import java.util.ArrayList;
import java.util.List;
import jdk.jfr.Event;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

/**
* Holds all JFR Java-level event classes.
*/
public class JfrJavaEvents {
private static final List<Class<? extends Event>> EVENT_CLASSES = new ArrayList<>();
private static final List<Class<? extends jdk.internal.event.Event>> EVENT_CLASSES = new ArrayList<>();
private static final List<Class<? extends jdk.jfr.Event>> JFR_EVENT_CLASSES = new ArrayList<>();

@Platforms(Platform.HOSTED_ONLY.class)
public static void registerEventClass(Class<? extends Event> eventClass) {
@SuppressWarnings("unchecked")
public static void registerEventClass(Class<? extends jdk.internal.event.Event> eventClass) {
EVENT_CLASSES.add(eventClass);
if (jdk.jfr.Event.class.isAssignableFrom(eventClass)) {
JFR_EVENT_CLASSES.add((Class<? extends jdk.jfr.Event>) eventClass);
}
}

public static List<Class<? extends Event>> getAllEventClasses() {
public static List<Class<? extends jdk.internal.event.Event>> getAllEventClasses() {
return EVENT_CLASSES;
}

public static List<Class<? extends jdk.jfr.Event>> getJfrEventClasses() {
return JFR_EVENT_CLASSES;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private boolean await() {

private void run0() {
/* Process all unprocessed sampler buffers. */
SamplerBuffersAccess.processSamplerBuffers();
SamplerBuffersAccess.processFullBuffers();
JfrChunkWriter chunkWriter = unlockedChunkWriter.lock();
try {
if (chunkWriter.hasOpenFile()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,27 +106,30 @@ public long getStackTraceId(int skipCount) {

/* Initialize stack walk. */
SamplerSampleWriterData data = StackValue.get(SamplerSampleWriterData.class);
SamplerThreadLocal.setSignalHandlerLocallyDisabled(true);
if (SamplerSampleWriterDataAccess.initialize(data, skipCount, maxDepth)) {
SamplerSampleWriter.begin(data);
/* Walk the stack. */
Pointer sp = KnownIntrinsics.readCallerStackPointer();
CodePointer ip = FrameAccess.singleton().readReturnAddress(sp);
if (JavaStackWalker.walkCurrentThread(sp, ip, SubstrateSigprofHandler.visitor()) || data.getTruncated()) {
acquireLock();
try {
CIntPointer status = StackValue.get(CIntPointer.class);
Pointer start = data.getStartPos().add(SamplerSampleWriter.getHeaderSize());
stackTraceId = getStackTraceId(start, data.getCurrentPos(), data.getHashCode(), status, false);
if (JfrStackTraceTableEntryStatus.get(status, JfrStackTraceTableEntryStatus.NEW)) {
SamplerSampleWriter.end(data);
SamplerThreadLocal.preventSigProfHandlerExecution();
try {
if (SamplerSampleWriterDataAccess.initialize(data, skipCount, maxDepth, true)) {
SamplerSampleWriter.begin(data);
/* Walk the stack. */
Pointer sp = KnownIntrinsics.readCallerStackPointer();
CodePointer ip = FrameAccess.singleton().readReturnAddress(sp);
if (JavaStackWalker.walkCurrentThread(sp, ip, SubstrateSigprofHandler.visitor()) || data.getTruncated()) {
acquireLock();
try {
CIntPointer status = StackValue.get(CIntPointer.class);
Pointer start = data.getStartPos().add(SamplerSampleWriter.getHeaderSize());
stackTraceId = getStackTraceId(start, data.getCurrentPos(), data.getHashCode(), status, false);
if (JfrStackTraceTableEntryStatus.get(status, JfrStackTraceTableEntryStatus.NEW)) {
SamplerSampleWriter.end(data);
}
} finally {
releaseLock();
}
} finally {
releaseLock();
}
}
} finally {
SamplerThreadLocal.allowSigProfHandlerExecution();
}
SamplerThreadLocal.setSignalHandlerLocallyDisabled(false);
return stackTraceId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ public void storeMetadataDescriptor(byte[] bytes) {

/** See {@link JVM#beginRecording}. */
public void beginRecording() {
assert !recording;
if (recording) {
return;
}

JfrChunkWriter chunkWriter = unlockedChunkWriter.lock();
try {
Expand All @@ -309,7 +311,10 @@ public void beginRecording() {

/** See {@link JVM#endRecording}. */
public void endRecording() {
assert recording;
if (!recording) {
return;
}

JfrEndRecordingOperation vmOp = new JfrEndRecordingOperation();
vmOp.enqueue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,18 @@ public boolean isRecording() {

/** See {@link JVM#getAllEventClasses}. */
@Substitute
public List<Class<? extends Event>> getAllEventClasses() {
@TargetElement(onlyWith = JDK17OrLater.class)
public List<Class<? extends jdk.internal.event.Event>> getAllEventClasses() {
return JfrJavaEvents.getAllEventClasses();
}

/** See {@link JVM#getAllEventClasses}. */
@Substitute
@TargetElement(name = "getAllEventClasses", onlyWith = JDK11OrEarlier.class)
public List<Class<? extends Event>> getAllEventClassesJDK11() {
return JfrJavaEvents.getJfrEventClasses();
}

/** See {@link JVM#getUnloadedEventClassCount}. */
@Substitute
public long getUnloadedEventClassCount() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
import com.oracle.svm.core.jfr.JfrTicks;
import com.oracle.svm.core.jfr.SubstrateJVM;

public class ThreadSleepEvent {
public class ThreadSleepEventJDK17 {
private static final JfrEvent ThreadSleep = JfrEvent.create("jdk.ThreadSleep");

public static void emit(long time, long startTicks) {
if (com.oracle.svm.core.jfr.HasJfrSupport.get()) {
Expand All @@ -46,15 +47,15 @@ public static void emit(long time, long startTicks) {

@Uninterruptible(reason = "Accesses a JFR buffer.")
private static void emit0(long time, long startTicks) {
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(JfrEvent.ThreadSleep)) {
if (SubstrateJVM.isRecording() && SubstrateJVM.get().isEnabled(ThreadSleep)) {
JfrNativeEventWriterData data = StackValue.get(JfrNativeEventWriterData.class);
JfrNativeEventWriterDataAccess.initializeThreadLocalNativeBuffer(data);

JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.ThreadSleep);
JfrNativeEventWriter.beginSmallEvent(data, ThreadSleep);
JfrNativeEventWriter.putLong(data, startTicks);
JfrNativeEventWriter.putLong(data, JfrTicks.elapsedTicks() - startTicks);
JfrNativeEventWriter.putEventThread(data);
JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(JfrEvent.ThreadSleep, 0));
JfrNativeEventWriter.putLong(data, SubstrateJVM.get().getStackTraceId(ThreadSleep, 0));
JfrNativeEventWriter.putLong(data, time);
JfrNativeEventWriter.endSmallEvent(data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.nativeimage.impl.UnmanagedMemorySupport;
import org.graalvm.word.Pointer;
Expand All @@ -35,6 +36,7 @@

import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.jfr.SubstrateJVM;
import com.oracle.svm.core.util.UnsignedUtils;

/**
Expand All @@ -57,6 +59,8 @@ public static SamplerBuffer allocate(UnsignedWord dataSize) {
if (result.isNonNull()) {
result.setSize(dataSize);
result.setFreeable(false);
result.setNext(WordFactory.nullPointer());
result.setOwner(0);
reinitialize(result);
}
return result;
Expand All @@ -71,7 +75,6 @@ public static void free(SamplerBuffer buffer) {
public static void reinitialize(SamplerBuffer buffer) {
Pointer dataStart = getDataStart(buffer);
buffer.setPos(dataStart);
buffer.setOwner(0L);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
Expand All @@ -88,4 +91,9 @@ public static boolean isEmpty(SamplerBuffer buffer) {
public static Pointer getDataEnd(SamplerBuffer buffer) {
return getDataStart(buffer).add(buffer.getSize());
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static boolean isOwner(SamplerBuffer buffer, IsolateThread thread) {
return buffer.getOwner() == SubstrateJVM.getThreadId(thread);
}
}
Loading