Thanks for the replies. I have worked further on this and the particular
issue isn't with GC barriers but with M-to-N threading. In theory if 1
of the M threads becomes blocked in a JNI call then the other threads
should be moved onto another of the N underlying native threads.
Unfortunately, as it's possible to call back into the JVM, the JVM's
yield code can schedule another thread on the same native thread before
realising the 1st thread is blocked and now its possibly handling a
second blocked thread but now on the same native thread. Scheduling
blocked 2 native threads running on the same native thread requires a
rewrite to the underlying native thread library. For the gtk peers this
is done by enabling the portable native sync code, but my experience is
that this is currently broken (and using it is not advised as it would
inhibit the using JVM from being used as a plugin in a gthreaded
application). In any case having a fixed number of N underlying threads
will probably also become a problem. Anyway, I have a small proposed
change to gdk_threads_enter for JVMs with M-to-N threading (in gtkpeer.h):
#define M_TO_N_JAVA_THREADING 1
#if M_TO_N_JAVA_THREADING
#define gdk_threads_enter() \
{ \
JNIEnv *env = cp_gtk_gdk_env(); \
while(g_mutex_trylock(gdk_threads_mutex) == FALSE){ \
jclass thread_class = (*env)->FindClass (env,
"java/lang/Thread"); \
jmethodID thread_yield_mth = (*env)->GetStaticMethodID (env,
thread_class, "yield", "()V"); \
(*env)->CallStaticVoidMethod (env, thread_class,
thread_yield_mth); \
} \
g_mutex_unlock(gdk_threads_mutex); \
gdk_threads_enter(); \
}
#endif
it prevents 2 java threads on the same native thread becoming deadlocked
on the gdk_threads_mutex. Unfortunately the gdk_threads_mutex is
supposed to be private, but I think accessing it here is suitable.
I think removing the portable native sync code and having specific fixes
for M-to-N threading is an appropriate change. What are others opinions?
As part of this would it be possible to have versions of JNI routines
that don't return that at least call Java yield in the case of being on
a M-to-N threaded JVM?
Thanks,
Ian Rogers