changeset 13832:ab370d74a8eb

implemented GC locking for duration of a PTX kernel call
author Doug Simon <doug.simon@oracle.com>
date Thu, 30 Jan 2014 23:52:34 +0100
parents d6823d127f76
children fe99bfb55626
files graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java src/gpu/ptx/vm/gpu_ptx.cpp
diffstat 3 files changed, 25 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java	Thu Jan 30 23:51:55 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ObjectPTXTest.java	Thu Jan 30 23:52:34 2014 +0100
@@ -40,7 +40,6 @@
         double d;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test0() {
         for (long l : new long[]{Long.MIN_VALUE, -10, 0, 1, 2, 10, Long.MAX_VALUE}) {
@@ -54,7 +53,6 @@
         return a.l + l;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test1() {
         for (int i : new int[]{Integer.MIN_VALUE, -10, 0, 1, 2, 10, Integer.MAX_VALUE}) {
@@ -68,7 +66,6 @@
         return a.i + i;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test2() {
         A a = new A();
@@ -82,7 +79,6 @@
         return a.z;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test3() {
         for (byte b : new byte[]{Byte.MIN_VALUE, -10, 0, 1, 2, 10, Byte.MAX_VALUE}) {
@@ -96,7 +92,6 @@
         return a.b + b;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test4() {
         for (short s : new short[]{Short.MIN_VALUE, -10, 0, 1, 2, 10, Short.MAX_VALUE}) {
@@ -110,7 +105,7 @@
         return a.s + s;
     }
 
-    @Ignore("Object parameters not yet GC safe")
+    @Ignore("java.lang.AssertionError: expected:<65531> but was:<809107451>")
     @Test
     public void test5() {
         for (char c : new char[]{Character.MIN_VALUE, 1, 2, 10, Character.MAX_VALUE}) {
@@ -124,7 +119,6 @@
         return a.c + c;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test6() {
         for (float f : new float[]{Float.MIN_VALUE, Float.MIN_NORMAL, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN, -11.45F, -0.0F, 0.0F, 2, 10, Float.MAX_VALUE}) {
@@ -138,7 +132,6 @@
         return a.f + f;
     }
 
-    @Ignore("Object parameters not yet GC safe")
     @Test
     public void test7() {
         for (double d : new double[]{Double.MIN_VALUE, Double.MIN_NORMAL, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY - 11.45D, -0.0D, 0.0D, 2, 10, Double.MAX_VALUE}) {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Thu Jan 30 23:51:55 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Thu Jan 30 23:52:34 2014 +0100
@@ -105,12 +105,12 @@
  * <p>
  * The generated graph includes a reference to the {@link HotSpotNmethod} for the kernel. There must
  * be another reference to the same {@link HotSpotNmethod} object to ensure that the nmethod is not
- * unloaded by the next full GC.
+ * unloaded by the next full GC. Currently, these extra "keep-alive" references are maintained by
+ * {@link PTXHotSpotBackend}.
  * <p>
- * TODO: Only the memory for objects passed as parameters is pinned. Surely the memory for other
- * objects accessed in the kernel reachable from the parameter objects needs to be pinned as well?
- * <p>
- * TODO: Objects references within kernels are currently completely hidden from GC.
+ * The PTX runtime code called by the wrapper blocks GC while the kernel is executing (cf
+ * GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical JNI functions). This ensures objects can
+ * be safely passed to kernels but should be replaced with a lighter weight mechanism at some point.
  */
 public class PTXWrapperBuilder extends GraphKit {
 
--- a/src/gpu/ptx/vm/gpu_ptx.cpp	Thu Jan 30 23:51:55 2014 +0100
+++ b/src/gpu/ptx/vm/gpu_ptx.cpp	Thu Jan 30 23:52:34 2014 +0100
@@ -29,6 +29,7 @@
 #include "utilities/ostream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/gcLocker.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "graal/graalEnv.hpp"
 #include "graal/graalCompiler.hpp"
@@ -404,6 +405,7 @@
   gpu::Ptx::CUdeviceptr  _ret_value;     // pointer to slot in GPU memory holding the return value
   int          _ret_type_size; // size of the return type value
   bool         _ret_is_object; // specifies if the return type is Object
+  bool         _gc_locked;
 
   bool check(int status, const char *action) {
     if (status != GRAAL_CUDA_SUCCESS) {
@@ -425,7 +427,7 @@
   }
 
  public:
-  PtxCall(JavaThread* thread, address buffer, int buffer_size, oop* pinned, int encodedReturnTypeSize) : _thread(thread),
+  PtxCall(JavaThread* thread, address buffer, int buffer_size, oop* pinned, int encodedReturnTypeSize) : _thread(thread), _gc_locked(false),
       _buffer(buffer), _buffer_size(buffer_size), _pinned(pinned), _pinned_length(0), _ret_value(0), _ret_is_object(encodedReturnTypeSize < 0) {
     _ret_type_size = _ret_is_object ? -encodedReturnTypeSize : encodedReturnTypeSize;
   }
@@ -445,6 +447,16 @@
     if (count == 0) {
       return;
     }
+    // Once we start pinning objects, no GC must occur
+    // until the kernel has completed. This is a big
+    // hammer for ensuring we can safely pass objects
+    // to the GPU.
+    GC_locker::lock_critical(_thread);
+    _gc_locked = true;
+    if (TraceGPUInteraction) {
+      tty->print_cr("[CUDA] Locked GC");
+    }
+
     for (int i = 0; i < count; i++) {
       int offset = objectOffsets[i];
       oop* argPtr = (oop*) (_buffer + offset);
@@ -531,6 +543,12 @@
     unpin_objects();
     free_return_value();
     destroy_context();
+    if (_gc_locked) {
+      GC_locker::unlock_critical(_thread);
+      if (TraceGPUInteraction) {
+        tty->print_cr("[CUDA] Unlocked GC");
+      }
+    }
   }
 };
 
@@ -550,10 +568,6 @@
     return 0L;
   }
 
-#if 0
-  Universe::heap()->collect(GCCause::_jvmti_force_gc);
-#endif
-
   PtxCall call(thread, (address) buffer, bufferSize, (oop*) (address) pinnedObjects, encodedReturnTypeSize);
 
 #define TRY(action) do { \