Skip to content

Commit d7639de

Browse files
committed
Use the same errno pointer in SVM NFI ErrnoMirror and NFIState
* This will be helpful when SVM supports the NFI Panama backend and allows mixing NFI backends like on JVM.
1 parent 38ae314 commit d7639de

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/Target_com_oracle_truffle_nfi_backend_spi_NFIState.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,52 @@
2525
package com.oracle.svm.truffle.nfi;
2626

2727
import com.oracle.svm.core.annotate.Alias;
28+
import com.oracle.svm.core.annotate.Substitute;
2829
import com.oracle.svm.core.annotate.TargetClass;
30+
import com.oracle.svm.core.heap.VMOperationInfos;
31+
import com.oracle.svm.core.thread.JavaVMOperation;
32+
import com.oracle.svm.core.thread.PlatformThreads;
33+
import com.oracle.truffle.api.CompilerDirectives;
34+
import org.graalvm.nativeimage.IsolateThread;
2935

3036
@TargetClass(className = "com.oracle.truffle.nfi.backend.spi.NFIState", onlyWith = TruffleNFIFeature.IsEnabled.class)
3137
final class Target_com_oracle_truffle_nfi_backend_spi_NFIState {
3238

3339
@Alias boolean hasPendingException;
3440

41+
@Substitute
42+
private static long initNfiErrnoAddress(Thread thread) {
43+
var op = new GetErrnoMirrorAddressOperation(thread);
44+
op.enqueue();
45+
long address = op.result;
46+
if (address == 0) {
47+
throw CompilerDirectives.shouldNotReachHere("Could not find the IsolateThread for " + thread);
48+
}
49+
return address;
50+
}
51+
52+
@Substitute
53+
private void freeNfiErrnoAddress() {
54+
}
55+
56+
private static class GetErrnoMirrorAddressOperation extends JavaVMOperation {
57+
private final Thread thread;
58+
private long result = 0;
59+
60+
GetErrnoMirrorAddressOperation(Thread thread) {
61+
super(VMOperationInfos.get(GetErrnoMirrorAddressOperation.class, "Get ErrnoMirror address", SystemEffect.SAFEPOINT));
62+
this.thread = thread;
63+
}
64+
65+
@Override
66+
protected void operate() {
67+
IsolateThread isolateThread = PlatformThreads.getIsolateThread(thread);
68+
if (isolateThread.isNonNull()) {
69+
this.result = ErrnoMirror.errnoMirror.getAddress(isolateThread).rawValue();
70+
}
71+
}
72+
}
73+
3574
@Alias
3675
native void setPendingException(Throwable t);
3776
}

truffle/src/com.oracle.truffle.nfi.backend.spi/src/com/oracle/truffle/nfi/backend/spi/NFIState.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@
4545
import java.lang.reflect.Field;
4646

4747
/**
48-
* Thread-local state of the NFI that is shared between different backends.
48+
* Thread-local state of the NFI that is shared between different backends. All methods should only
49+
* be called from the corresponding thread to which this state belongs (for thread-safety reasons
50+
* and because the SVM NFI backend relies on it by using a FastThreadLocalBytes for the errno
51+
* pointer, which means the errno pointer points inside the IsolateThread), except the constructor
52+
* and {@link #dispose()} which may be called from another thread, as Truffle hooks which call those
53+
* are not guaranteed to be called from the corresponding thread.
4954
*/
5055
public final class NFIState {
5156

@@ -76,9 +81,8 @@ public final class NFIState {
7681
// for faster query from JNI
7782
boolean hasPendingException;
7883

79-
public NFIState() {
80-
this.nfiErrnoAddress = UNSAFE.allocateMemory(Integer.BYTES);
81-
UNSAFE.putInt(nfiErrnoAddress, 0);
84+
public NFIState(Thread thread) {
85+
this.nfiErrnoAddress = initNfiErrnoAddress(thread);
8286
}
8387

8488
public int getNFIErrno() {
@@ -104,7 +108,17 @@ public void clearPendingException() {
104108
hasPendingException = false;
105109
}
106110

107-
public void dispose() {
111+
private static long initNfiErrnoAddress(@SuppressWarnings("unused") Thread thread) {
112+
long address = UNSAFE.allocateMemory(Integer.BYTES);
113+
UNSAFE.putInt(address, 0);
114+
return address;
115+
}
116+
117+
private void freeNfiErrnoAddress() {
108118
UNSAFE.freeMemory(this.nfiErrnoAddress);
109119
}
120+
121+
public void dispose() {
122+
freeNfiErrnoAddress();
123+
}
110124
}

truffle/src/com.oracle.truffle.nfi/src/com/oracle/truffle/nfi/NFILanguage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public class NFILanguage extends TruffleLanguage<NFIContext> {
6161

6262
private final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("NFI single context");
6363

64-
final ContextThreadLocal<NFIState> nfiState = locals.createContextThreadLocal((ctx, thread) -> new NFIState());
64+
final ContextThreadLocal<NFIState> nfiState = locals.createContextThreadLocal((ctx, thread) -> new NFIState(thread));
6565

6666
protected void setPendingException(Throwable pendingException) {
6767
TruffleStackTrace.fillIn(pendingException);

0 commit comments

Comments
 (0)