Skip to content
Snippets Groups Projects
Commit eb8bc833 authored by Stepan Sindelar's avatar Stepan Sindelar
Browse files

[GR-2798] Synchronization related fixes.

PullRequest: fastr/1196
parents faaa8ab3 00089f9c
No related branches found
No related tags found
No related merge requests found
......@@ -29,10 +29,12 @@ import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceEnabled;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.concurrent.locks.ReentrantLock;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.InteropException;
import com.oracle.truffle.api.interop.Message;
......@@ -43,6 +45,7 @@ import com.oracle.truffle.r.ffi.impl.common.LibPaths;
import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_DLL.NFIHandle;
import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
import com.oracle.truffle.r.runtime.FastROptions;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
......@@ -77,6 +80,9 @@ class UnsafeAdapter {
final class TruffleNFI_Context extends RFFIContext {
@CompilationFinal private static boolean hasAccessLock;
private static ReentrantLock accessLock;
TruffleNFI_Context() {
super(new TruffleNFI_C(), new TruffleNFI_Base(), new TruffleNFI_Call(), new TruffleNFI_DLL(), new TruffleNFI_UserRng(), new TruffleNFI_Zip(), new TruffleNFI_PCRE(), new TruffleNFI_Lapack(),
new TruffleNFI_Stats(), new TruffleNFI_Tools(), new TruffleNFI_REmbed(), new TruffleNFI_Misc());
......@@ -117,9 +123,17 @@ final class TruffleNFI_Context extends RFFIContext {
if (function.getLibrary() == NativeFunction.baseLibrary()) {
dllInfo = TruffleNFI_Context.getInstance().defaultLibrary;
} else if (function.getLibrary() == NativeFunction.anyLibrary()) {
dllInfo = ((NFIHandle) DLL.findLibraryContainingSymbol(function.getCallName()).handle).libHandle;
DLLInfo lib = DLL.findLibraryContainingSymbol(function.getCallName());
if (lib == null) {
throw RInternalError.shouldNotReachHere("Could not find library containing symbol " + function.getCallName());
}
dllInfo = ((NFIHandle) lib.handle).libHandle;
} else {
dllInfo = ((NFIHandle) DLL.findLibrary(function.getLibrary()).handle).libHandle;
DLLInfo lib = DLL.findLibrary(function.getLibrary());
if (lib == null) {
throw RInternalError.shouldNotReachHere("Could not find library " + function.getLibrary());
}
dllInfo = ((NFIHandle) lib.handle).libHandle;
}
try {
TruffleObject symbol = ((TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), dllInfo, function.getCallName()));
......@@ -231,6 +245,7 @@ final class TruffleNFI_Context extends RFFIContext {
@Override
public ContextState initialize(RContext context) {
RFFIUtils.initializeTracing();
initializeLock();
if (traceEnabled()) {
traceDownCall("initialize");
}
......@@ -266,6 +281,13 @@ final class TruffleNFI_Context extends RFFIContext {
}
}
private static synchronized void initializeLock() {
hasAccessLock = FastROptions.SynchronizeNativeCode.getBooleanValue();
if (hasAccessLock && accessLock == null) {
accessLock = new ReentrantLock();
}
}
@Override
public void beforeDispose(RContext context) {
switch (context.getKind()) {
......@@ -302,4 +324,30 @@ final class TruffleNFI_Context extends RFFIContext {
public DLLInfo getRLibDLLInfo() {
return rlibDLLInfo;
}
@Override
public void beforeUpcall(boolean canRunGc) {
super.beforeUpcall(canRunGc);
if (hasAccessLock) {
acquireLock();
}
}
@Override
public void afterUpcall(boolean canRunGc) {
super.afterUpcall(canRunGc);
if (hasAccessLock) {
releaseLock();
}
}
@TruffleBoundary
private void acquireLock() {
accessLock.lock();
}
@TruffleBoundary
private void releaseLock() {
accessLock.unlock();
}
}
......@@ -50,8 +50,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
* Encapsulated the access to the global grid state.
*/
public final class GridContext {
private static final GridContext INSTANCE = new GridContext();
private RInternalCode internalCode;
private final GridState gridState = new GridState();
/**
......@@ -65,7 +63,11 @@ public final class GridContext {
}
public static GridContext getContext() {
return INSTANCE;
RContext rCtx = RContext.getInstance();
if (rCtx.gridContext == null) {
rCtx.gridContext = new GridContext();
}
return (GridContext) rCtx.gridContext;
}
@TruffleBoundary
......
......@@ -24,6 +24,7 @@ import com.oracle.truffle.r.runtime.ROptions.OptionsException;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RPairList;
import com.oracle.truffle.r.runtime.env.REnvironment;
......@@ -65,7 +66,7 @@ public final class RGridGraphicsAdapter {
}
public static void initialize() {
addDevice(NULL_DEVICE);
REnvironment.baseEnv().safePut(DOT_DEVICES, RDataFactory.createPairList(NULL_DEVICE));
setCurrentDevice(NULL_DEVICE);
RContext ctx = RContext.getInstance();
ROptions.ContextStateImpl options = ctx.stateROptions;
......@@ -81,26 +82,41 @@ public final class RGridGraphicsAdapter {
}
/**
* Fixup .Devices array as someone may have set it to something that is not a pair list nor
* RNull, which breaks dev.cur built-in R function and others. GNUR seems to have active binding
* for it. This is such special case that it doesn't seem necessary for now.
* Fixup .Devices global variable to be a pair list of length at least 1. Non-empty lists are
* converted to pair lists, anything else causes the variable to be reset back to the initial
* value.
*/
@TruffleBoundary
public static void fixupDevicesVariable() {
Object devices = REnvironment.baseEnv().get(DOT_DEVICES);
if (devices == RNull.instance || !(devices instanceof RPairList)) {
// reset the .Devices and .Device variables to initial values
REnvironment.baseEnv().safePut(DOT_DEVICES, RNull.instance);
addDevice(NULL_DEVICE);
setCurrentDevice(NULL_DEVICE);
public static RPairList fixupDevicesVariable() {
REnvironment baseEnv = REnvironment.baseEnv();
Object devices = baseEnv.get(DOT_DEVICES);
if (devices instanceof RPairList) {
return (RPairList) devices;
}
if (devices instanceof RList) {
RList list = (RList) devices;
if (list.getLength() > 0) {
RPairList head = RDataFactory.createPairList(list.getDataAt(0));
RPairList curr = head;
for (int i = 1; i < list.getLength(); i++) {
RPairList next = RDataFactory.createPairList(list.getDataAt(i));
curr.setCdr(next);
curr = next;
}
baseEnv.safePut(DOT_DEVICES, head);
return head;
}
}
// reset the .Devices and .Device variables to initial values
RPairList nullDevice = RDataFactory.createPairList(NULL_DEVICE);
baseEnv.safePut(DOT_DEVICES, nullDevice);
setCurrentDevice(NULL_DEVICE);
return nullDevice;
}
public static void removeDevice(int index) {
assert index > 0 : "cannot remove null device";
REnvironment baseEnv = REnvironment.baseEnv();
fixupDevicesVariable();
RPairList devices = (RPairList) baseEnv.get(DOT_DEVICES);
RPairList devices = fixupDevicesVariable();
assert index < devices.getLength() : "wrong index in removeDevice";
RPairList prev = devices;
for (int i = 0; i < index - 1; ++i) {
......@@ -120,12 +136,8 @@ public final class RGridGraphicsAdapter {
public static void addDevice(String name) {
REnvironment baseEnv = REnvironment.baseEnv();
baseEnv.safePut(DOT_DEVICE, name);
Object dotDevices = baseEnv.get(DOT_DEVICES);
if (dotDevices instanceof RPairList) {
((RPairList) dotDevices).appendToEnd(RDataFactory.createPairList(name));
} else {
baseEnv.safePut(DOT_DEVICES, RDataFactory.createPairList(name));
}
RPairList dotDevices = fixupDevicesVariable();
dotDevices.appendToEnd(RDataFactory.createPairList(name));
}
public static String getDefaultDevice() {
......
......@@ -61,6 +61,7 @@ public enum FastROptions {
EmitTmpDir("The directory where to allocate temporary files with deparsed source code.", null, true),
EmitTmpHashed("Use an SHA-256 hash as file name to reduce temporary file creation.", true),
SpawnUsesPolyglot("use PolyglotEngine for .fastr.context.spwan", false),
SynchronizeNativeCode("allow only one thread to enter packages' native code", false),
// Promises optimizations
EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false),
......
......@@ -350,6 +350,10 @@ public final class RContext implements RTruffleObject {
@CompilationFinal private RFFIContext stateRFFI;
// Context specific state required for libraries, the initialization is handled lazily by the
// concrete library.
public Object gridContext = null;
public final WeakHashMap<String, WeakReference<String>> stringMap = new WeakHashMap<>();
public final WeakHashMap<Source, REnvironment> sourceRefEnvironments = new WeakHashMap<>();
public final WeakHashMap<Path, REnvironment> srcfileEnvironments = new WeakHashMap<>();
......
......@@ -654,7 +654,7 @@ public class DLL {
return findSymbolNode.execute((String) args[0], (String) args[1], (RegisteredNativeSymbol) args[2]);
}
private static RFindSymbolRootNode create() {
private static synchronized RFindSymbolRootNode create() {
if (findSymbolRootNode == null) {
findSymbolRootNode = new RFindSymbolRootNode();
Truffle.getRuntime().createCallTarget(findSymbolRootNode);
......
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