JRE-202 Deadlock in CGLGraphicsConfig.getCGLConfigInfo

Moved getCGLConfigInfo logic execution to AppKit thread so, awt lock is
 taken on one thread
diff --git a/src/macosx/classes/sun/font/CStrike.java b/src/macosx/classes/sun/font/CStrike.java
index 896b7cc..9968a38 100644
--- a/src/macosx/classes/sun/font/CStrike.java
+++ b/src/macosx/classes/sun/font/CStrike.java
@@ -461,16 +461,8 @@
             // 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
             //    blocked on RenderQueue.lock
             // 1) invokes native block on AppKit and wait
-            //
-            // If dispatch instance is not available, run the code on
-            // disposal thread as before
 
-            final Dispatch dispatch = Dispatch.getInstance();
-
-            if (!CThreading.isAppKit() && dispatch != null)
-                dispatch.getNonBlockingMainQueueExecutor().execute(command);
-            else
-                command.run();
+            CThreading.executeOnAppKit(command);
         }
 
         private static void disposeLongArray(final long[] longArray) {
diff --git a/src/macosx/classes/sun/font/CStrikeDisposer.java b/src/macosx/classes/sun/font/CStrikeDisposer.java
index 855853f..814a363 100644
--- a/src/macosx/classes/sun/font/CStrikeDisposer.java
+++ b/src/macosx/classes/sun/font/CStrikeDisposer.java
@@ -97,16 +97,8 @@
         // 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
         //    blocked on RenderQueue.lock
         // 1) invokes native block on AppKit and wait
-        //
-        // If dispatch instance is not available, run the code on
-        // disposal thread as before
 
-        final Dispatch dispatch = Dispatch.getInstance();
-
-        if (!CThreading.isAppKit() && dispatch != null)
-            dispatch.getNonBlockingMainQueueExecutor().execute(command);
-        else
-            command.run();
+        CThreading.executeOnAppKit(command);
     }
 
     private native void freeNativeScalerContext(long pContext);
diff --git a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java
index e98b4da..4a061dd 100644
--- a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java
+++ b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java
@@ -26,6 +26,7 @@
 package sun.java2d.opengl;
 
 import java.awt.AWTException;
+import java.awt.AWTError;
 import java.awt.BufferCapabilities;
 import java.awt.Component;
 import java.awt.Graphics;
@@ -42,6 +43,7 @@
 import java.awt.image.VolatileImage;
 import java.awt.image.WritableRaster;
 import java.util.HashMap;
+import java.util.concurrent.Callable;
 
 import sun.awt.CGraphicsConfig;
 import sun.awt.CGraphicsDevice;
@@ -62,6 +64,7 @@
 
 import sun.lwawt.LWComponentPeer;
 import sun.lwawt.macosx.CPlatformView;
+import sun.lwawt.macosx.CThreading;
 
 public final class CGLGraphicsConfig extends CGraphicsConfig
     implements OGLGraphicsConfig
@@ -136,40 +139,59 @@
             return null;
         }
 
-        long cfginfo = 0;
-        int textureSize = 0;
-        final String ids[] = new String[1];
-        OGLRenderQueue rq = OGLRenderQueue.getInstance();
-        rq.lock();
-        try {
-            // getCGLConfigInfo() creates and destroys temporary
-            // surfaces/contexts, so we should first invalidate the current
-            // Java-level context and flush the queue...
-            OGLContext.invalidateCurrentContext();
+        // Move CGLGraphicsConfig creation code to AppKit thread in order to avoid the
+        // following deadlock:
+        // 1) CGLGraphicsConfig.getCGLConfigInfo (called from EDT) takes RenderQueue.lock
+        // 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
+        //    blocked on RenderQueue.lock
+        // 1) invokes native block on AppKit and wait
 
-            cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt,
-                                       kOpenGLSwapInterval);
-            if (cfginfo != 0L) {
-                textureSize = nativeGetMaxTextureSize();
-                // 7160609: GL still fails to create a square texture of this
-                // size. Half should be safe enough.
-                // Explicitly not support a texture more than 2^14, see 8010999.
-                textureSize = textureSize <= 16384 ? textureSize / 2 : 8192;
-                OGLContext.setScratchSurface(cfginfo);
-                rq.flushAndInvokeNow(() -> {
-                    ids[0] = OGLContext.getOGLIdString();
-                });
+        Callable<CGLGraphicsConfig> command = new Callable<CGLGraphicsConfig>() {
+            @Override
+            public CGLGraphicsConfig call() throws Exception {
+                long cfginfo = 0;
+                int textureSize = 0;
+                final String ids[] = new String[1];
+                OGLRenderQueue rq = OGLRenderQueue.getInstance();
+                rq.lock();
+                try {
+                    // getCGLConfigInfo() creates and destroys temporary
+                    // surfaces/contexts, so we should first invalidate the current
+                    // Java-level context and flush the queue...
+                    OGLContext.invalidateCurrentContext();
+
+                    cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt,
+                            kOpenGLSwapInterval);
+                    if (cfginfo != 0L) {
+                        textureSize = nativeGetMaxTextureSize();
+                        // 7160609: GL still fails to create a square texture of this
+                        // size. Half should be safe enough.
+                        // Explicitly not support a texture more than 2^14, see 8010999.
+                        textureSize = textureSize <= 16384 ? textureSize / 2 : 8192;
+                        OGLContext.setScratchSurface(cfginfo);
+                        rq.flushAndInvokeNow(() -> {
+                            ids[0] = OGLContext.getOGLIdString();
+                        });
+                    }
+                } finally {
+                    rq.unlock();
+                }
+                if (cfginfo == 0) {
+                    return null;
+                }
+
+                int oglCaps = getOGLCapabilities(cfginfo);
+                ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
+                return new CGLGraphicsConfig(
+                        device, pixfmt, cfginfo, textureSize, caps);
             }
-        } finally {
-            rq.unlock();
-        }
-        if (cfginfo == 0) {
-            return null;
-        }
+        };
 
-        int oglCaps = getOGLCapabilities(cfginfo);
-        ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
-        return new CGLGraphicsConfig(device, pixfmt, cfginfo, textureSize, caps);
+        try {
+            return CThreading.executeOnAppKit(command);
+        } catch (Throwable throwable) {
+            throw new AWTError(throwable.getMessage());
+        }
     }
 
     static void refPConfigInfo(long pConfigInfo) {
diff --git a/src/macosx/classes/sun/lwawt/macosx/CThreading.java b/src/macosx/classes/sun/lwawt/macosx/CThreading.java
index b3fc716..f9df79b 100644
--- a/src/macosx/classes/sun/lwawt/macosx/CThreading.java
+++ b/src/macosx/classes/sun/lwawt/macosx/CThreading.java
@@ -24,17 +24,23 @@
  */
 package sun.lwawt.macosx;
 
+import com.apple.concurrent.Dispatch;
+
 import java.awt.EventQueue;
+import java.awt.AWTError;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
 
 
 public class CThreading {
-    static String APPKIT_THREAD_NAME = "AppKit Thread";
+    static String APPKIT_THREAD_NAME = "AWT-AppKit";
 
     static boolean isEventQueue() {
         return EventQueue.isDispatchThread();
     }
 
-    public static boolean isAppKit() {
+    private static boolean isAppKit() {
         return APPKIT_THREAD_NAME.equals(Thread.currentThread().getName());
     }
 
@@ -61,4 +67,41 @@
         assert isNotAppKitThread : "Threading violation: AppKit thread";
         return isNotAppKitThread;
     }
+
+    public static <V> V executeOnAppKit(Callable<V> command) throws Throwable {
+        if (!isAppKit()) {
+            Dispatch dispatch = Dispatch.getInstance();
+
+            if (dispatch == null) {
+                throw new AWTError("Could not get Dispatch object");
+            }
+
+            FutureTask<V> future = new FutureTask<>(command);
+
+            dispatch.getNonBlockingMainQueueExecutor().execute(future);
+
+            try {
+                return future.get();
+            } catch (InterruptedException e) {
+                throw new AWTError(e.getMessage());
+            } catch (ExecutionException e) {
+                throw e.getCause();
+            }
+        } else
+            return command.call();
+    }
+
+    public static void executeOnAppKit(Runnable command) {
+        if (!isAppKit()) {
+            Dispatch dispatch = Dispatch.getInstance();
+
+            if (dispatch != null) {
+                dispatch.getNonBlockingMainQueueExecutor().execute(command);
+            }
+            else {
+                throw new AWTError("Could not get Dispatch object");
+            }
+        } else
+            command.run();
+    }
 }