Signed-off-by: Tomek Grabiec <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel