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 ¤t_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