Note: static field access fixup as well as trampoline backpatching is
steel not MP safe after this patch. This is something yet to be done.

Apart from that there was a race condition on access to fixup site
lists causing the following segfault to occurre:

[thread: main] SIGSEGV at EIP 080550bd while accessing memory address 00000000.
Registers:
 eax: 00000000   ebx: 08300908   ecx: 00000000   edx: 08300730
 esi: 087c54e8   edi: 087cc3f0   ebp: bfe0e524   esp: bfe0e500
Native and JAVA stack trace:
 [<080550bd>] native     : <unknown>
 [<08062cc5>] native     : jit_magic_trampoline+1c5 (jato/jit/trampoline.c:146)
 [<a7c0aaec>] trampoline : java/lang/System.<clinit>(System.java:74)
 [<0806643f>] native     : vm_class_init+13f (jato/jato/vm/class.c:461)
 [<08062b2d>] native     : <unknown>
 [<a7c0abcc>] trampoline : java/lang/System.currentTimeMillis(System.java:222)
 [<a7c14f1a>] jit        : java/lang/VMThread.sleep(VMThread.java:393)
 [<a7c14e12>] jit        : java/lang/Thread.sleep(Thread.java:896)
 [<a7c14c08>] jit        : java/lang/Thread.sleep(Thread.java:861)
 [<a7c0d992>] jit        : Test.main(Test.java:40)
 [<08069d38>] native     : main+390 (jato/vm/jato.c:962)
 [<b7caa60b>] native     : <unknown>
 [<08052f70>] native     : <unknown>

for the following test case run with -Xtrace:invoke:

public class Test extends Thread {
        public static Object syn;

        public void run() {
                while (true) {
                        synchronized (Test.syn) {
                                try {
                                        Test.syn.wait();
                                } catch (InterruptedException e) {
                                }
                        }
                }
        }

        public static void main(String[] args) {
                Thread t[] = new Thread[1];

                syn = new Object();

                for (int i = 0; i < t.length; i++) {
                        t[i] = new Test();
                }

                for (int i = 0; i < t.length; i++) {
                        t[i].start();
                }

                while (true) {
                        synchronized (Test.syn) {
                                Test.syn.notifyAll();
                        }

                        try {
                                Thread.sleep(500);
                        } catch (InterruptedException e) {
                        }
                }
        }
}

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 arch/x86/emit-code.c |   18 ++++++++++++++++--
 include/vm/class.h   |    3 +++
 vm/class.c           |   31 ++++++++++++++++++++++++++++++-
 vm/static.c          |    4 ++++
 4 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c
index f1b7353..1e57d8a 100644
--- a/arch/x86/emit-code.c
+++ b/arch/x86/emit-code.c
@@ -420,6 +420,8 @@ void fixup_static(struct vm_class *vmc)
 {
        struct static_fixup_site *this, *next;
 
+       pthread_mutex_lock(&vmc->mutex);
+
        list_for_each_entry_safe(this, next,
                &vmc->static_fixup_site_list, vmc_node)
        {
@@ -431,20 +433,28 @@ void fixup_static(struct vm_class *vmc)
                cpu_write_u32(site_addr + 2, (unsigned long) new_target);
 
                list_del(&this->vmc_node);
+
+               pthread_mutex_lock(&this->cu->mutex);
                list_del(&this->cu_node);
+               pthread_mutex_unlock(&this->cu->mutex);
+
                free(this);
        }
+
+       pthread_mutex_unlock(&vmc->mutex);
 }
 
 int fixup_static_at(unsigned long addr)
 {
        struct compilation_unit *cu;
-       struct static_fixup_site *this;
+       struct static_fixup_site *this, *t;
 
        cu = jit_lookup_cu(addr);
        assert(cu);
 
-       list_for_each_entry(this, &cu->static_fixup_site_list, cu_node)
+       pthread_mutex_lock(&cu->mutex);
+
+       list_for_each_entry_safe(this, t, &cu->static_fixup_site_list, cu_node)
        {
                void *site_addr = buffer_ptr(cu->objcode)
                        + this->insn->mach_offset;
@@ -452,6 +462,8 @@ int fixup_static_at(unsigned long addr)
                if ((unsigned long) site_addr == addr) {
                        struct vm_class *vmc = this->vmf->class;
 
+                       pthread_mutex_unlock(&cu->mutex);
+
                        /* Note: After this call, we can no longer access
                         * "this" because it may have been deleted already
                         * (from insite the class initializer of "vmc". */
@@ -464,6 +476,8 @@ int fixup_static_at(unsigned long addr)
                }
        }
 
+       pthread_mutex_unlock(&cu->mutex);
+
        return 0;
 }
 
diff --git a/include/vm/class.h b/include/vm/class.h
index 2ed5ffe..43d364a 100644
--- a/include/vm/class.h
+++ b/include/vm/class.h
@@ -2,6 +2,7 @@
 #define _VM_CLASS_H
 
 #include <assert.h>
+#include <pthread.h>
 
 #include "vm/field.h"
 #include "vm/itable.h"
@@ -34,6 +35,8 @@ struct vm_class {
        enum vm_class_state state;
        char *name;
 
+       pthread_mutex_t mutex;
+
        struct vm_class *super;
        unsigned int nr_interfaces;
        struct vm_class **interfaces;
diff --git a/vm/class.c b/vm/class.c
index a96f1b6..e357946 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -124,11 +124,28 @@ setup_vtable(struct vm_class *vmc)
        }
 }
 
+static int vm_class_link_common(struct vm_class *vmc)
+{
+       int err;
+
+       err = pthread_mutex_init(&vmc->mutex, NULL);
+       if (err)
+               return -err;
+
+       return 0;
+}
+
 int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class)
 {
+       int err;
+
        vmc->class = class;
        vmc->kind = VM_CLASS_KIND_REGULAR;
 
+       err = vm_class_link_common(vmc);
+       if (err)
+               return -err;
+
        const struct cafebabe_constant_info_class *constant_class;
        if (cafebabe_class_constant_get_class(class,
                class->this_class, &constant_class))
@@ -312,11 +329,17 @@ int vm_class_link(struct vm_class *vmc, const struct 
cafebabe_class *class)
        INIT_LIST_HEAD(&vmc->static_fixup_site_list);
 
        vmc->state = VM_CLASS_LINKED;
-       return 0;
+       return 0;;
 }
 
 int vm_class_link_primitive_class(struct vm_class *vmc, const char *class_name)
 {
+       int err;
+
+       err = vm_class_link_common(vmc);
+       if (err)
+               return err;
+
        vmc->name = strdup(class_name);
        if (!vmc->name)
                return -ENOMEM;
@@ -343,6 +366,12 @@ int vm_class_link_primitive_class(struct vm_class *vmc, 
const char *class_name)
 
 int vm_class_link_array_class(struct vm_class *vmc, const char *class_name)
 {
+       int err;
+
+       err = vm_class_link_common(vmc);
+       if (err)
+               return err;
+
        vmc->name = strdup(class_name);
        if (!vmc->name)
                return -ENOMEM;
diff --git a/vm/static.c b/vm/static.c
index c910fe3..69551fb 100644
--- a/vm/static.c
+++ b/vm/static.c
@@ -39,7 +39,11 @@ add_static_fixup_site(enum static_fixup_type type, struct 
insn *insn,
        site->insn = insn;
        site->vmf = vmf;
        site->cu = cu;
+
+       pthread_mutex_lock(&vmc->mutex);
        list_add_tail(&site->vmc_node, &vmc->static_fixup_site_list);
+       pthread_mutex_unlock(&vmc->mutex);
+
        list_add_tail(&site->cu_node, &cu->static_fixup_site_list);
        return 0;
 }
-- 
1.6.0.6


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to