Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 Makefile               |    1 +
 include/vm/preload.h   |   20 ++++
 include/vm/thread.h    |   43 +++++++-
 test/arch-x86/Makefile |    1 +
 test/vm/preload-stub.c |   20 ++++
 test/vm/signal-stub.c  |    3 +
 vm/jato.c              |   21 ++++
 vm/preload.c           |   75 ++++++++++++++
 vm/stack-trace.c       |   21 ++++-
 vm/thread.c            |  261 ++++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 459 insertions(+), 7 deletions(-)
 create mode 100644 vm/thread.c

diff --git a/Makefile b/Makefile
index 178983c..8a0fbe9 100644
--- a/Makefile
+++ b/Makefile
@@ -113,6 +113,7 @@ VM_OBJS = \
        vm/stack.o              \
        vm/stack-trace.o        \
        vm/static.o             \
+       vm/thread.o             \
        vm/types.o              \
        vm/utf8.o               \
        vm/zalloc.o             \
diff --git a/include/vm/preload.h b/include/vm/preload.h
index d7f5a52..d2571e0 100644
--- a/include/vm/preload.h
+++ b/include/vm/preload.h
@@ -25,6 +25,10 @@ extern struct vm_class 
*vm_java_lang_ExceptionInInitializerError;
 extern struct vm_class *vm_java_lang_NoSuchFieldError;
 extern struct vm_class *vm_java_lang_NoSuchMethodError;
 extern struct vm_class *vm_java_lang_StackOverflowError;
+extern struct vm_class *vm_java_lang_Thread;
+extern struct vm_class *vm_java_lang_ThreadGroup;
+extern struct vm_class *vm_java_lang_VMThread;
+extern struct vm_class *vm_java_lang_IllegalMonitorStateException;
 extern struct vm_class *vm_boolean_class;
 extern struct vm_class *vm_char_class;
 extern struct vm_class *vm_float_class;
@@ -40,6 +44,15 @@ extern struct vm_field *vm_java_lang_String_count;
 extern struct vm_field *vm_java_lang_String_value;
 extern struct vm_field *vm_java_lang_Throwable_detailMessage;
 extern struct vm_field *vm_java_lang_VMThrowable_vmdata;
+extern struct vm_field *vm_java_lang_Thread_daemon;
+extern struct vm_field *vm_java_lang_Thread_group;
+extern struct vm_field *vm_java_lang_Thread_name;
+extern struct vm_field *vm_java_lang_Thread_priority;
+extern struct vm_field *vm_java_lang_Thread_contextClassLoader;
+extern struct vm_field 
*vm_java_lang_Thread_contextClassLoaderIsSystemClassLoader;
+extern struct vm_field *vm_java_lang_Thread_vmThread;
+extern struct vm_field *vm_java_lang_VMThread_thread;
+extern struct vm_field *vm_java_lang_VMThread_vmdata;
 
 extern struct vm_method *vm_java_util_Properties_setProperty;
 extern struct vm_method *vm_java_lang_Throwable_initCause;
@@ -48,6 +61,13 @@ extern struct vm_method 
*vm_java_lang_Throwable_stackTraceString;
 extern struct vm_method *vm_java_lang_Throwable_getStackTrace;
 extern struct vm_method *vm_java_lang_Throwable_setStackTrace;
 extern struct vm_method *vm_java_lang_StackTraceElement_init;
+extern struct vm_method *vm_java_lang_Thread_init;
+extern struct vm_method *vm_java_lang_Thread_isDaemon;
+extern struct vm_method *vm_java_lang_Thread_getName;
+extern struct vm_method *vm_java_lang_ThreadGroup_init;
+extern struct vm_method *vm_java_lang_ThreadGroup_addThread;
+extern struct vm_method *vm_java_lang_VMThread_init;
+extern struct vm_method *vm_java_lang_VMThread_run;
 
 int preload_vm_classes(void);
 
diff --git a/include/vm/thread.h b/include/vm/thread.h
index 73b04f9..407934e 100644
--- a/include/vm/thread.h
+++ b/include/vm/thread.h
@@ -1,20 +1,53 @@
 #ifndef __VM_THREAD_H
 #define __VM_THREAD_H
 
+#include "lib/list.h"
+
 #include <stdio.h> /* for NOT_IMPLEMENTED */
+#include <pthread.h>
 
 struct vm_object;
 
+enum vm_thread_state {
+       VM_THREAD_STATE_BLOCKED,
+       VM_THREAD_STATE_NEW,
+       VM_THREAD_STATE_RUNNABLE,
+       VM_THREAD_STATE_TERMINATED,
+       VM_THREAD_STATE_TIMED_WAITING,
+       VM_THREAD_STATE_WAITING,
+};
+
 struct vm_thread {
-       struct vm_object *exception;
+       pthread_mutex_t mutex;
+
+       /* instance of java.lang.VMThread associated with current thread */
+       struct vm_object *vmthread;
+
+       pthread_t posix_id;
+       enum vm_thread_state state;
+       struct list_head list_node;
 };
 
-static inline struct vm_thread *vm_current_thread(void)
+struct vm_exec_env {
+       struct vm_thread *thread;
+};
+
+extern __thread struct vm_exec_env current_exec_env;
+
+static inline struct vm_exec_env *vm_get_exec_env(void)
 {
-       static struct vm_thread tmp;
+       return &current_exec_env;
+}
 
-       NOT_IMPLEMENTED;
-       return &tmp;
+static inline struct vm_thread *vm_thread_self(void)
+{
+       return vm_get_exec_env()->thread;
 }
 
+int init_threading(void);
+int vm_thread_start(struct vm_object *vmthread);
+void vm_thread_wait_for_non_daemons(void);
+void vm_thread_set_state(struct vm_thread *thread, enum vm_thread_state state);
+struct vm_object *vm_thread_get_java_thread(struct vm_thread *thread);
+
 #endif
diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile
index a8f741a..078685d 100644
--- a/test/arch-x86/Makefile
+++ b/test/arch-x86/Makefile
@@ -66,6 +66,7 @@ TOPLEVEL_OBJS := \
        vm/stack.o \
        vm/stack-trace.o \
        vm/static.o \
+       vm/thread.o \
        vm/types.o \
        vm/utf8.o \
        vm/zalloc.o \
diff --git a/test/vm/preload-stub.c b/test/vm/preload-stub.c
index 7d871c1..387fd33 100644
--- a/test/vm/preload-stub.c
+++ b/test/vm/preload-stub.c
@@ -12,6 +12,15 @@ struct vm_field *vm_java_lang_String_count;
 struct vm_field *vm_java_lang_String_value;
 struct vm_field *vm_java_lang_Throwable_detailMessage;
 struct vm_field *vm_java_lang_VMThrowable_vmdata;
+struct vm_field *vm_java_lang_Thread_daemon;
+struct vm_field *vm_java_lang_Thread_group;
+struct vm_field *vm_java_lang_Thread_name;
+struct vm_field *vm_java_lang_Thread_priority;
+struct vm_field *vm_java_lang_Thread_contextClassLoader;
+struct vm_field *vm_java_lang_Thread_contextClassLoaderIsSystemClassLoader;
+struct vm_field *vm_java_lang_Thread_vmThread;
+struct vm_field *vm_java_lang_VMThread_thread;
+struct vm_field *vm_java_lang_VMThread_vmdata;
 
 struct vm_class *vm_java_lang_Throwable;
 struct vm_class *vm_java_lang_VMThrowable;
@@ -31,6 +40,10 @@ struct vm_class *vm_java_lang_ClassCastException;
 struct vm_class *vm_java_lang_NoSuchFieldError;
 struct vm_class *vm_java_lang_NoSuchMethodError;
 struct vm_class *vm_java_lang_StackOverflowError;
+struct vm_class *vm_java_lang_Thread;
+struct vm_class *vm_java_lang_ThreadGroup;
+struct vm_class *vm_java_lang_VMThread;
+struct vm_class *vm_java_lang_IllegalMonitorStateException;
 
 struct vm_method *vm_java_lang_Throwable_initCause;
 struct vm_method *vm_java_lang_Throwable_getCause;
@@ -38,3 +51,10 @@ struct vm_method *vm_java_lang_Throwable_stackTraceString;
 struct vm_method *vm_java_lang_Throwable_getStackTrace;
 struct vm_method *vm_java_lang_Throwable_setStackTrace;
 struct vm_method *vm_java_lang_StackTraceElement_init;
+struct vm_method *vm_java_lang_Thread_init;
+struct vm_method *vm_java_lang_Thread_isDaemon;
+struct vm_method *vm_java_lang_Thread_getName;
+struct vm_method *vm_java_lang_ThreadGroup_init;
+struct vm_method *vm_java_lang_ThreadGroup_addThread;
+struct vm_method *vm_java_lang_VMThread_init;
+struct vm_method *vm_java_lang_VMThread_run;
diff --git a/test/vm/signal-stub.c b/test/vm/signal-stub.c
index c73bfc3..f2cd736 100644
--- a/test/vm/signal-stub.c
+++ b/test/vm/signal-stub.c
@@ -1,2 +1,5 @@
 #include "vm/signal.h"
 
+void setup_signal_handlers(void)
+{
+}
diff --git a/vm/jato.c b/vm/jato.c
index 4912243..e2d7c66 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -53,6 +53,7 @@
 
 #include "lib/list.h"
 
+#include "vm/call.h"
 #include "vm/class.h"
 #include "vm/classloader.h"
 #include "vm/fault-inject.h"
@@ -67,6 +68,7 @@
 #include "vm/stack-trace.h"
 #include "vm/static.h"
 #include "vm/system.h"
+#include "vm/thread.h"
 #include "vm/vm.h"
 
 static bool perf_enabled;
@@ -533,6 +535,17 @@ native_vm_throw_null_pointer_exception(void)
        throw_from_native(0);
 }
 
+static struct vm_object *native_vmthread_current_thread(void)
+{
+       return field_get_object(vm_get_exec_env()->thread->vmthread,
+                               vm_java_lang_VMThread_thread);
+}
+
+static void native_vmthread_start(struct vm_object *vmthread, jlong stacksize)
+{
+       vm_thread_start(vmthread);
+}
+
 static struct vm_native natives[] = {
        DEFINE_NATIVE("gnu/classpath/VMStackWalker", "getClassContext", 
&native_vmstackwalker_getclasscontext),
        DEFINE_NATIVE("gnu/classpath/VMSystemProperties", "preInit", 
&native_vmsystemproperties_preinit),
@@ -553,6 +566,8 @@ static struct vm_native natives[] = {
        DEFINE_NATIVE("java/lang/VMRuntime", "runFinalizationForExit", 
&native_vmruntime_run_finalization_for_exit),
        DEFINE_NATIVE("java/lang/VMSystem", "arraycopy", 
&native_vmsystem_arraycopy),
        DEFINE_NATIVE("java/lang/VMSystem", "identityHashCode", 
&native_vmsystem_identityhashcode),
+       DEFINE_NATIVE("java/lang/VMThread", "currentThread", 
&native_vmthread_current_thread),
+       DEFINE_NATIVE("java/lang/VMThread", "start", &native_vmthread_start),
        DEFINE_NATIVE("java/lang/VMThrowable", "fillInStackTrace", 
&native_vmthrowable_fill_in_stack_trace),
        DEFINE_NATIVE("java/lang/VMThrowable", "getStackTrace", 
&native_vmthrowable_get_stack_trace),
        DEFINE_NATIVE("jato/internal/VM", "enableFault", 
&native_vm_enable_fault),
@@ -864,6 +879,10 @@ main(int argc, char *argv[])
        }
 
        init_stack_trace_printing();
+       if (init_threading()) {
+               fprintf(stderr, "could not initialize threading\n");
+               goto out_check_exception;
+       }
 
        struct vm_class *vmc = classloader_load(classname);
        if (!vmc) {
@@ -899,6 +918,8 @@ out_check_exception:
                goto out;
        }
        status = EXIT_SUCCESS;
+
+       vm_thread_wait_for_non_daemons();
 out:
        return status;
 }
diff --git a/vm/preload.c b/vm/preload.c
index b168310..de2922d 100644
--- a/vm/preload.c
+++ b/vm/preload.c
@@ -61,6 +61,10 @@ struct vm_class *vm_java_lang_ExceptionInInitializerError;
 struct vm_class *vm_java_lang_NoSuchFieldError;
 struct vm_class *vm_java_lang_NoSuchMethodError;
 struct vm_class *vm_java_lang_StackOverflowError;
+struct vm_class *vm_java_lang_Thread;
+struct vm_class *vm_java_lang_ThreadGroup;
+struct vm_class *vm_java_lang_VMThread;
+struct vm_class *vm_java_lang_IllegalMonitorStateException;
 struct vm_class *vm_boolean_class;
 struct vm_class *vm_char_class;
 struct vm_class *vm_float_class;
@@ -95,6 +99,10 @@ static const struct preload_entry preload_entries[] = {
        { "java/lang/NoSuchFieldError", &vm_java_lang_NoSuchFieldError },
        { "java/lang/NoSuchMethodError", &vm_java_lang_NoSuchMethodError },
        { "java/lang/StackOverflowError", &vm_java_lang_StackOverflowError },
+       { "java/lang/Thread", &vm_java_lang_Thread },
+       { "java/lang/ThreadGroup", &vm_java_lang_ThreadGroup },
+       { "java/lang/VMThread", &vm_java_lang_VMThread },
+       { "java/lang/IllegalMonitorStateException", 
&vm_java_lang_IllegalMonitorStateException },
 };
 
 static const struct preload_entry primitive_preload_entries[] = {
@@ -121,6 +129,15 @@ struct vm_field *vm_java_lang_String_count;
 struct vm_field *vm_java_lang_String_value;
 struct vm_field *vm_java_lang_Throwable_detailMessage;
 struct vm_field *vm_java_lang_VMThrowable_vmdata;
+struct vm_field *vm_java_lang_Thread_daemon;
+struct vm_field *vm_java_lang_Thread_group;
+struct vm_field *vm_java_lang_Thread_name;
+struct vm_field *vm_java_lang_Thread_priority;
+struct vm_field *vm_java_lang_Thread_contextClassLoader;
+struct vm_field *vm_java_lang_Thread_contextClassLoaderIsSystemClassLoader;
+struct vm_field *vm_java_lang_Thread_vmThread;
+struct vm_field *vm_java_lang_VMThread_thread;
+struct vm_field *vm_java_lang_VMThread_vmdata;
 
 static const struct field_preload_entry field_preload_entries[] = {
        { &vm_java_lang_Class, "vmdata", "Ljava/lang/Object;", 
&vm_java_lang_Class_vmdata },
@@ -129,6 +146,15 @@ static const struct field_preload_entry 
field_preload_entries[] = {
        { &vm_java_lang_String, "value", "[C",  &vm_java_lang_String_value },
        { &vm_java_lang_Throwable, "detailMessage", "Ljava/lang/String;", 
&vm_java_lang_Throwable_detailMessage },
        { &vm_java_lang_VMThrowable, "vmdata", "Ljava/lang/Object;", 
&vm_java_lang_VMThrowable_vmdata },
+       { &vm_java_lang_Thread, "daemon", "Z", &vm_java_lang_Thread_daemon },
+       { &vm_java_lang_Thread, "group", "Ljava/lang/ThreadGroup;", 
&vm_java_lang_Thread_group },
+       { &vm_java_lang_Thread, "name", "Ljava/lang/String;", 
&vm_java_lang_Thread_name },
+       { &vm_java_lang_Thread, "priority", "I", &vm_java_lang_Thread_priority 
},
+       { &vm_java_lang_Thread, "contextClassLoader", 
"Ljava/lang/ClassLoader;", &vm_java_lang_Thread_contextClassLoader },
+       { &vm_java_lang_Thread, "contextClassLoaderIsSystemClassLoader", "Z", 
&vm_java_lang_Thread_contextClassLoaderIsSystemClassLoader },
+       { &vm_java_lang_Thread, "vmThread", "Ljava/lang/VMThread;", 
&vm_java_lang_Thread_vmThread },
+       { &vm_java_lang_VMThread, "thread", "Ljava/lang/Thread;", 
&vm_java_lang_VMThread_thread },
+       { &vm_java_lang_VMThread, "vmdata", "Ljava/lang/Object;", 
&vm_java_lang_VMThread_vmdata },
 };
 
 struct method_preload_entry {
@@ -145,6 +171,13 @@ struct vm_method *vm_java_lang_Throwable_stackTraceString;
 struct vm_method *vm_java_lang_Throwable_getStackTrace;
 struct vm_method *vm_java_lang_Throwable_setStackTrace;
 struct vm_method *vm_java_lang_StackTraceElement_init;
+struct vm_method *vm_java_lang_Thread_init;
+struct vm_method *vm_java_lang_Thread_isDaemon;
+struct vm_method *vm_java_lang_Thread_getName;
+struct vm_method *vm_java_lang_ThreadGroup_init;
+struct vm_method *vm_java_lang_ThreadGroup_addThread;
+struct vm_method *vm_java_lang_VMThread_init;
+struct vm_method *vm_java_lang_VMThread_run;
 
 static const struct method_preload_entry method_preload_entries[] = {
        {
@@ -189,6 +222,48 @@ static const struct method_preload_entry 
method_preload_entries[] = {
                "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V",
                &vm_java_lang_StackTraceElement_init,
        },
+       {
+               &vm_java_lang_Thread,
+               "<init>",
+               
"(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;Ljava/lang/String;)V",
+               &vm_java_lang_Thread_init,
+       },
+       {
+               &vm_java_lang_Thread,
+               "isDaemon",
+               "()Z",
+               &vm_java_lang_Thread_isDaemon,
+       },
+       {
+               &vm_java_lang_Thread,
+               "getName",
+               "()Ljava/lang/String;",
+               &vm_java_lang_Thread_getName,
+       },
+       {
+               &vm_java_lang_ThreadGroup,
+               "<init>",
+               "()V",
+               &vm_java_lang_ThreadGroup_init,
+       },
+       {
+               &vm_java_lang_ThreadGroup,
+               "addThread",
+               "(Ljava/lang/Thread;)V",
+               &vm_java_lang_ThreadGroup_addThread,
+       },
+       {
+               &vm_java_lang_VMThread,
+               "<init>",
+               "(Ljava/lang/Thread;)V",
+               &vm_java_lang_VMThread_init,
+       },
+       {
+               &vm_java_lang_VMThread,
+               "run",
+               "()V",
+               &vm_java_lang_VMThread_run,
+       },
 };
 
 int preload_vm_classes(void)
diff --git a/vm/stack-trace.c b/vm/stack-trace.c
index 5964839..95a8bf6 100644
--- a/vm/stack-trace.c
+++ b/vm/stack-trace.c
@@ -37,6 +37,7 @@
 #include "vm/preload.h"
 #include "vm/stack-trace.h"
 #include "vm/system.h"
+#include "vm/thread.h"
 
 #include "jit/bc-offset-mapping.h"
 #include "jit/cu-mapping.h"
@@ -632,8 +633,24 @@ void vm_print_exception(struct vm_object *exception)
        old_exception = exception_occurred();
        clear_exception();
 
-       /* TODO: print correct thread name */
-       str_append(str, "Exception in thread \"main\" ");
+       struct vm_thread *self = vm_thread_self();
+       if (self) {
+               struct vm_object *jthread = vm_thread_get_java_thread(self);
+               struct vm_object *name;
+
+               name = vm_call_method_object(vm_java_lang_Thread_getName,
+                                            jthread);
+               char *name_s = vm_string_to_cstr(name);
+               if (!name_s)
+                       goto error;
+
+               str_append(str, "Exception in thread \"");
+               str_append(str, name_s);
+               str_append(str, "\" ");
+
+               free(name_s);
+       } else
+               str_append(str, "Exception in thread \"main\" ");
 
        string = vm_call_method_object(vm_java_lang_Throwable_stackTraceString, 
exception);
        if (exception_occurred())
diff --git a/vm/thread.c b/vm/thread.c
new file mode 100644
index 0000000..d10a801
--- /dev/null
+++ b/vm/thread.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2009 Tomasz Grabiec
+ *
+ * This file is released under the GPL version 2 with the following
+ * clarification and special exception:
+ *
+ *     Linking this library statically or dynamically with other modules is
+ *     making a combined work based on this library. Thus, the terms and
+ *     conditions of the GNU General Public License cover the whole
+ *     combination.
+ *
+ *     As a special exception, the copyright holders of this library give you
+ *     permission to link this library with independent modules to produce an
+ *     executable, regardless of the license terms of these independent
+ *     modules, and to copy and distribute the resulting executable under terms
+ *     of your choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module. An
+ *     independent module is a module which is not derived from or based on
+ *     this library. If you modify this library, you may extend this exception
+ *     to your version of the library, but you are not obligated to do so. If
+ *     you do not wish to do so, delete this exception statement from your
+ *     version.
+ *
+ * Please refer to the file LICENSE for details.
+ */
+
+#include "vm/call.h"
+#include "vm/class.h"
+#include "vm/die.h"
+#include "vm/object.h"
+#include "vm/preload.h"
+#include "vm/signal.h"
+#include "vm/stdlib.h"
+#include "vm/thread.h"
+
+#include "jit/exception.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+__thread struct vm_exec_env current_exec_env;
+
+static struct vm_object *main_thread_group;
+
+/* This mutex protects global operations on thread structures. */
+static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Condition variable used for waiting on any thread's death. */
+static pthread_cond_t thread_terminate_cond = PTHREAD_COND_INITIALIZER;
+
+static int nr_non_daemons;
+
+static struct list_head thread_list;
+
+#define thread_for_each(this) list_for_each_entry(this, &thread_list, 
list_node)
+
+static void vm_thread_free(struct vm_thread *thread)
+{
+       free(thread);
+}
+
+static struct vm_thread *vm_thread_alloc(void)
+{
+       struct vm_thread *thread = malloc(sizeof(struct vm_thread));
+       if (!thread)
+               return NULL;
+
+       if (pthread_mutex_init(&thread->mutex, NULL)) {
+               warn("pthread_mutex_init() failed");
+               vm_thread_free(thread);
+               return NULL;
+       }
+
+       thread->state = VM_THREAD_STATE_NEW;
+       thread->vmthread = NULL;
+       thread->posix_id = -1;
+
+       return thread;
+}
+
+/**
+ * Returns instance of java.lang.Thread associated with given thread.
+ */
+struct vm_object *vm_thread_get_java_thread(struct vm_thread *thread)
+{
+       struct vm_object *result;
+
+       pthread_mutex_lock(&thread->mutex);
+       result = field_get_object(thread->vmthread,
+                                 vm_java_lang_VMThread_thread);
+       pthread_mutex_unlock(&thread->mutex);
+
+       return result;
+}
+
+static bool vm_thread_is_daemon(struct vm_thread *thread)
+{
+       struct vm_object *jthread;
+
+       jthread = vm_thread_get_java_thread(thread);
+       return field_get_int32(jthread, vm_java_lang_Thread_daemon) != 0;
+}
+
+void vm_thread_set_state(struct vm_thread *thread, enum vm_thread_state state)
+{
+       pthread_mutex_lock(&thread->mutex);
+       thread->state = state;
+       pthread_mutex_unlock(&thread->mutex);
+}
+
+static void vm_thread_attach_thread(struct vm_thread *thread)
+{
+       pthread_mutex_lock(&threads_mutex);
+       list_add(&thread->list_node, &thread_list);
+       pthread_mutex_unlock(&threads_mutex);
+}
+
+static void vm_thread_detach_thread(struct vm_thread *thread)
+{
+       vm_thread_set_state(thread, VM_THREAD_STATE_TERMINATED);
+
+       pthread_mutex_lock(&threads_mutex);
+
+       list_del(&thread->list_node);
+
+       if (!vm_thread_is_daemon(thread))
+               nr_non_daemons--;
+
+       pthread_cond_broadcast(&thread_terminate_cond);
+       pthread_mutex_unlock(&threads_mutex);
+}
+
+int init_threading(void) {
+       INIT_LIST_HEAD(&thread_list);
+       nr_non_daemons = 0;
+
+       main_thread_group = vm_object_alloc(vm_java_lang_ThreadGroup);
+       if (!main_thread_group)
+               return -ENOMEM;
+
+       vm_call_method(vm_java_lang_ThreadGroup_init, main_thread_group);
+       if (exception_occurred())
+               return -1;
+
+       /*
+        * Initialize the main thread
+        */
+       struct vm_object *thread = vm_object_alloc(vm_java_lang_Thread);
+       if (!thread)
+               return -ENOMEM;
+
+       struct vm_object *thread_name = vm_object_alloc_string_from_c("main");
+       if (!thread_name)
+               return -ENOMEM;
+
+       struct vm_object *vmthread = vm_object_alloc(vm_java_lang_VMThread);
+       if (!vmthread)
+               return -ENOMEM;
+
+       struct vm_thread *main_thread = vm_thread_alloc();
+       if (!main_thread)
+               return -ENOMEM;
+
+       main_thread->state = VM_THREAD_STATE_RUNNABLE;
+       main_thread->vmthread = vmthread;
+       main_thread->posix_id = pthread_self();
+
+       vm_get_exec_env()->thread = main_thread;
+
+       field_set_int32(thread, vm_java_lang_Thread_priority, 5);
+       field_set_int32(thread, vm_java_lang_Thread_daemon, 0);
+       field_set_object(thread, vm_java_lang_Thread_name, thread_name);
+       field_set_object(thread, vm_java_lang_Thread_group, main_thread_group);
+       field_set_object(thread, vm_java_lang_Thread_vmThread, vmthread);
+
+       field_set_object(thread,
+               vm_java_lang_Thread_contextClassLoader, NULL);
+       field_set_int32(thread,
+               vm_java_lang_Thread_contextClassLoaderIsSystemClassLoader, 1);
+
+       field_set_object(vmthread,
+               vm_java_lang_VMThread_thread, thread);
+
+       vm_call_method(vm_java_lang_ThreadGroup_addThread, main_thread_group,
+                      thread);
+       if (exception_occurred())
+               return -1;
+
+       vm_thread_attach_thread(main_thread);
+
+       return 0;
+}
+
+/**
+ * This is the entry point for all java threads.
+ */
+static void *vm_thread_entry(void *arg)
+{
+       struct vm_thread *thread = arg;
+
+       vm_get_exec_env()->thread = thread;
+
+       setup_signal_handlers();
+       thread_init_exceptions();
+
+       vm_call_method(vm_java_lang_VMThread_run, thread->vmthread);
+
+       if (exception_occurred())
+               vm_print_exception(exception_occurred());
+
+       vm_thread_detach_thread(vm_thread_self());
+
+       return NULL;
+}
+
+/**
+ * Creates new native thread representing a java thread.
+ */
+int vm_thread_start(struct vm_object *vmthread)
+{
+       struct vm_thread *thread = vm_thread_alloc();
+       if (!thread) {
+               NOT_IMPLEMENTED;
+               return -1;
+       }
+
+       /* XXX: no need to lock because @thread is not yet visible to
+        * other threads. */
+       thread->vmthread = vmthread;
+       thread->state = VM_THREAD_STATE_RUNNABLE;
+
+       field_set_object(vmthread, vm_java_lang_VMThread_vmdata,
+                        (struct vm_object *) thread);
+
+       if (!vm_thread_is_daemon(thread)) {
+               pthread_mutex_lock(&threads_mutex);
+               nr_non_daemons++;
+               pthread_mutex_unlock(&threads_mutex);
+       }
+
+       vm_thread_attach_thread(thread);
+
+       if (pthread_create(&thread->posix_id, NULL, &vm_thread_entry, thread))
+       {
+               vm_thread_detach_thread(thread);
+               return -1;
+       }
+
+       return 0;
+}
+
+void vm_thread_wait_for_non_daemons(void)
+{
+       pthread_mutex_lock(&threads_mutex);
+
+       while (nr_non_daemons)
+               pthread_cond_wait(&thread_terminate_cond, &threads_mutex);
+
+       pthread_mutex_unlock(&threads_mutex);
+}
-- 
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