Skip to content
Snippets Groups Projects
Commit 89af22dd authored by stepan's avatar stepan
Browse files

NFI Context can deal with being accessed from multiple threads

There is fast-path implementation that handles single thread case until
another thread appears in which case we transfer to interpreter, invalidate,
and fallback to more generic implementation.
parent 9b10e492
No related branches found
No related tags found
No related merge requests found
......@@ -186,13 +186,14 @@ final class TruffleNFI_Context extends RFFIContext {
}
}
private void initCallbacksAddress() {
@TruffleBoundary
private long initCallbacksAddress() {
// get the address of the native thread local
try {
Node bind = Message.createInvoke(1).createNode();
Node executeNode = Message.createExecute(1).createNode();
TruffleObject getCallbacksAddressFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, DLL.findSymbol("Rinternals_getCallbacksAddress", null).asTruffleObject(), "bind", "(): sint64");
callbacksAddress = (long) ForeignAccess.sendExecute(executeNode, getCallbacksAddressFunction);
return (long) ForeignAccess.sendExecute(executeNode, getCallbacksAddressFunction);
} catch (InteropException ex) {
throw RInternalError.shouldNotReachHere(ex);
}
......@@ -222,22 +223,47 @@ final class TruffleNFI_Context extends RFFIContext {
}
private long callbacks;
@CompilationFinal private boolean singleThreadOnly = true;
@CompilationFinal private long callbacksAddressThread;
@CompilationFinal private long callbacksAddress;
private long lastCallbacksAddressThread;
private long lastCallbacksAddress;
private long pushCallbacks() {
if (callbacksAddress == 0) {
CompilerDirectives.transferToInterpreterAndInvalidate();
initCallbacksAddress();
callbacksAddress = initCallbacksAddress();
callbacksAddressThread = Thread.currentThread().getId();
}
long oldCallbacks = UnsafeAdapter.UNSAFE.getLong(callbacksAddress);
assert callbacks != 0L;
assert callbacksAddress != 0L;
UnsafeAdapter.UNSAFE.putLong(callbacksAddress, callbacks);
if (singleThreadOnly && callbacksAddressThread == Thread.currentThread().getId()) {
// Fast path for contexts used only from a single thread
long oldCallbacks = UnsafeAdapter.UNSAFE.getLong(callbacksAddress);
assert callbacksAddress != 0L;
UnsafeAdapter.UNSAFE.putLong(callbacksAddress, callbacks);
return oldCallbacks;
}
// Slow path: cache the address, but reinitialize it if the thread has changed, without
// transfer to interpreter this time.
boolean reinitialize = singleThreadOnly || lastCallbacksAddressThread != Thread.currentThread().getId();
if (singleThreadOnly) {
CompilerDirectives.transferToInterpreterAndInvalidate();
singleThreadOnly = false;
}
if (reinitialize) {
lastCallbacksAddress = initCallbacksAddress();
lastCallbacksAddressThread = Thread.currentThread().getId();
}
long oldCallbacks = UnsafeAdapter.UNSAFE.getLong(lastCallbacksAddress);
assert lastCallbacksAddress != 0L;
assert lastCallbacksAddressThread == Thread.currentThread().getId();
UnsafeAdapter.UNSAFE.putLong(lastCallbacksAddress, callbacks);
return oldCallbacks;
}
private void popCallbacks(long beforeValue) {
assert UnsafeAdapter.UNSAFE.getLong(callbacksAddress) == callbacks : "invalid nesting of native calling contexts";
assert !singleThreadOnly || UnsafeAdapter.UNSAFE.getLong(callbacksAddress) == callbacks : "invalid nesting of native calling contexts";
assert singleThreadOnly || UnsafeAdapter.UNSAFE.getLong(lastCallbacksAddress) == callbacks : "invalid nesting of native calling contexts";
UnsafeAdapter.UNSAFE.putLong(callbacksAddress, beforeValue);
}
......
......@@ -30,11 +30,4 @@ import com.oracle.truffle.r.runtime.data.RFunction;
public abstract class TruffleRLanguage extends TruffleLanguage<RContext> {
public abstract HashMap<String, RFunction> getBuiltinFunctionCache();
@Override
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
// FastR does not support access to a single context from multiple threads, mainly because
// it has to maintain thread local variables on the native side.
return Thread.currentThread() == thread;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment