From 21e22101d1efd40ab38d6d6ab98ce92aa5bf502a Mon Sep 17 00:00:00 2001
From: Gary Frost <frost.gary@gmail.com>
Date: Sat, 22 Sep 2012 17:16:51 +0000
Subject: [PATCH] Attempt to fix race condition raised by issue # 68.

---
 .../java/com/amd/aparapi/KernelRunner.java    | 83 ++++++++++---------
 1 file changed, 42 insertions(+), 41 deletions(-)

diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java b/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java
index 62ac74df..7bccfd2b 100644
--- a/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java
@@ -321,7 +321,7 @@ class KernelRunner{
     * @author rlamothe
     */
    @UsedByJNICode public static final int ARG_CHAR = 1 << 21;
-   
+
    /**
     * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>static</code> field (array or primitive).
     * 
@@ -375,7 +375,7 @@ class KernelRunner{
     * 
     * @author gfrost
     */
-  // @UsedByJNICode public static final int JNI_FLAG_ENABLE_PROFILING_CSV = 1 << 1;
+   // @UsedByJNICode public static final int JNI_FLAG_ENABLE_PROFILING_CSV = 1 << 1;
 
    /**
     * This 'bit' indicates that we want to execute on the GPU.
@@ -399,8 +399,8 @@ class KernelRunner{
     * @author gfrost
     */
 
-  // @UsedByJNICode public static final int JNI_FLAG_ENABLE_VERBOSE_JNI = 1 << 3;
-   
+   // @UsedByJNICode public static final int JNI_FLAG_ENABLE_VERBOSE_JNI = 1 << 3;
+
    /**
     * This 'bit' indicates that we wish to enable OpenCL resource tracking by JNI layer to be written to stderr.<br/>
     * 
@@ -410,8 +410,7 @@ class KernelRunner{
     * @author gfrost
     */
 
- //  @UsedByJNICode @Annotations.Experimental public static final int JNI_FLAG_ENABLE_VERBOSE_JNI_OPENCL_RESOURCE_TRACKING = 1 << 4;
-
+   //  @UsedByJNICode @Annotations.Experimental public static final int JNI_FLAG_ENABLE_VERBOSE_JNI_OPENCL_RESOURCE_TRACKING = 1 << 4;
 
    /**
     * Each field (or captured field in the case of an anonymous inner class) referenced by any bytecode reachable from the users Kernel.run(), will
@@ -452,7 +451,6 @@ class KernelRunner{
        */
       @UsedByJNICode public int type;
 
-     
       /**
        * Name of the field
        */
@@ -1332,7 +1330,7 @@ class KernelRunner{
    }
 
    synchronized private Kernel fallBackAndExecute(String _entrypointName, final Range _range, final int _passes) {
-      if(kernel.hasNextExecutionMode()) {
+      if (kernel.hasNextExecutionMode()) {
          kernel.tryNextExecutionMode();
       } else {
          kernel.setFallbackExecutionMode();
@@ -1376,41 +1374,44 @@ class KernelRunner{
                return warnFallBackAndExecute(_entrypointName, _range, _passes, exception);
             }
             if ((entryPoint != null) && !entryPoint.shouldFallback()) {
-
-               if (device != null && !(device instanceof OpenCLDevice)) {
-                  throw new IllegalStateException("range's device is not suitable for OpenCL ");
-               }
-               OpenCLDevice openCLDevice = (OpenCLDevice) device; // still might be null! 
-
-               int jniFlags = 0;
-               if (openCLDevice == null) {
-                  if (kernel.getExecutionMode().equals(EXECUTION_MODE.GPU)) {
-                     // We used to treat as before by getting first GPU device
-                     // now we get the best GPU
-                     openCLDevice = (OpenCLDevice) OpenCLDevice.best();
-                     jniFlags |= JNI_FLAG_USE_GPU; // this flag might be redundant now. 
+               synchronized (Kernel.class) { // This seems to be needed because of a race condition uncovered with issue #68 http://code.google.com/p/aparapi/issues/detail?id=68
+                  if (device != null && !(device instanceof OpenCLDevice)) {
+                     throw new IllegalStateException("range's device is not suitable for OpenCL ");
+                  }
+                  OpenCLDevice openCLDevice = (OpenCLDevice) device; // still might be null! 
+
+                  int jniFlags = 0;
+                  if (openCLDevice == null) {
+                     if (kernel.getExecutionMode().equals(EXECUTION_MODE.GPU)) {
+                        // We used to treat as before by getting first GPU device
+                        // now we get the best GPU
+                        openCLDevice = (OpenCLDevice) OpenCLDevice.best();
+                        jniFlags |= JNI_FLAG_USE_GPU; // this flag might be redundant now. 
+                     } else {
+                        // We fetch the first CPU device 
+                        openCLDevice = (OpenCLDevice) OpenCLDevice.firstCPU();
+                        if (openCLDevice == null) {
+                           return warnFallBackAndExecute(_entrypointName, _range, _passes,
+                                 "CPU request can't be honored not CPU device");
+                        }
+                     }
                   } else {
-                     // We fetch the first CPU device 
-                     openCLDevice = (OpenCLDevice) OpenCLDevice.firstCPU();
-                     if (openCLDevice == null){
-                        return warnFallBackAndExecute(_entrypointName, _range, _passes, "CPU request can't be honored not CPU device");
+                     if (openCLDevice.getType() == Device.TYPE.GPU) {
+                        jniFlags |= JNI_FLAG_USE_GPU; // this flag might be redundant now. 
                      }
                   }
-               } else {
-                  if (openCLDevice.getType() == Device.TYPE.GPU) {
-                     jniFlags |= JNI_FLAG_USE_GPU; // this flag might be redundant now. 
-                  }
-               }
-
-             //  jniFlags |= (Config.enableProfiling ? JNI_FLAG_ENABLE_PROFILING : 0);
-             //  jniFlags |= (Config.enableProfilingCSV ? JNI_FLAG_ENABLE_PROFILING_CSV | JNI_FLAG_ENABLE_PROFILING : 0);
-             //  jniFlags |= (Config.enableVerboseJNI ? JNI_FLAG_ENABLE_VERBOSE_JNI : 0);
-             // jniFlags |= (Config.enableVerboseJNIOpenCLResourceTracking ? JNI_FLAG_ENABLE_VERBOSE_JNI_OPENCL_RESOURCE_TRACKING :0);
-               // jniFlags |= (kernel.getExecutionMode().equals(EXECUTION_MODE.GPU) ? JNI_FLAG_USE_GPU : 0);
-               // Init the device to check capabilities before emitting the
-               // code that requires the capabilities.
 
-               jniContextHandle = initJNI(kernel, openCLDevice, jniFlags); // openCLDevice will not be null here
+                  //  jniFlags |= (Config.enableProfiling ? JNI_FLAG_ENABLE_PROFILING : 0);
+                  //  jniFlags |= (Config.enableProfilingCSV ? JNI_FLAG_ENABLE_PROFILING_CSV | JNI_FLAG_ENABLE_PROFILING : 0);
+                  //  jniFlags |= (Config.enableVerboseJNI ? JNI_FLAG_ENABLE_VERBOSE_JNI : 0);
+                  // jniFlags |= (Config.enableVerboseJNIOpenCLResourceTracking ? JNI_FLAG_ENABLE_VERBOSE_JNI_OPENCL_RESOURCE_TRACKING :0);
+                  // jniFlags |= (kernel.getExecutionMode().equals(EXECUTION_MODE.GPU) ? JNI_FLAG_USE_GPU : 0);
+                  // Init the device to check capabilities before emitting the
+                  // code that requires the capabilities.
+
+                  // synchronized(Kernel.class){
+                  jniContextHandle = initJNI(kernel, openCLDevice, jniFlags); // openCLDevice will not be null here
+               } // end of synchronized! issue 68
                if (jniContextHandle == 0) {
                   return warnFallBackAndExecute(_entrypointName, _range, _passes, "initJNI failed to return a valid handle");
                }
@@ -1472,10 +1473,10 @@ class KernelRunner{
                      args[i] = new KernelArg();
                      args[i].name = field.getName();
                      args[i].field = field;
-                     if ((field.getModifiers() & Modifier.STATIC)== Modifier.STATIC){
+                     if ((field.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
                         args[i].type |= ARG_STATIC;
                      }
-                  
+
                      Class<?> type = field.getType();
                      if (type.isArray()) {
 
-- 
GitLab