Skip to content

Commit

Permalink
Compute Posix signal data at build-time.
Browse files Browse the repository at this point in the history
  • Loading branch information
christianhaeubl committed Oct 8, 2024
1 parent b2615fb commit 41893e1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
import static com.oracle.svm.core.jdk.Target_jdk_internal_misc_Signal.Constants.ERROR_HANDLER;
import static com.oracle.svm.core.jdk.Target_jdk_internal_misc_Signal.Constants.IGNORE_HANDLER;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.MapCursor;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand Down Expand Up @@ -70,7 +70,6 @@
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.nodes.extended.MembarNode;

/**
* The signal handler mechanism exists only once per process. So, only a single isolate at a time
Expand All @@ -85,7 +84,7 @@ public final class PosixSignalHandlerSupport implements SignalHandlerSupport {
* Note that aliases are allowed in this map, i.e., different signal names may have the same C
* signal number.
*/
private EconomicMap<String, Integer> signalNameToSignalNum;
private Map<String, Integer> signalNameToSignalNum;
private boolean[] supportedSignals;
private DispatcherThread dispatcherThread;
private boolean initialized;
Expand All @@ -99,6 +98,14 @@ public static PosixSignalHandlerSupport singleton() {
return ImageSingletons.lookup(PosixSignalHandlerSupport.class);
}

@Platforms(Platform.HOSTED_ONLY.class)
@SuppressWarnings("hiding")
public void setData(Map<String, Integer> signalNameToSignalNum, boolean[] supportedSignals) {
assert this.signalNameToSignalNum == null && this.supportedSignals == null;
this.signalNameToSignalNum = signalNameToSignalNum;
this.supportedSignals = supportedSignals;
}

/** Returns whether the currently installed signal handler matched the passed dispatcher. */
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
static boolean isCurrentDispatcher(int sig, SignalDispatcher dispatcher) {
Expand All @@ -108,8 +115,6 @@ static boolean isCurrentDispatcher(int sig, SignalDispatcher dispatcher) {
}

public int findSignal0(String signalName) {
initSupportedSignals();

Integer result = signalNameToSignalNum.get(signalName);
if (result != null) {
return result;
Expand Down Expand Up @@ -162,8 +167,6 @@ private void ensureInitialized() throws IllegalArgumentException {
return;
}

initSupportedSignals();

int code = CSunMiscSignal.open();
if (code == 0) {
startDispatcherThread();
Expand All @@ -177,47 +180,6 @@ private void ensureInitialized() throws IllegalArgumentException {
}
}

/** May be executed by multiple threads but each thread will compute the same data. */
private void initSupportedSignals() {
if (signalNameToSignalNum != null && supportedSignals != null) {
return;
}

int maxSigNum = 0;
EconomicMap<String, Integer> map = EconomicMap.create();
for (SignalEnum value : SignalEnum.values()) {
maxSigNum = Math.max(value.getCValue(), maxSigNum);
map.put(getJavaSignalName(value.name()), value.getCValue());
}

if (Platform.includedIn(Platform.LINUX.class)) {
for (Signal.LinuxSignalEnum value : Signal.LinuxSignalEnum.values()) {
maxSigNum = Math.max(value.getCValue(), maxSigNum);
map.put(getJavaSignalName(value.name()), value.getCValue());
}
} else if (Platform.includedIn(Platform.DARWIN.class)) {
for (Signal.DarwinSignalEnum value : Signal.DarwinSignalEnum.values()) {
maxSigNum = Math.max(value.getCValue(), maxSigNum);
map.put(getJavaSignalName(value.name()), value.getCValue());
}
}

boolean[] signals = new boolean[maxSigNum + 1];
MapCursor<String, Integer> cursor = map.getEntries();
while (cursor.advance()) {
signals[cursor.getValue()] = true;
}

MembarNode.memoryBarrier(MembarNode.FenceKind.STORE_STORE);
signalNameToSignalNum = map;
supportedSignals = signals;
}

private static String getJavaSignalName(String name) {
assert name.startsWith("SIG");
return name.substring(3);
}

private void startDispatcherThread() {
dispatcherThread = new DispatcherThread();
dispatcherThread.start();
Expand Down Expand Up @@ -340,10 +302,53 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
return List.of(RuntimeSupportFeature.class);
}

@Override
public void duringSetup(DuringSetupAccess access) {
setSignalData();
}

@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
RuntimeSupport.getRuntimeSupport().addStartupHook(new IgnoreSignalsStartupHook());
}

private static void setSignalData() {
int maxSigNum = 0;
Map<String, Integer> signalNameToSignalNum = new HashMap<>();
for (SignalEnum sig : SignalEnum.values()) {
int sigNum = sig.getCValue();
maxSigNum = Math.max(sigNum, maxSigNum);
signalNameToSignalNum.put(getJavaSignalName(sig.name()), sigNum);
}

if (Platform.includedIn(Platform.LINUX.class)) {
for (Signal.LinuxSignalEnum sig : Signal.LinuxSignalEnum.values()) {
int sigNum = sig.getCValue();
maxSigNum = Math.max(sigNum, maxSigNum);
signalNameToSignalNum.put(getJavaSignalName(sig.name()), sigNum);
}
} else if (Platform.includedIn(Platform.DARWIN.class)) {
for (Signal.DarwinSignalEnum sig : Signal.DarwinSignalEnum.values()) {
int sigNum = sig.getCValue();
maxSigNum = Math.max(sigNum, maxSigNum);
signalNameToSignalNum.put(getJavaSignalName(sig.name()), sigNum);
}
}

boolean[] supportedSignals = new boolean[maxSigNum + 1];
for (var entry : signalNameToSignalNum.entrySet()) {
supportedSignals[entry.getValue()] = true;
}

/* Copy the map data into an unmodifiable map (safer and more compact). */
Map<String, Integer> map = Map.copyOf(signalNameToSignalNum);
PosixSignalHandlerSupport.singleton().setData(map, supportedSignals);
}

private static String getJavaSignalName(String name) {
assert name.startsWith("SIG");
return name.substring(3);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.svm.core.posix.headers;

import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
import static org.graalvm.nativeimage.c.function.CFunction.Transition.NO_TRANSITION;

import org.graalvm.nativeimage.Platform;
Expand All @@ -46,6 +47,8 @@

import com.oracle.svm.core.RegisterDumper;
import com.oracle.svm.core.SubstrateSegfaultHandler;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.posix.PosixUtils;

// Checkstyle: stop
Expand Down Expand Up @@ -234,8 +237,16 @@ public enum SignalEnum {
SIGXCPU,
SIGXFSZ;

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public int getCValue() {
if (SubstrateUtil.HOSTED) {
return CConstant.ValueAccess.get(this, "getCValue0");
}
return getCValue0();
}

@CEnumValue
public native int getCValue();
private native int getCValue0();
}

@Platforms(Platform.LINUX.class)
Expand All @@ -245,8 +256,16 @@ public enum LinuxSignalEnum {
SIGPOLL,
SIGPWR;

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public int getCValue() {
if (SubstrateUtil.HOSTED) {
return CConstant.ValueAccess.get(this, "getCValue0");
}
return getCValue0();
}

@CEnumValue
public native int getCValue();
private native int getCValue0();
}

@Platforms(Platform.DARWIN.class)
Expand All @@ -256,8 +275,16 @@ public enum DarwinSignalEnum {
SIGINFO,
SIGEMT;

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public int getCValue() {
if (SubstrateUtil.HOSTED) {
return CConstant.ValueAccess.get(this, "getCValue0");
}
return getCValue0();
}

@CEnumValue
public native int getCValue();
private native int getCValue0();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
}

@Override
public void duringSetup(DuringSetupAccess access) {
public void beforeAnalysis(BeforeAnalysisAccess access) {
if (ImageSingletons.contains(SignalHandlerSupport.class)) {
SignalHandlerSupport support = SignalHandlerSupport.singleton();
RuntimeSupport.getRuntimeSupport().addTearDownHook(new StopDispatcherThread());
Expand Down

0 comments on commit 41893e1

Please sign in to comment.