diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java index 8ea8d72d97fd793667d4d0ea8831cb275a74c804..a4e26e084cb26a2b33636465fd06b613b18346ba 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,11 +39,13 @@ public class JNI_C implements CRFFI { */ @Override @TruffleBoundary - public synchronized void invoke(NativeCallInfo nativeCallInfo, Object[] args) { - if (traceEnabled()) { - traceDownCall(nativeCallInfo.name, args); + public void invoke(NativeCallInfo nativeCallInfo, Object[] args) { + synchronized (JNI_CRFFINode.class) { + if (traceEnabled()) { + traceDownCall(nativeCallInfo.name, args); + } + c(nativeCallInfo.address.asAddress(), args); } - c(nativeCallInfo.address.asAddress(), args); } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java index ee4a044a1f19a7438b001314ff4bc6c0a47718fc..7aae50716574d0dfd8ea5be6e62a49f5bcdd7fb7 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,9 @@ import com.oracle.truffle.r.runtime.ffi.UpCallsRFFIFactory; * they are passed as an array and the JNI code has to call back to get the args (not very * efficient). * - * The JNI layer is not (currently) MT safe, so all calls are single threaded. + * The JNI layer is not (currently) MT safe, so all calls are single threaded. N.B. Since the calls + * take place from a {@link JNI_CallRFFINode}, and this is duplicated in separate contexts, we must + * synchronize on the class. */ public class JNI_Call implements CallRFFI { @@ -53,14 +55,15 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized Object invokeCall(NativeCallInfo nativeCallInfo, Object[] args) { - long address = nativeCallInfo.address.asAddress(); - Object result = null; - if (traceEnabled()) { - traceDownCall(nativeCallInfo.name, args); - } - try { - switch (args.length) { + public Object invokeCall(NativeCallInfo nativeCallInfo, Object[] args) { + synchronized (JNI_CallRFFINode.class) { + long address = nativeCallInfo.address.asAddress(); + Object result = null; + if (traceEnabled()) { + traceDownCall(nativeCallInfo.name, args); + } + try { + switch (args.length) { // @formatter:off case 0: result = call0(address); break; case 1: result = call1(address, args[0]); break; @@ -75,60 +78,67 @@ public class JNI_Call implements CallRFFI { default: result = call(address, args); break; // @formatter:on - } - return result; - } finally { - if (traceEnabled()) { - traceDownCallReturn(nativeCallInfo.name, result); + } + return result; + } finally { + if (traceEnabled()) { + traceDownCallReturn(nativeCallInfo.name, result); + } } } } @Override @TruffleBoundary - public synchronized void invokeVoidCall(NativeCallInfo nativeCallInfo, Object[] args) { - if (traceEnabled()) { - traceDownCall(nativeCallInfo.name, args); - } - long address = nativeCallInfo.address.asAddress(); - try { - switch (args.length) { - case 0: - callVoid0(address); - break; - case 1: - callVoid1(address, args[0]); - break; - default: - throw RInternalError.shouldNotReachHere(); - } - } finally { + public void invokeVoidCall(NativeCallInfo nativeCallInfo, Object[] args) { + synchronized (JNI_CallRFFINode.class) { if (traceEnabled()) { - traceDownCallReturn(nativeCallInfo.name, null); + traceDownCall(nativeCallInfo.name, args); + } + long address = nativeCallInfo.address.asAddress(); + try { + switch (args.length) { + case 0: + callVoid0(address); + break; + case 1: + callVoid1(address, args[0]); + break; + default: + throw RInternalError.shouldNotReachHere(); + } + } finally { + if (traceEnabled()) { + traceDownCallReturn(nativeCallInfo.name, null); + } } } } @Override - public synchronized void setTempDir(String tempDir) { - if (traceEnabled()) { - traceDownCall("setTempDir", tempDir); - } - RFFIVariables.setTempDir(tempDir); - nativeSetTempDir(tempDir); - if (traceEnabled()) { - traceDownCallReturn("setTempDir", null); + public void setTempDir(String tempDir) { + synchronized (JNI_CallRFFINode.class) { + if (traceEnabled()) { + traceDownCall("setTempDir", tempDir); + } + RFFIVariables.setTempDir(tempDir); + nativeSetTempDir(tempDir); + if (traceEnabled()) { + traceDownCallReturn("setTempDir", null); + } } } @Override - public synchronized void setInteractive(boolean interactive) { - if (traceEnabled()) { - traceDownCall("setInteractive", interactive); - } - nativeSetInteractive(interactive); - if (traceEnabled()) { - traceDownCallReturn("setInteractive", null); + public void setInteractive(boolean interactive) { + synchronized (JNI_CallRFFINode.class) { + if (traceEnabled()) { + traceDownCall("setInteractive", interactive); + } + nativeSetInteractive(interactive); + if (traceEnabled()) { + traceDownCallReturn("setInteractive", null); + } } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java index 181da4cc9d31082accd86f6a2728539eb311a475..bff24d02281e3874c40b0c6648be35a83b339980 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -382,7 +382,7 @@ public class DLL { * R_DEFAULT_PACKAGES do throw RErrors. */ - private static DLLInfo doLoad(String absPath, boolean local, boolean now, boolean addToList) throws DLLException { + private static synchronized DLLInfo doLoad(String absPath, boolean local, boolean now, boolean addToList) throws DLLException { Object handle = RFFIFactory.getRFFI().getDLLRFFI().dlopen(absPath, local, now); if (handle == null) { String dlError = RFFIFactory.getRFFI().getDLLRFFI().dlerror(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java index 3659d2f7e2ec07bd0cd62c0a750fcaa18d1f792c..09e61c5bb0bb1d7d8122caf034cd3d04ee34f047 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,12 @@ package com.oracle.truffle.r.runtime.ffi; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +/** + * Caller should not assume that this interface is implemented in a thread-safe manner. In + * particular, pairs of {@link #dlopen}/{@link #dlerror} and {@link #dlsym}/{@link #dlerror} should + * be atomic in the caller. + * + */ public interface DLLRFFI { /** * Open a DLL.