From 56a56503d630a64cb7b468c4f5b8b9c15a78c441 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sun, 23 Oct 2005 19:41:09 +0000 Subject: [PATCH] Linux: Don't assume JAWT Lock()/Unlock() are re-entrant, fixing a hang with GCJ 4 --- src/java/org/lwjgl/opengl/LinuxDisplay.java | 51 +++++++++++++++++++-- src/native/linux/org_lwjgl_opengl_Display.c | 9 ++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index a14d6f16..64ea9d14 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -49,16 +49,61 @@ import org.lwjgl.input.Keyboard; final class LinuxDisplay implements DisplayImplementation { private static final int NUM_BUTTONS = 3; + /** Keep track on the current awt lock owner to avoid + * depending on JAWT locking to be re-entrant (This is a + * problem with GCJ). JAWT locking is not that well specified + * anyway so it is probably best to avoid assuming too much + * about it. + */ + private static Thread current_awt_lock_owner; + private static int awt_lock_count; + private static int display_connection_usage_count = 0; private static PeerInfo peer_info; /* Since Xlib is not guaranteed to be thread safe, we need a way to synchronize LWJGL - * Xlib calls with AWT Xlib calls. Fortunately, JAWT implements LockAWT and UnlockAWT() to + * Xlib calls with AWT Xlib calls. Fortunately, JAWT implements Lock()/Unlock() to * do just that. */ - static native void lockAWT(); - static native void unlockAWT(); + static synchronized void lockAWT() { + Thread this_thread = Thread.currentThread(); + while (current_awt_lock_owner != null && current_awt_lock_owner != this_thread) { + try { + LinuxDisplay.class.wait(); + } catch (InterruptedException e) { + LWJGLUtil.log("Interrupted while waiting for awt lock: " + e); + } + } + if (awt_lock_count == 0) { + current_awt_lock_owner = this_thread; + try { + nLockAWT(); + } catch (LWJGLException e) { + LWJGLUtil.log("Caught exception while locking AWT: " + e); + } + } + awt_lock_count++; + } + private static native void nLockAWT() throws LWJGLException; + + static synchronized void unlockAWT() { + if (awt_lock_count <= 0) + throw new IllegalStateException("AWT not locked!"); + if (Thread.currentThread() != current_awt_lock_owner) + throw new IllegalStateException("AWT already locked by " + current_awt_lock_owner); + awt_lock_count--; + if (awt_lock_count == 0) { + try { + nUnlockAWT(); + } catch (LWJGLException e) { + LWJGLUtil.log("Caught exception while unlocking AWT: " + e); + } + current_awt_lock_owner = null; + LinuxDisplay.class.notify(); + } + } + private static native void nUnlockAWT() throws LWJGLException; /** * increment and decrement display usage. diff --git a/src/native/linux/org_lwjgl_opengl_Display.c b/src/native/linux/org_lwjgl_opengl_Display.c index 6e3bfd40..efc99f0d 100644 --- a/src/native/linux/org_lwjgl_opengl_Display.c +++ b/src/native/linux/org_lwjgl_opengl_Display.c @@ -124,7 +124,6 @@ static int errorHandler(Display *disp, XErrorEvent *error) { return 0; } - Display *getDisplay(void) { return display_connection; } @@ -556,21 +555,21 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsActive return focused || isLegacyFullscreen() ? JNI_TRUE : JNI_FALSE; } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_lockAWT(JNIEnv *env, jclass clazz) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nLockAWT(JNIEnv *env, jclass clazz) { JAWT jawt; jawt.version = JAWT_VERSION_1_4; if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) { - throwGeneralException(env, "java/lang/RuntimeException", "GetAWT failed"); + throwException(env, "GetAWT failed"); return; } jawt.Lock(env); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_unlockAWT(JNIEnv *env, jclass clazz) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUnlockAWT(JNIEnv *env, jclass clazz) { JAWT jawt; jawt.version = JAWT_VERSION_1_4; if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) { - throwGeneralException(env, "java/lang/RuntimeException", "GetAWT failed"); + throwException(env, "GetAWT failed"); return; } jawt.Unlock(env);