3232
3333import org .graalvm .nativeimage .ImageSingletons ;
3434import org .graalvm .nativeimage .Platform ;
35- import org .graalvm .nativeimage .Platforms ;
3635import org .graalvm .nativeimage .c .function .CEntryPoint ;
3736import org .graalvm .nativeimage .c .function .CEntryPointLiteral ;
3837import org .graalvm .nativeimage .c .function .CodePointer ;
3938import org .graalvm .nativeimage .hosted .Feature ;
4039import org .graalvm .word .Pointer ;
41- import org .graalvm .word .WordFactory ;
4240
4341import com .oracle .svm .core .IsolateListenerSupport ;
4442import com .oracle .svm .core .IsolateListenerSupportFeature ;
4846import com .oracle .svm .core .c .function .CEntryPointOptions ;
4947import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
5048import com .oracle .svm .core .feature .InternalFeature ;
51- import com .oracle .svm .core .graal .stackvalue .UnsafeStackValue ;
5249import com .oracle .svm .core .heap .RestrictHeapAccess ;
5350import com .oracle .svm .core .jfr .JfrExecutionSamplerSupported ;
5451import com .oracle .svm .core .jfr .JfrFeature ;
5552import com .oracle .svm .core .jfr .sampler .JfrExecutionSampler ;
5653import com .oracle .svm .core .option .HostedOptionKey ;
5754import com .oracle .svm .core .option .SubstrateOptionsParser ;
55+ import com .oracle .svm .core .posix .darwin .DarwinSubstrateSigprofHandler ;
5856import com .oracle .svm .core .posix .headers .Signal ;
59- import com .oracle .svm .core .posix .headers . Time ;
57+ import com .oracle .svm .core .posix .linux . LinuxSubstrateSigprofHandler ;
6058import com .oracle .svm .core .sampler .SubstrateSigprofHandler ;
6159import com .oracle .svm .core .thread .ThreadListenerSupport ;
6260import com .oracle .svm .core .thread .ThreadListenerSupportFeature ;
63- import com .oracle .svm .core .util .TimeUtils ;
6461import com .oracle .svm .core .util .UserError ;
62+ import com .oracle .svm .core .util .VMError ;
6563
6664import jdk .graal .compiler .options .Option ;
6765
68- public final class PosixSubstrateSigprofHandler extends SubstrateSigprofHandler {
66+ /**
67+ * <p>
68+ * This class serves as the core for POSIX-based SIGPROF signal handlers.
69+ * </p>
70+ *
71+ * <p>
72+ * POSIX supports two types of timers: the global timer and per-thread timer. Both timers can
73+ * interrupt threads that are blocked. This may result in situations where the VM operation changes
74+ * unexpectedly while a thread executes signal handler code:
75+ * <ul>
76+ * <li>Thread A requests a safepoint.
77+ * <li>Thread B is blocked because of the safepoint but the VM did not start executing the VM
78+ * operation yet (i.e., there is no VM operation in progress).
79+ * <li>Thread B receives a SIGPROF signal and starts executing the signal handler.
80+ * <li>The VM reaches a safepoint and thread A starts executing the VM operation.
81+ * <li>Thread B continues executing the signal handler while the VM operation is now suddenly in
82+ * progress.
83+ * </ul>
84+ * </p>
85+ */
86+ public abstract class PosixSubstrateSigprofHandler extends SubstrateSigprofHandler {
6987 private static final CEntryPointLiteral <Signal .AdvancedSignalDispatcher > advancedSignalDispatcher = CEntryPointLiteral .create (PosixSubstrateSigprofHandler .class ,
7088 "dispatch" , int .class , Signal .siginfo_t .class , Signal .ucontext_t .class );
7189
72- @ Platforms (Platform .HOSTED_ONLY .class )
73- public PosixSubstrateSigprofHandler () {
74- }
75-
7690 @ SuppressWarnings ("unused" )
7791 @ CEntryPoint (include = CEntryPoint .NotIncludedAutomatically .class , publishAs = CEntryPoint .Publish .NotPublished )
7892 @ CEntryPointOptions (prologue = CEntryPointOptions .NoPrologue .class , epilogue = CEntryPointOptions .NoEpilogue .class )
@@ -87,40 +101,9 @@ private static void dispatch(@SuppressWarnings("unused") int signalNumber, @Supp
87101 }
88102 }
89103
90- private static void registerSigprofSignal (Signal .AdvancedSignalDispatcher dispatcher ) {
91- PosixUtils .installSignalHandler (Signal .SignalEnum .SIGPROF , dispatcher , Signal .SA_RESTART ());
92- }
93-
94- @ Override
95- protected void updateInterval () {
96- updateInterval (TimeUtils .millisToMicros (newIntervalMillis ));
97- }
98-
99- public static void updateInterval (long us ) {
100- Time .itimerval newValue = UnsafeStackValue .get (Time .itimerval .class );
101- newValue .it_value ().set_tv_sec (us / TimeUtils .microsPerSecond );
102- newValue .it_value ().set_tv_usec (us % TimeUtils .microsPerSecond );
103- newValue .it_interval ().set_tv_sec (us / TimeUtils .microsPerSecond );
104- newValue .it_interval ().set_tv_usec (us % TimeUtils .microsPerSecond );
105-
106- int status = Time .NoTransitions .setitimer (Time .TimerTypeEnum .ITIMER_PROF , newValue , WordFactory .nullPointer ());
107- PosixUtils .checkStatusIs0 (status , "setitimer(which, newValue, oldValue): wrong arguments." );
108- }
109-
110104 @ Override
111105 protected void installSignalHandler () {
112- registerSigprofSignal (advancedSignalDispatcher .getFunctionPointer ());
113- updateInterval ();
114- }
115-
116- @ Override
117- protected void uninstallSignalHandler () {
118- /*
119- * Only disable the sampling but do not replace the signal handler with the default one
120- * because a signal might be pending for some thread (the default signal handler would print
121- * "Profiling timer expired" to the output).
122- */
123- updateInterval (0 );
106+ PosixUtils .installSignalHandler (Signal .SignalEnum .SIGPROF , advancedSignalDispatcher .getFunctionPointer (), Signal .SA_RESTART ());
124107 }
125108
126109 static boolean isSignalHandlerBasedExecutionSamplerEnabled () {
@@ -159,12 +142,22 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
159142 @ Override
160143 public void afterRegistration (AfterRegistrationAccess access ) {
161144 if (JfrExecutionSamplerSupported .isSupported () && isSignalHandlerBasedExecutionSamplerEnabled ()) {
162- SubstrateSigprofHandler sampler = new PosixSubstrateSigprofHandler ();
145+ SubstrateSigprofHandler sampler = makeNewSigprofHandler ();
163146 ImageSingletons .add (JfrExecutionSampler .class , sampler );
164147 ImageSingletons .add (SubstrateSigprofHandler .class , sampler );
165148
166149 ThreadListenerSupport .get ().register (sampler );
167150 IsolateListenerSupport .singleton ().register (sampler );
168151 }
169152 }
153+
154+ private static SubstrateSigprofHandler makeNewSigprofHandler () {
155+ if (Platform .includedIn (Platform .LINUX .class )) {
156+ return new LinuxSubstrateSigprofHandler ();
157+ } else if (Platform .includedIn (Platform .DARWIN .class )) {
158+ return new DarwinSubstrateSigprofHandler ();
159+ } else {
160+ throw VMError .shouldNotReachHere ("The JFR-based sampler is not supported on this platform." );
161+ }
162+ }
170163}
0 commit comments