* src/toolbox/logging.h: Updated copyright.
[cacao.git] / src / threads / thread.c
index 1552eff4f6f11498e015714bc1aa004f216d6109..c857e007d6ff3ab6db089db4c76c790e5d6f9443 100644 (file)
 
 #include "mm/memory.h"
 
+#if defined(ENABLE_GC_BOEHM)
+/* We need to include Boehm's gc.h here for GC_register_my_thread and
+   friends. */
+# include "mm/boehm-gc/include/gc.h"
+#endif
+
 #include "native/jni.h"
 #include "native/llni.h"
 #include "native/native.h"
 # include "native/include/java_lang_ThreadGroup.h"
 #endif
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 # include "native/include/java_lang_VMThread.h"
 #endif
 
-#include "threads/critical.h"
 #include "threads/lock-common.h"
 #include "threads/threadlist.h"
 #include "threads/thread.h"
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
 
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
 
 #include "vmcore/class.h"
+#include "vmcore/globals.hpp"
 #include "vmcore/method.h"
 #include "vmcore/options.h"
 
 
 /* global variables ***********************************************************/
 
-methodinfo *thread_method_init;
-
-#if defined(ENABLE_JAVASE)
-static java_lang_ThreadGroup *threadgroup_system;
-static java_lang_ThreadGroup *threadgroup_main;
-#endif
+static methodinfo    *thread_method_init;
+static java_handle_t *threadgroup_system;
+static java_handle_t *threadgroup_main;
 
 #if defined(__LINUX__)
 /* XXX Remove for exact-GC. */
@@ -89,8 +92,9 @@ bool threads_pthreads_implementation_nptl;
 
 /* static functions ***********************************************************/
 
-static void thread_create_initial_threadgroups(void);
-static void thread_create_initial_thread(void);
+static void          thread_create_initial_threadgroups(void);
+static void          thread_create_initial_thread(void);
+static threadobject *thread_new(void);
 
 
 /* threads_preinit *************************************************************
@@ -146,9 +150,15 @@ void threads_preinit(void)
 
        threads_impl_preinit();
 
-       /* create internal thread data-structure for the main thread */
+       /* Create internal thread data-structure for the main thread. */
+
+       mainthread = thread_new();
 
-       mainthread = threads_thread_new();
+       /* The main thread should always have index 1. */
+
+       if (mainthread->index != 1)
+               vm_abort("threads_preinit: main thread index not 1: %d != 1",
+                                mainthread->index);
 
        /* thread is a Java thread and running */
 
@@ -177,7 +187,7 @@ void threads_init(void)
 
        /* Cache the java.lang.Thread initialization method. */
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
        thread_method_init =
                class_resolveclassmethod(class_java_lang_Thread,
@@ -186,7 +196,7 @@ void threads_init(void)
                                                                 class_java_lang_Thread,
                                                                 true);
 
-#elif defined(WITH_CLASSPATH_SUN)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
        thread_method_init =
                class_resolveclassmethod(class_java_lang_Thread,
@@ -195,7 +205,7 @@ void threads_init(void)
                                                                 class_java_lang_Thread,
                                                                 true);
 
-#elif defined(WITH_CLASSPATH_CLDC1_1)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
 
        thread_method_init =
                class_resolveclassmethod(class_java_lang_Thread,
@@ -217,11 +227,132 @@ void threads_init(void)
 
 /* thread_create_object ********************************************************
 
+   Create a Java thread object for the given thread data-structure,
+   initializes it and adds the thread to the threadgroup.
+
+   ARGUMENTS:
+
+       t ....... thread
+       name .... thread name
+       group ... threadgroup
+
+   RETURN:
+
 *******************************************************************************/
 
-static void thread_create_object(void)
+static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
 {
-#warning refactor thread_create_initial_thread and threads_attach_current_thread, maybe threads_thread_start_internal
+       java_handle_t    *o;
+       java_lang_Thread *to;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       java_lang_VMThread    *vmto;
+       classinfo             *c;
+       methodinfo            *m;
+       bool                   isdaemon;
+#endif
+
+       /* Create a java.lang.Thread Java object. */
+
+       o = builtin_new(class_java_lang_Thread);
+
+       if (o == NULL)
+               return false;
+
+       to = (java_lang_Thread *) o;
+
+       /* Set the Java object in the thread data-structure.  This
+          indicates that the thread is attached to the VM. */
+
+       thread_set_object(t, (java_handle_t *) to);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       /* Create a java.lang.VMThread Java object. */
+
+       vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+
+       if (vmto == NULL)
+               return false;
+
+       /* Set the Java thread object in the Java VM-thread object. */
+
+       LLNI_field_set_ref(vmto, thread, to);
+
+       /* Set the thread data-structure in the Java VM-thread object. */
+
+       LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
+
+       /* Call:
+          java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+
+       isdaemon = thread_is_daemon(t);
+
+       (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
+                                                 isdaemon);
+
+       if (exceptions_get_exception())
+               return false;
+
+       /* Set the threadgroup in the Java thread object. */
+
+       LLNI_field_set_ref(to, group, (java_lang_ThreadGroup *) group);
+
+       /* Add thread to the threadgroup. */
+
+       LLNI_class_get(group, c);
+
+       m = class_resolveclassmethod(c,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
+
+       if (m == NULL)
+               return false;
+
+       (void) vm_call_method(m, group, to);
+
+       if (exceptions_get_exception())
+               return false;
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       /* OpenJDK's java.lang.Thread does not have a VMThread field in
+          the class.  Nothing to do here. */
+
+       /* Set the priority.  java.lang.Thread.<init> requires it because
+          it sets the priority of the current thread to the parent's one
+          (which is the current thread in this case). */
+
+       LLNI_field_set_val(to, priority, NORM_PRIORITY);
+
+       /* Call:
+          java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
+
+       (void) vm_call_method(thread_method_init, o, group, name);
+
+       if (exceptions_get_exception())
+               return false;
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+       /* Set the thread data-structure in the Java thread object. */
+
+       LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
+
+       /* Call: public Thread(Ljava/lang/String;)V */
+
+       (void) vm_call_method(thread_method_init, o, name);
+
+       if (exceptions_get_exception())
+               return false;
+
+#else
+# error unknown classpath configuration
+#endif
+
+       return true;
 }
 
 
@@ -244,12 +375,11 @@ static void thread_create_object(void)
 static void thread_create_initial_threadgroups(void)
 {
 #if defined(ENABLE_JAVASE)
-# if defined(WITH_CLASSPATH_GNU)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
        /* Allocate and initialize the main thread group. */
 
-       threadgroup_main = (java_lang_ThreadGroup *)
-               native_new_and_init(class_java_lang_ThreadGroup);
+       threadgroup_main = native_new_and_init(class_java_lang_ThreadGroup);
 
        if (threadgroup_main == NULL)
                vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
@@ -258,24 +388,21 @@ static void thread_create_initial_threadgroups(void)
 
        threadgroup_system = threadgroup_main;
 
-# elif defined(WITH_CLASSPATH_SUN)
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
        java_handle_t *name;
        methodinfo    *m;
-       java_handle_t *o;
 
        /* Allocate and initialize the system thread group. */
 
-       threadgroup_system = (java_lang_ThreadGroup *)
-               native_new_and_init(class_java_lang_ThreadGroup);
+       threadgroup_system = native_new_and_init(class_java_lang_ThreadGroup);
 
        if (threadgroup_system == NULL)
                vm_abort("thread_create_initial_threadgroups: failed to allocate system threadgroup");
 
        /* Allocate and initialize the main thread group. */
 
-       threadgroup_main =
-               (java_lang_ThreadGroup *) builtin_new(class_java_lang_ThreadGroup);
+       threadgroup_main = builtin_new(class_java_lang_ThreadGroup);
 
        if (threadgroup_main == NULL)
                vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
@@ -291,9 +418,7 @@ static void thread_create_initial_threadgroups(void)
        if (m == NULL)
                vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
 
-       o = (java_handle_t *) threadgroup_main;
-
-       (void) vm_call_method(m, o, threadgroup_system, name);
+       (void) vm_call_method(m, threadgroup_main, threadgroup_system, name);
 
        if (exceptions_get_exception())
                vm_abort("thread_create_initial_threadgroups: exception while initializing main threadgroup");
@@ -313,31 +438,17 @@ static void thread_create_initial_threadgroups(void)
 
 static void thread_create_initial_thread(void)
 {
-       threadobject       *mainthread;
-       java_handle_t      *name;
-       java_lang_Thread   *to;                        /* java.lang.Thread object */
-       java_handle_t      *o;
-
-#if defined(WITH_CLASSPATH_GNU)
-       java_lang_VMThread *vmto;                    /* java.lang.VMThread object */
-       methodinfo         *m;
-#endif
+       threadobject  *t;
+       java_handle_t *name;
 
        /* Get the main-thread (NOTE: The main thread is always the first
           thread in the list). */
 
-       mainthread = threadlist_first();
-
-       /* Create a java.lang.Thread object for the main thread. */
+       t = threadlist_first();
 
-       to = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
-
-       if (to == NULL)
-               vm_abort("threads_init: failed to allocate java.lang.Thread object");
-
-       /* set the object in the internal data structure */
+       /* The thread name. */
 
-       threads_thread_set_object(mainthread, (java_handle_t *) to);
+       name = javastring_new(utf_main);
 
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
@@ -348,107 +459,30 @@ static void thread_create_initial_thread(void)
        }
 #endif
 
-       name = javastring_new(utf_main);
-
-#if defined(WITH_CLASSPATH_GNU)
-       /* Create a java.lang.VMThread for the main thread. */
-
-       vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
-
-       if (vmto == NULL)
-               vm_abort("threads_init: failed to allocate java.lang.VMThread object");
-
-       /* Set the thread. */
-
-       LLNI_field_set_ref(vmto, thread, to);
-       LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) mainthread);
-
-       /* Set the thread group. */
-
-       LLNI_field_set_ref(to, group, threadgroup_main);
-
-       /* Call:
-          java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
-
-       o = (java_handle_t *) to;
-
-       (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
-                                                 false);
-
-       if (exceptions_get_exception())
-               vm_abort("threads_init: exception while initializing main thread");
-
-       /* Add main thread to main threadgroup. */
-
-       m = class_resolveclassmethod(class_java_lang_ThreadGroup,
-                                                                utf_addThread,
-                                                                utf_java_lang_Thread__V,
-                                                                class_java_lang_ThreadGroup,
-                                                                true);
-
-       o = (java_handle_t *) threadgroup_main;
-
-       (void) vm_call_method(m, o, to);
-
-       if (exceptions_get_exception())
-        vm_abort("threads_init: exception while adding main thread to main threadgroup");
-
-#elif defined(WITH_CLASSPATH_SUN)
-
-       /* Set the priority.  java.lang.Thread.<init> requires it because
-          it sets the priority of the current thread to the parent's one
-          (which is the current thread in this case). */
-
-       LLNI_field_set_val(to, priority, NORM_PRIORITY);
-
-       /* Call:
-          java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
-
-       o = (java_object_t *) to;
-
-       (void) vm_call_method(thread_method_init, o, threadgroup_main, name);
-
-       if (exceptions_get_exception())
-               vm_abort("threads_init: exception while initializing main thread");
-
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-
-       /* Set the thread. */
-
-       LLNI_field_set_val(to, vm_thread, (java_lang_Object *) mainthread);
-
-       /* Call public Thread(String name). */
-
-       o = (java_handle_t *) to;
-
-       (void) vm_call_method(thread_method_init, o, name);
-
-       if (exceptions_get_exception())
-               vm_abort("threads_init: exception while initializing main thread");
+       /* Create the Java thread object. */
 
-#else
-# error unknown classpath configuration
-#endif
+       if (!thread_create_object(t, name, threadgroup_main))
+               vm_abort("thread_create_initial_thread: failed to create Java object");
 
        /* Initialize the implementation specific bits. */
 
        threads_impl_init();
 
-       DEBUGTHREADS("starting (main)", mainthread);
+       DEBUGTHREADS("starting (main)", t);
 }
 
 
-/* threads_thread_new **********************************************************
+/* thread_new ******************************************************************
 
    Allocates and initializes an internal thread data-structure and
    adds it to the threads list.
 
 *******************************************************************************/
 
-threadobject *threads_thread_new(void)
+static threadobject *thread_new(void)
 {
-       int32_t         index;
-       threadobject   *t;
+       int32_t       index;
+       threadobject *t;
        
        /* Lock the thread lists */
 
@@ -529,18 +563,18 @@ threadobject *threads_thread_new(void)
 }
 
 
-/* threads_thread_free *********************************************************
+/* thread_free *****************************************************************
 
    Remove the thread from the threads-list and free the internal
    thread data structure.  The thread index is added to the
    thread-index free-list.
 
    IN:
-       t....thread data structure
+       t ... thread data structure
 
 *******************************************************************************/
 
-void threads_thread_free(threadobject *t)
+void thread_free(threadobject *t)
 {
        /* Lock the thread lists. */
 
@@ -556,7 +590,7 @@ void threads_thread_free(threadobject *t)
 
        /* Set the reference to the Java object to NULL. */
 
-       threads_thread_set_object(t, NULL);
+       thread_set_object(t, NULL);
 
        /* Add the thread data structure to the free list. */
 
@@ -581,11 +615,7 @@ void threads_thread_free(threadobject *t)
 
 bool threads_thread_start_internal(utf *name, functionptr f)
 {
-       threadobject       *t;
-       java_lang_Thread   *to;                        /* java.lang.Thread object */
-#if defined(WITH_CLASSPATH_GNU)
-       java_lang_VMThread *vmto;                    /* java.lang.VMThread object */
-#endif
+       threadobject *t;
 
        /* Enter the join-mutex, so if the main-thread is currently
           waiting to join all threads, the number of non-daemon threads
@@ -593,9 +623,9 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
        threads_mutex_join_lock();
 
-       /* create internal thread data-structure */
+       /* Create internal thread data-structure. */
 
-       t = threads_thread_new();
+       t = thread_new();
 
        t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
 
@@ -606,62 +636,9 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
        /* Create the Java thread object. */
 
-       to = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
-
-       /* XXX memory leak!!! */
-       if (to == NULL)
-               return false;
-
-#if defined(WITH_CLASSPATH_GNU)
-
-       vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
-
-       /* XXX memory leak!!! */
-       if (vmto == NULL)
+       if (!thread_create_object(t, javastring_new(name), threadgroup_system))
                return false;
 
-       LLNI_field_set_ref(vmto, thread, to);
-       LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
-
-       LLNI_field_set_ref(to, vmThread, vmto);
-
-#elif defined(WITH_CLASSPATH_SUN)
-
-       /* Nothing to do. */
-
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-
-       LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
-
-#else
-# error unknown classpath configuration
-#endif
-
-       threads_thread_set_object(t, (java_handle_t *) to);
-
-       /* Set java.lang.Thread fields. */
-
-#if defined(WITH_CLASSPATH_GNU)
-
-       LLNI_field_set_ref(to, name,     (java_lang_String *) javastring_new(name));
-
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
-
-       /* FIXME: In cldc the name is a char[] */
-/*     LLNI_field_set_ref(to, name,     (java_chararray *) name); */
-       LLNI_field_set_ref(to, name,     NULL);
-
-#else
-# error unknow classpath configuration
-#endif
-
-       LLNI_field_set_val(to, priority, NORM_PRIORITY);
-
-#if defined(ENABLE_JAVASE)
-       LLNI_field_set_val(to, daemon,   true);
-       LLNI_field_set_ref(to, group,    threadgroup_system);
-#endif
-
        /* Start the thread. */
 
        threads_impl_thread_start(t, f);
@@ -686,7 +663,7 @@ void threads_thread_start(java_handle_t *object)
 {
        java_lang_Thread   *to;
        threadobject       *t;
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
        java_lang_VMThread *vmto;
 #endif
 
@@ -698,9 +675,9 @@ void threads_thread_start(java_handle_t *object)
 
        threads_mutex_join_lock();
 
-       /* create internal thread data-structure */
+       /* Create internal thread data-structure. */
 
-       t = threads_thread_new();
+       t = thread_new();
 
        /* this is a normal Java thread */
 
@@ -720,9 +697,9 @@ void threads_thread_start(java_handle_t *object)
 
        /* Link the two objects together. */
 
-       threads_thread_set_object(t, object);
+       thread_set_object(t, object);
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
        /* Get the java.lang.VMThread object and do some sanity checks. */
 
@@ -733,11 +710,11 @@ void threads_thread_start(java_handle_t *object)
 
        LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
 
-#elif defined(WITH_CLASSPATH_SUN)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
        /* Nothing to do. */
 
-#elif defined(WITH_CLASSPATH_CLDC1_1)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
 
        LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
 
@@ -752,30 +729,22 @@ void threads_thread_start(java_handle_t *object)
 }
 
 
-/* threads_attach_current_thread ***********************************************
-
-   Attaches the current thread to the VM.  Used in JNI.
-
-*******************************************************************************/
-
-bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+/**
+ * Attaches the current thread to the VM.
+ *
+ * @param vm_aargs Attach arguments.
+ * @param isdaemon true if the attached thread should be a daemon
+ *                 thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 {
-       bool                   result;
-       threadobject          *t;
-       utf                   *u;
-       java_handle_t         *s;
-       java_handle_t         *o;
-       java_lang_Thread      *to;
-
-#if defined(ENABLE_JAVASE)
-       java_lang_ThreadGroup *group;
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
-       java_lang_VMThread    *vmt;
-       classinfo             *c;
-       methodinfo            *m;
-#endif
+       bool           result;
+       threadobject  *t;
+       utf           *u;
+       java_handle_t *name;
+       java_handle_t *group;
 
     /* If the current thread has already been attached, this operation
           is a no-op. */
@@ -793,7 +762,7 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
        /* Create internal thread data structure. */
 
-       t = threads_thread_new();
+       t = thread_new();
 
        /* Thread is a Java thread and running. */
 
@@ -802,26 +771,41 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        if (isdaemon)
                t->flags |= THREAD_FLAG_DAEMON;
 
+       /* Store the internal thread data-structure in the TSD. */
+
+       thread_set_current(t);
+
        /* The thread is flagged and (non-)daemon thread, we can leave the
           mutex. */
 
        threads_mutex_join_unlock();
 
-       /* create a java.lang.Thread object */
+       DEBUGTHREADS("attaching", t);
 
-       to = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+       /* Get the thread name. */
 
-       /* XXX memory leak!!! */
-       if (to == NULL)
-               return false;
+       if (vm_aargs != NULL) {
+               u = utf_new_char(vm_aargs->name);
+       }
+       else {
+               u = utf_null;
+       }
 
-       threads_thread_set_object(t, (java_handle_t *) to);
+       name = javastring_new(u);
 
-       /* Thread is completely initialized. */
+#if defined(ENABLE_JAVASE)
+       /* Get the threadgroup. */
 
-       threads_thread_state_runnable(t);
+       if (vm_aargs != NULL)
+               group = (java_handle_t *) vm_aargs->group;
+       else
+               group = NULL;
 
-       DEBUGTHREADS("attaching", t);
+       /* If no threadgroup was given, use the main threadgroup. */
+
+       if (group == NULL)
+               group = threadgroup_main;
+#endif
 
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
@@ -832,200 +816,209 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        }
 #endif
 
-#if defined(WITH_CLASSPATH_GNU)
-
-       /* create a java.lang.VMThread object */
-
-       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+       /* Create the Java thread object. */
 
-       /* XXX memory leak!!! */
-       if (vmt == NULL)
+       if (!thread_create_object(t, name, group))
                return false;
 
-       /* set the thread */
-
-       LLNI_field_set_ref(vmt, thread, to);
-       LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) t);
+       /* The thread is completely initialized. */
 
-#elif defined(WITH_CLASSPATH_SUN)
+       thread_set_state_runnable(t);
 
-       /* Sun's java.lang.Thread does not have a VMThread field in the
-          class.  Nothing to do here. */
+       return true;
+}
 
-#elif defined(WITH_CLASSPATH_CLDC1_1)
 
-       LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
+/**
+ * Attaches the current external thread to the VM.  This function is
+ * called by JNI's AttachCurrentThread.
+ *
+ * @param vm_aargs Attach arguments.
+ * @param isdaemon true if the attached thread should be a daemon
+ *                 thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+       int result;
 
-#else
-# error unknown classpath configuration
+#if defined(ENABLE_GC_BOEHM)
+       struct GC_stack_base sb;
 #endif
 
-       /* Get the thread name. */
+#if defined(ENABLE_GC_BOEHM)
+       /* Register the thread with Boehm-GC.  This must happen before the
+          thread allocates any memory from the GC heap.*/
 
-       if (vm_aargs != NULL) {
-               u = utf_new_char(vm_aargs->name);
-       }
-       else {
-               u = utf_null;
-       }
+       result = GC_get_stack_base(&sb);
 
-#if defined(ENABLE_JAVASE)
-       /* Get the threadgroup.  If no threadgroup was given, use the main
-          threadgroup. */
+       if (result != GC_SUCCESS)
+               vm_abort("threads_attach_current_thread: GC_get_stack_base failed");
 
-       if (vm_aargs != NULL)
-               group = (java_lang_ThreadGroup *) vm_aargs->group;
-               
-       if (group == NULL)
-               group = threadgroup_main;
+       GC_register_my_thread(&sb);
 #endif
 
-       /* The thread name. */
+       result = thread_attach_current_thread(vm_aargs, isdaemon);
 
-       s = javastring_new(u);
+       if (result == false) {
+#if defined(ENABLE_GC_BOEHM)
+               /* Unregister the thread. */
 
-       /* for convenience */
+               GC_unregister_my_thread();
+#endif
 
-       o = (java_handle_t *) to;
+               return false;
+       }
 
-#if defined(WITH_CLASSPATH_GNU)
+       return true;
+}
 
-       (void) vm_call_method(thread_method_init, o, vmt, s, NORM_PRIORITY,
-                                                 isdaemon);
 
-       if (exceptions_get_exception())
+/**
+ * Detaches the current external thread from the VM.  This function is
+ * called by JNI's DetachCurrentThread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool thread_detach_current_external_thread(void)
+{
+       int result;
+
+       result = thread_detach_current_thread();
+
+       if (result == false)
                return false;
 
-       /* Store the threadgroup in the Java object. */
+#if defined(ENABLE_GC_BOEHM)
+       /* Unregister the thread with Boehm-GC.  This must happen after
+          the thread allocates any memory from the GC heap. */
 
-       LLNI_field_set_ref(to, group, group);
+       /* Don't detach the main thread.  This is a workaround for
+          OpenJDK's java binary. */
+       if (thread_get_current()->index != 1)
+               GC_unregister_my_thread();
+#endif
 
-       /* Add thread to given threadgroup. */
+       return true;
+}
 
-       LLNI_class_get(group, c);
 
-       m = class_resolveclassmethod(c,
-                                                                utf_addThread,
-                                                                utf_java_lang_Thread__V,
-                                                                class_java_lang_ThreadGroup,
-                                                                true);
+/* thread_fprint_name **********************************************************
 
-       if (m == NULL)
-               return false;
+   Print the name of the given thread to the given stream.
 
-       o = (java_handle_t *) group;
+   ARGUMENTS:
+       t ........ thread data-structure
+       stream ... stream to print to
 
-       (void) vm_call_method(m, o, to);
+*******************************************************************************/
 
-       if (exceptions_get_exception())
-               return false;
+void thread_fprint_name(threadobject *t, FILE *stream)
+{
+       java_lang_Thread *to;
 
-#elif defined(WITH_CLASSPATH_SUN)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       java_lang_String *name;
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+       java_chararray_t *name;
+#endif
 
-       /* Set the priority.  java.lang.Thread.<init> requires it because
-          it sets the priority of the current thread to the parent's one
-          (which is the current thread in this case). */
+       to = (java_lang_Thread *) thread_get_object(t);
 
-       LLNI_field_set_val(to, priority, NORM_PRIORITY);
+       if (to == NULL)
+               vm_abort("");
 
-       (void) vm_call_method(thread_method_init, o, group, s);
+       LLNI_field_get_ref(to, name, name);
 
-       if (exceptions_get_exception())
-               return false;
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
-#elif defined(WITH_CLASSPATH_CLDC1_1)
+       javastring_fprint((java_handle_t *) name, stream);
 
-       (void) vm_call_method(thread_method_init, o, s);
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
 
-       if (exceptions_get_exception())
-               return false;
+       /* FIXME: In OpenJDK and CLDC the name is a char[]. */
+       /* FIXME This prints to stdout. */
+       utf_display_printable_ascii(utf_null);
 
 #else
 # error unknown classpath configuration
 #endif
-
-       return true;
 }
 
 
-/* threads_thread_print_info ***************************************************
+/* thread_print_info ***********************************************************
 
    Print information of the passed thread.
-   
+
+   ARGUMENTS:
+       t ... thread data-structure.
+
 *******************************************************************************/
 
-void threads_thread_print_info(threadobject *t)
+void thread_print_info(threadobject *t)
 {
-       java_lang_Thread *object;
-#if defined(WITH_CLASSPATH_GNU)
-       java_lang_String *namestring;
-#endif
-       utf              *name;
-
-       assert(t->state != THREAD_STATE_NEW);
+       java_lang_Thread *to;
+       int               state;
 
-       /* the thread may be currently in initalization, don't print it */
+       /* If the thread is currently in initalization, don't print it. */
 
-       object = (java_lang_Thread *) threads_thread_get_object(t);
+       to = (java_lang_Thread *) thread_get_object(t);
 
-       if (object != NULL) {
-               /* get thread name */
+       /* Print as much as we can when we are in state NEW. */
 
-#if defined(WITH_CLASSPATH_GNU)
-               LLNI_field_get_ref(object, name, namestring);
-               name = javastring_toutf((java_handle_t *) namestring, false);
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
-               /* FIXME: In cldc the name is a char[] */
-/*             name = object->name; */
-               name = utf_null;
-#else
-# error unknown classpath configuration
-#endif
+       if (to != NULL) {
+               /* Print thread name. */
 
                printf("\"");
-               utf_display_printable_ascii(name);
+               thread_fprint_name(t, stdout);
                printf("\"");
+       }
+       else {
+       }
 
-               if (t->flags & THREAD_FLAG_DAEMON)
-                       printf(" daemon");
+       if (thread_is_daemon(t))
+               printf(" daemon");
 
-               printf(" prio=%d", LLNI_field_direct(object, priority));
+       if (to != NULL) {
+               printf(" prio=%d", LLNI_field_direct(to, priority));
+       }
 
 #if SIZEOF_VOID_P == 8
-               printf(" t=0x%016lx tid=0x%016lx (%ld)",
-                          (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
+       printf(" t=0x%016lx tid=0x%016lx (%ld)",
+                  (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
 #else
-               printf(" t=0x%08x tid=0x%08x (%d)",
-                          (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
+       printf(" t=0x%08x tid=0x%08x (%d)",
+                  (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
 #endif
 
-               printf(" index=%d", t->index);
+       printf(" index=%d", t->index);
 
-               /* print thread state */
+       /* Print thread state. */
 
-               switch (t->state) {
-               case THREAD_STATE_NEW:
-                       printf(" new");
-                       break;
-               case THREAD_STATE_RUNNABLE:
-                       printf(" runnable");
-                       break;
-               case THREAD_STATE_BLOCKED:
-                       printf(" blocked");
-                       break;
-               case THREAD_STATE_WAITING:
-                       printf(" waiting");
-                       break;
-               case THREAD_STATE_TIMED_WAITING:
-                       printf(" waiting on condition");
-                       break;
-               case THREAD_STATE_TERMINATED:
-                       printf(" terminated");
-                       break;
-               default:
-                       vm_abort("threads_thread_print_info: unknown thread state %d",
-                                        t->state);
-               }
+       state = cacaothread_get_state(t);
+
+       switch (state) {
+       case THREAD_STATE_NEW:
+               printf(" new");
+               break;
+       case THREAD_STATE_RUNNABLE:
+               printf(" runnable");
+               break;
+       case THREAD_STATE_BLOCKED:
+               printf(" blocked");
+               break;
+       case THREAD_STATE_WAITING:
+               printf(" waiting");
+               break;
+       case THREAD_STATE_TIMED_WAITING:
+               printf(" waiting on condition");
+               break;
+       case THREAD_STATE_TERMINATED:
+               printf(" terminated");
+               break;
+       default:
+               vm_abort("thread_print_info: unknown thread state %d", state);
        }
 }
 
@@ -1054,7 +1047,7 @@ intptr_t threads_get_current_tid(void)
 }
 
 
-/* threads_thread_state_runnable ***********************************************
+/* thread_set_state_runnable ***************************************************
 
    Set the current state of the given thread to THREAD_STATE_RUNNABLE.
 
@@ -1063,22 +1056,23 @@ intptr_t threads_get_current_tid(void)
 
 *******************************************************************************/
 
-void threads_thread_state_runnable(threadobject *t)
+void thread_set_state_runnable(threadobject *t)
 {
        /* Set the state inside a lock. */
 
        threadlist_lock();
 
-       if (t->state != THREAD_STATE_TERMINATED)
+       if (t->state != THREAD_STATE_TERMINATED) {
                t->state = THREAD_STATE_RUNNABLE;
 
-       DEBUGTHREADS("is RUNNABLE", t);
+               DEBUGTHREADS("is RUNNABLE", t);
+       }
 
        threadlist_unlock();
 }
 
 
-/* threads_thread_state_waiting ************************************************
+/* thread_set_state_waiting ****************************************************
 
    Set the current state of the given thread to THREAD_STATE_WAITING.
 
@@ -1087,22 +1081,23 @@ void threads_thread_state_runnable(threadobject *t)
 
 *******************************************************************************/
 
-void threads_thread_state_waiting(threadobject *t)
+void thread_set_state_waiting(threadobject *t)
 {
        /* Set the state inside a lock. */
 
        threadlist_lock();
 
-       if (t->state != THREAD_STATE_TERMINATED)
+       if (t->state != THREAD_STATE_TERMINATED) {
                t->state = THREAD_STATE_WAITING;
 
-       DEBUGTHREADS("is WAITING", t);
+               DEBUGTHREADS("is WAITING", t);
+       }
 
        threadlist_unlock();
 }
 
 
-/* threads_thread_state_timed_waiting ******************************************
+/* thread_set_state_timed_waiting **********************************************
 
    Set the current state of the given thread to
    THREAD_STATE_TIMED_WAITING.
@@ -1112,31 +1107,32 @@ void threads_thread_state_waiting(threadobject *t)
 
 *******************************************************************************/
 
-void threads_thread_state_timed_waiting(threadobject *t)
+void thread_set_state_timed_waiting(threadobject *t)
 {
        /* Set the state inside a lock. */
 
        threadlist_lock();
 
-       if (t->state != THREAD_STATE_TERMINATED)
+       if (t->state != THREAD_STATE_TERMINATED) {
                t->state = THREAD_STATE_TIMED_WAITING;
 
-       DEBUGTHREADS("is TIMED_WAITING", t);
+               DEBUGTHREADS("is TIMED_WAITING", t);
+       }
 
        threadlist_unlock();
 }
 
 
-/* threads_thread_state_terminated *********************************************
+/* thread_set_state_terminated *************************************************
 
    Set the current state of the given thread to
    THREAD_STATE_TERMINATED.
 
 *******************************************************************************/
 
-void threads_thread_state_terminated(threadobject *t)
+void thread_set_state_terminated(threadobject *t)
 {
-       /* set the state in the lock */
+       /* Set the state inside a lock. */
 
        threadlist_lock();
 
@@ -1148,47 +1144,6 @@ void threads_thread_state_terminated(threadobject *t)
 }
 
 
-/* threads_thread_get_state ****************************************************
-
-   Returns the current state of the given thread.
-
-*******************************************************************************/
-
-utf *threads_thread_get_state(threadobject *t)
-{
-       utf *u;
-
-       switch (t->state) {
-       case THREAD_STATE_NEW:
-               u = utf_new_char("NEW");
-               break;
-       case THREAD_STATE_RUNNABLE:
-               u = utf_new_char("RUNNABLE");
-               break;
-       case THREAD_STATE_BLOCKED:
-               u = utf_new_char("BLOCKED");
-               break;
-       case THREAD_STATE_WAITING:
-               u = utf_new_char("WAITING");
-               break;
-       case THREAD_STATE_TIMED_WAITING:
-               u = utf_new_char("TIMED_WAITING");
-               break;
-       case THREAD_STATE_TERMINATED:
-               u = utf_new_char("TERMINATED");
-               break;
-       default:
-               vm_abort("threads_get_state: unknown thread state %d", t->state);
-
-               /* keep compiler happy */
-
-               u = NULL;
-       }
-
-       return u;
-}
-
-
 /* thread_get_thread **********************************************************
 
    Return the thread data structure of the given Java thread object.
@@ -1204,15 +1159,15 @@ utf *threads_thread_get_state(threadobject *t)
 threadobject *thread_get_thread(java_handle_t *h)
 {
        threadobject       *t;
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
        java_lang_VMThread *vmto;
        java_lang_Object   *to;
 #endif
-#if defined(WITH_CLASSPATH_SUN)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        bool                equal;
 #endif
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
        vmto = (java_lang_VMThread *) h;
 
@@ -1220,7 +1175,7 @@ threadobject *thread_get_thread(java_handle_t *h)
 
        t = (threadobject *) to;
 
-#elif defined(WITH_CLASSPATH_SUN)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
        /* XXX This is just a quick hack. */
 
@@ -1235,7 +1190,7 @@ threadobject *thread_get_thread(java_handle_t *h)
 
        threadlist_unlock();
 
-#elif defined(WITH_CLASSPATH_CLDC1_1)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
 
        log_println("threads_get_thread: IMPLEMENT ME!");
 
@@ -1255,7 +1210,11 @@ threadobject *thread_get_thread(java_handle_t *h)
 
 bool threads_thread_is_alive(threadobject *t)
 {
-       switch (t->state) {
+       int state;
+
+       state = cacaothread_get_state(t);
+
+       switch (state) {
        case THREAD_STATE_NEW:
        case THREAD_STATE_TERMINATED:
                return false;
@@ -1267,7 +1226,7 @@ bool threads_thread_is_alive(threadobject *t)
                return true;
 
        default:
-               vm_abort("threads_thread_is_alive: unknown thread state %d", t->state);
+               vm_abort("threads_thread_is_alive: unknown thread state %d", state);
        }
 
        /* keep compiler happy */
@@ -1313,12 +1272,12 @@ void threads_dump(void)
                /* Print thread info. */
 
                printf("\n");
-               threads_thread_print_info(t);
+               thread_print_info(t);
                printf("\n");
 
                /* Print trace of thread. */
 
-               threads_thread_print_stacktrace(t);
+               stacktrace_print_of_thread(t);
 
 #if defined(ENABLE_GC_CACAO)
                /* Resume the thread. */
@@ -1334,60 +1293,6 @@ void threads_dump(void)
 }
 
 
-/* threads_thread_print_stacktrace *********************************************
-
-   Print the current stacktrace of the given thread.
-
-*******************************************************************************/
-
-void threads_thread_print_stacktrace(threadobject *thread)
-{
-       stackframeinfo_t        *sfi;
-       java_handle_bytearray_t *ba;
-       stacktrace_t            *st;
-
-       /* Build a stacktrace for the passed thread. */
-
-       sfi = thread->_stackframeinfo;
-       ba  = stacktrace_get(sfi);
-       
-       if (ba != NULL) {
-               /* We need a critical section here as we use the byte-array
-                  data pointer directly. */
-
-               LLNI_CRITICAL_START;
-       
-               st = (stacktrace_t *) LLNI_array_data(ba);
-
-               /* Print stacktrace. */
-
-               stacktrace_print(st);
-
-               LLNI_CRITICAL_END;
-       }
-       else {
-               puts("\t<<No stacktrace available>>");
-               fflush(stdout);
-       }
-}
-
-
-/* threads_print_stacktrace ****************************************************
-
-   Print the current stacktrace of the current thread.
-
-*******************************************************************************/
-
-void threads_print_stacktrace(void)
-{
-       threadobject *thread;
-
-       thread = THREADOBJECT;
-
-       threads_thread_print_stacktrace(thread);
-}
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where