The instruction selector can deadlock during compilation if method A invokes method B and the same method B also invokes method A. Fix that by using pthread_mutex_trylock() and treating the target method as not compiled of the mutex is under contention.
Fixes the following deadlock found by helgrind: ==5206== Thread #1: lock order "0x4A4C0CC before 0x18A9F5A4" violated ==5206== at 0x40264B7: pthread_mutex_lock (hg_intercepts.c:408) ==5206== by 0x805ED27: mono_burg_emit (insn-selector.c:730) ==5206== by 0x80608F3: emit_code (insn-selector.c:874) ==5206== by 0x8060A57: select_instructions (insn-selector.c:925) ==5206== by 0x80652B6: compile (compiler.c:80) ==5206== by 0x806C4C9: jit_magic_trampoline (trampoline.c:97) ==5206== by 0x890640C: ??? ==5206== by 0x89069A3: ??? ==5206== by 0x4DAE7FF: ??? ==5206== by 0x4DAE7FF: ??? Cc: Tomek Grabiec <tgrab...@gmail.com> Signed-off-by: Pekka Enberg <penb...@cs.helsinki.fi> --- arch/x86/insn-selector.brg | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg index c2d06c3..26bcfd5 100644 --- a/arch/x86/insn-selector.brg +++ b/arch/x86/insn-selector.brg @@ -3170,25 +3170,27 @@ static void invoke(struct basic_block *s, struct tree_node *tree) { struct compilation_unit *cu; struct vm_method *method; + bool is_compiled = false; struct statement *stmt; struct insn *call_insn; int nr_stack_args; - bool is_compiled; void *target; stmt = to_stmt(tree); method = stmt->target_method; cu = method->compilation_unit; - if (cu == s->b_parent) { - /* - * This is recursive invocation so we call the trampoline. - */ - is_compiled = false; - target = vm_method_trampoline_ptr(method); - } else { - pthread_mutex_lock(&cu->mutex); + is_compiled = false; + target = vm_method_trampoline_ptr(method); + /* + * Look out for an ABBA deadlock during compilation if a method + * A invokes method B and the same method B invokes method A as + * well. Therefore, if cu->mutex is under contention, treat the + * target method as not compiled and let trampoline + * backpatching deal with it later. + */ + if (pthread_mutex_trylock(&cu->mutex) == 0) { is_compiled = cu->is_compiled; if (is_compiled) target = vm_method_native_ptr(method); -- 1.5.6.3 ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel