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

Reply via email to