* src/threads/thread.cpp: thread_new no longer adds to active list.
[cacao.git] / src / threads / thread.cpp
index d6cea1793c6a197849d89c325df2e898ee1374b9..15bd67c5898826a6025cd91ea238c058cec4be1e 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/thread.cpp - machine independent thread functions
 
-   Copyright (C) 2007, 2008
+   Copyright (C) 1996-2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -31,7 +31,7 @@
 
 #include "vm/types.h"
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #if defined(ENABLE_GC_BOEHM)
 /* We need to include Boehm's gc.h here for GC_register_my_thread and
 # include "mm/boehm-gc/include/gc.h"
 #endif
 
-#include "native/jni.h"
 #include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
+#include "threads/threadlist.hpp"
 #include "threads/thread.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
 #include "vm/exceptions.hpp"
-#include "vm/stringlocal.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/method.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
 #include "vm/vm.hpp"
 
-#include "vm/jit/stacktrace.hpp"
-
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
 #if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
 #endif
 
-#include "vmcore/utf8.h"
-
+#include "vm/jit/stacktrace.hpp"
 
-// FIXME
-extern "C" {
 
 /* global variables ***********************************************************/
 
@@ -95,9 +78,8 @@ bool threads_pthreads_implementation_nptl;
 
 /* static functions ***********************************************************/
 
-static void          thread_create_initial_threadgroups(void);
 static void          thread_create_initial_thread(void);
-static threadobject *thread_new(void);
+static threadobject *thread_new(int32_t flags);
 
 
 /* threads_preinit *************************************************************
@@ -155,7 +137,11 @@ void threads_preinit(void)
 
        /* Create internal thread data-structure for the main thread. */
 
-       mainthread = thread_new();
+       mainthread = thread_new(THREAD_FLAG_JAVA);
+
+       /* Add the thread to the thread list. */
+
+       ThreadList::add_to_active_thread_list(mainthread);
 
        /* The main thread should always have index 1. */
 
@@ -163,9 +149,8 @@ void threads_preinit(void)
                vm_abort("threads_preinit: main thread index not 1: %d != 1",
                                 mainthread->index);
 
-       /* thread is a Java thread and running */
+       /* Thread is already running. */
 
-       mainthread->flags |= THREAD_FLAG_JAVA;
        mainthread->state = THREAD_STATE_RUNNABLE;
 
        /* Store the internal thread data-structure in the TSD. */
@@ -186,40 +171,11 @@ void threads_init(void)
 
        /* Create the system and main thread groups. */
 
-       thread_create_initial_threadgroups();
+       ThreadRuntime::thread_create_initial_threadgroups(&threadgroup_main, &threadgroup_system);
 
        /* Cache the java.lang.Thread initialization method. */
 
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       thread_method_init =
-               class_resolveclassmethod(class_java_lang_Thread,
-                                                                utf_init,
-                                                                utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
-                                                                class_java_lang_Thread,
-                                                                true);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       thread_method_init =
-               class_resolveclassmethod(class_java_lang_Thread,
-                                                                utf_init,
-                                                                utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"),
-                                                                class_java_lang_Thread,
-                                                                true);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
-       thread_method_init =
-               class_resolveclassmethod(class_java_lang_Thread,
-                                                                utf_init,
-                                                                utf_java_lang_String__void,
-                                                                class_java_lang_Thread,
-                                                                true);
-
-#else
-# error unknown classpath configuration
-#endif
+       thread_method_init = ThreadRuntime::get_thread_init_method();
 
        if (thread_method_init == NULL)
                vm_abort("threads_init: failed to resolve thread init method");
@@ -245,191 +201,20 @@ void threads_init(void)
 
 static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
 {
-       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);
+       java_handle_t* h = builtin_new(class_java_lang_Thread);
 
-       if (exceptions_get_exception())
+       if (h == NULL)
                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;
-}
-
-
-/* thread_create_initial_threadgroups ******************************************
-
-   Create the initial threadgroups.
-
-   GNU Classpath:
-       Create the main threadgroup only and set the system
-       threadgroup to the main threadgroup.
-
-   SUN:
-       Create the system and main threadgroup.
-
-   CLDC:
-       This function is a no-op.
-
-*******************************************************************************/
-
-static void thread_create_initial_threadgroups(void)
-{
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       /* Allocate and initialize the main thread group. */
-
-       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");
+       java_lang_Thread jlt(h);
 
-       /* Use the same threadgroup for system as for main. */
+       // Set the Java object in the thread data-structure.  This
+       // indicates that the thread is attached to the VM.
+       thread_set_object(t, jlt.get_handle());
 
-       threadgroup_system = threadgroup_main;
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       java_handle_t *name;
-       methodinfo    *m;
-
-       /* Allocate and initialize the system thread group. */
-
-       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 = builtin_new(class_java_lang_ThreadGroup);
-
-       if (threadgroup_main == NULL)
-               vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
-
-       name = javastring_new(utf_main);
-
-       m = class_resolveclassmethod(class_java_lang_ThreadGroup,
-                                                                utf_init,
-                                                                utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V,
-                                                                class_java_lang_ThreadGroup,
-                                                                true);
-
-       if (m == NULL)
-               vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
-
-       (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");
-
-# else
-#  error unknown classpath configuration
-# endif
-#endif
+       return ThreadRuntime::invoke_thread_initializer(jlt, t, thread_method_init, name, group);
 }
 
 
@@ -447,7 +232,7 @@ static void thread_create_initial_thread(void)
        /* Get the main-thread (NOTE: The main thread is always the first
           thread in the list). */
 
-       t = threadlist_first();
+       t = ThreadList::get_main_thread();
 
        /* The thread name. */
 
@@ -482,28 +267,28 @@ static void thread_create_initial_thread(void)
 
 *******************************************************************************/
 
-static threadobject *thread_new(void)
+static threadobject *thread_new(int32_t flags)
 {
        int32_t       index;
        threadobject *t;
        
        /* Lock the thread lists */
 
-       threadlist_lock();
+       ThreadList::lock();
 
-       index = threadlist_get_free_index();
+       index = ThreadList::get_free_thread_index();
 
        /* Allocate a thread data structure. */
 
        /* First, try to get one from the free-list. */
 
-       t = threadlist_free_first();
+       t = ThreadList::get_free_thread();
 
-       if (t != NULL) {
-               /* Remove from free list. */
+       /* Unlock the thread lists. */
 
-               threadlist_free_remove(t);
+       ThreadList::unlock();
 
+       if (t != NULL) {
                /* Equivalent of MZERO on the else path */
 
                threads_impl_thread_clear(t);
@@ -524,6 +309,20 @@ static threadobject *thread_new(void)
 
                MZERO(t, threadobject, 1);
 
+               // Initialize the mutex and the condition.
+               t->flc_lock = new Mutex();
+               t->flc_cond = new Condition();
+
+               t->waitmutex = new Mutex();
+               t->waitcond = new Condition();
+
+               t->suspendmutex = new Mutex();
+               t->suspendcond = new Condition();
+
+#if defined(ENABLE_TLH)
+               tlh_init(&(t->tlh));
+#endif
+
 #if defined(ENABLE_GC_CACAO)
                /* Register reference to java.lang.Thread with the GC. */
                /* FIXME is it ok to do this only once? */
@@ -532,9 +331,7 @@ static threadobject *thread_new(void)
                gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
 #endif
 
-               /* Initialize the implementation-specific bits. */
-
-               threads_impl_thread_init(t);
+               t->_dumpmemory = new DumpMemory();
        }
 
        /* Pre-compute the thinlock-word. */
@@ -542,8 +339,8 @@ static threadobject *thread_new(void)
        assert(index != 0);
 
        t->index     = index;
-       t->thinlock  = lock_pre_compute_thinlock(t->index);
-       t->flags     = 0;
+       t->thinlock  = Lockword::pre_compute_thinlock(t->index);
+       t->flags     = flags;
        t->state     = THREAD_STATE_NEW;
 
 #if defined(ENABLE_GC_CACAO)
@@ -554,14 +351,6 @@ static threadobject *thread_new(void)
 
        threads_impl_thread_reuse(t);
 
-       /* Add the thread to the thread list. */
-
-       threadlist_add(t);
-
-       /* Unlock the thread lists. */
-
-       threadlist_unlock();
-
        return t;
 }
 
@@ -579,29 +368,13 @@ static threadobject *thread_new(void)
 
 void thread_free(threadobject *t)
 {
-       /* Lock the thread lists. */
-
-       threadlist_lock();
-
-       /* Remove the thread from the thread-list. */
-
-       threadlist_remove(t);
-
-       /* Add the thread index to the free list. */
-
-       threadlist_index_add(t->index);
-
        /* Set the reference to the Java object to NULL. */
 
        thread_set_object(t, NULL);
 
-       /* Add the thread data structure to the free list. */
-
-       threadlist_free_add(t);
-
-       /* Unlock the thread lists. */
+       /* Release the thread. */
 
-       threadlist_unlock();
+       ThreadList::release_thread(t);
 }
 
 
@@ -628,9 +401,11 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
        /* Create internal thread data-structure. */
 
-       t = thread_new();
+       t = thread_new(THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON);
 
-       t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+       /* Add the thread to the thread list. */
+
+       ThreadList::add_to_active_thread_list(t);
 
        /* The thread is flagged as (non-)daemon thread, we can leave the
           mutex. */
@@ -664,13 +439,7 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
 void threads_thread_start(java_handle_t *object)
 {
-       java_lang_Thread   *to;
-       threadobject       *t;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_lang_VMThread *vmto;
-#endif
-
-       to = (java_lang_Thread *) object;
+       java_lang_Thread jlt(object);
 
        /* Enter the join-mutex, so if the main-thread is currently
           waiting to join all threads, the number of non-daemon threads
@@ -680,50 +449,26 @@ void threads_thread_start(java_handle_t *object)
 
        /* Create internal thread data-structure. */
 
-       t = thread_new();
-
-       /* this is a normal Java thread */
-
-       t->flags |= THREAD_FLAG_JAVA;
+       threadobject* t = thread_new(THREAD_FLAG_JAVA);
 
 #if defined(ENABLE_JAVASE)
        /* Is this a daemon thread? */
 
-       if (LLNI_field_direct(to, daemon) == true)
+       if (jlt.get_daemon() == true)
                t->flags |= THREAD_FLAG_DAEMON;
 #endif
 
-       /* The thread is flagged and (non-)daemon thread, we can leave the
-          mutex. */
-
-       threads_mutex_join_unlock();
-
        /* Link the two objects together. */
 
        thread_set_object(t, object);
 
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       /* Get the java.lang.VMThread object and do some sanity checks. */
-
-       LLNI_field_get_ref(to, vmThread, vmto);
-
-       assert(vmto);
-       assert(LLNI_field_direct(vmto, vmdata) == NULL);
-
-       LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       /* Nothing to do. */
+       /* Add the thread to the thread list. */
 
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+       ThreadList::add_to_active_thread_list(t);
 
-       LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
+       threads_mutex_join_unlock();
 
-#else
-# error unknown classpath configuration
-#endif
+       ThreadRuntime::setup_thread_vmdata(jlt, t);
 
        /* Start the thread.  Don't pass a function pointer (NULL) since
           we want Thread.run()V here. */
@@ -765,11 +510,7 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
        /* Create internal thread data structure. */
 
-       t = thread_new();
-
-       /* Thread is a Java thread and running. */
-
-       t->flags = THREAD_FLAG_JAVA;
+       t = thread_new(THREAD_FLAG_JAVA);
 
        if (isdaemon)
                t->flags |= THREAD_FLAG_DAEMON;
@@ -781,6 +522,10 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        /* The thread is flagged and (non-)daemon thread, we can leave the
           mutex. */
 
+       /* Add the thread to the thread list. */
+
+       ThreadList::add_to_active_thread_list(t);
+
        threads_mutex_join_unlock();
 
        DEBUGTHREADS("attaching", t);
@@ -848,9 +593,7 @@ bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isda
 
 #if defined(ENABLE_GC_BOEHM)
        struct GC_stack_base sb;
-#endif
 
-#if defined(ENABLE_GC_BOEHM)
        /* Register the thread with Boehm-GC.  This must happen before the
           thread allocates any memory from the GC heap.*/
 
@@ -898,7 +641,7 @@ bool thread_detach_current_external_thread(void)
           the thread allocates any memory from the GC heap. */
 
        /* Don't detach the main thread.  This is a workaround for
-          OpenJDK's java binary. */
+          OpenJDK's java launcher. */
        if (thread_get_current()->index != 1)
                GC_unregister_my_thread();
 #endif
@@ -919,34 +662,12 @@ bool thread_detach_current_external_thread(void)
 
 void thread_fprint_name(threadobject *t, FILE *stream)
 {
-       java_lang_Thread *to;
-
-#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
-
-       to = (java_lang_Thread *) thread_get_object(t);
-
-       if (to == NULL)
+       if (thread_get_object(t) == NULL)
                vm_abort("");
 
-       LLNI_field_get_ref(to, name, name);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       javastring_fprint((java_handle_t *) name, stream);
+       java_lang_Thread jlt(thread_get_object(t));
 
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
-       /* 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
+       ThreadRuntime::print_thread_name(jlt, stream);
 }
 
 
@@ -961,16 +682,11 @@ void thread_fprint_name(threadobject *t, FILE *stream)
 
 void thread_print_info(threadobject *t)
 {
-       java_lang_Thread *to;
-       int               state;
-
-       /* If the thread is currently in initalization, don't print it. */
-
-       to = (java_lang_Thread *) thread_get_object(t);
+       java_lang_Thread jlt(thread_get_object(t));
 
        /* Print as much as we can when we are in state NEW. */
 
-       if (to != NULL) {
+       if (jlt.get_handle() != NULL) {
                /* Print thread name. */
 
                printf("\"");
@@ -983,8 +699,8 @@ void thread_print_info(threadobject *t)
        if (thread_is_daemon(t))
                printf(" daemon");
 
-       if (to != NULL) {
-               printf(" prio=%d", LLNI_field_direct(to, priority));
+       if (jlt.get_handle() != NULL) {
+               printf(" prio=%d", jlt.get_priority());
        }
 
 #if SIZEOF_VOID_P == 8
@@ -999,7 +715,7 @@ void thread_print_info(threadobject *t)
 
        /* Print thread state. */
 
-       state = cacaothread_get_state(t);
+       int state = cacaothread_get_state(t);
 
        switch (state) {
        case THREAD_STATE_NEW:
@@ -1017,6 +733,12 @@ void thread_print_info(threadobject *t)
        case THREAD_STATE_TIMED_WAITING:
                printf(" waiting on condition");
                break;
+       case THREAD_STATE_PARKED:
+               printf(" parked");
+               break;
+       case THREAD_STATE_TIMED_PARKED:
+               printf(" timed parked");
+               break;
        case THREAD_STATE_TERMINATED:
                printf(" terminated");
                break;
@@ -1050,6 +772,21 @@ intptr_t threads_get_current_tid(void)
 }
 
 
+/**
+ * Set the current state of the given thread. This method should only
+ * be called while holding the threadlist-lock and after checking that
+ * the new state is valid. It is best to not call this method directly
+ * but call the specific setter methods below.
+ */
+static inline void thread_set_state(threadobject *t, int state)
+{
+       // Set the state of our internal threadobject.
+       t->state = state;
+
+       ThreadRuntime::set_javathread_state(t, state);
+}
+
+
 /* thread_set_state_runnable ***************************************************
 
    Set the current state of the given thread to THREAD_STATE_RUNNABLE.
@@ -1061,17 +798,11 @@ intptr_t threads_get_current_tid(void)
 
 void thread_set_state_runnable(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       threadlist_lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
-               t->state = THREAD_STATE_RUNNABLE;
+               thread_set_state(t, THREAD_STATE_RUNNABLE);
 
                DEBUGTHREADS("is RUNNABLE", t);
        }
-
-       threadlist_unlock();
 }
 
 
@@ -1086,17 +817,11 @@ void thread_set_state_runnable(threadobject *t)
 
 void thread_set_state_waiting(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       threadlist_lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
-               t->state = THREAD_STATE_WAITING;
+               thread_set_state(t, THREAD_STATE_WAITING);
 
                DEBUGTHREADS("is WAITING", t);
        }
-
-       threadlist_unlock();
 }
 
 
@@ -1112,17 +837,49 @@ void thread_set_state_waiting(threadobject *t)
 
 void thread_set_state_timed_waiting(threadobject *t)
 {
-       /* Set the state inside a lock. */
+       if (t->state != THREAD_STATE_TERMINATED) {
+               thread_set_state(t, THREAD_STATE_TIMED_WAITING);
+
+               DEBUGTHREADS("is TIMED_WAITING", t);
+       }
+}
 
-       threadlist_lock();
 
+/* thread_set_state_parked *****************************************************
+
+   Set the current state of the given thread to THREAD_STATE_PARKED.
+
+   NOTE: If the thread has already terminated, don't set the state.
+         This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_parked(threadobject *t)
+{
        if (t->state != THREAD_STATE_TERMINATED) {
-               t->state = THREAD_STATE_TIMED_WAITING;
+               thread_set_state(t, THREAD_STATE_PARKED);
 
-               DEBUGTHREADS("is TIMED_WAITING", t);
+               DEBUGTHREADS("is PARKED", t);
        }
+}
+
+
+/* thread_set_state_timed_parked ***********************************************
 
-       threadlist_unlock();
+   Set the current state of the given thread to THREAD_STATE_TIMED_PARKED.
+
+   NOTE: If the thread has already terminated, don't set the state.
+         This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_timed_parked(threadobject *t)
+{
+       if (t->state != THREAD_STATE_TERMINATED) {
+               thread_set_state(t, THREAD_STATE_TIMED_PARKED);
+
+               DEBUGTHREADS("is TIMED_PARKED", t);
+       }
 }
 
 
@@ -1137,13 +894,13 @@ void thread_set_state_terminated(threadobject *t)
 {
        /* Set the state inside a lock. */
 
-       threadlist_lock();
+       ThreadList::lock();
 
-       t->state = THREAD_STATE_TERMINATED;
+       thread_set_state(t, THREAD_STATE_TERMINATED);
 
        DEBUGTHREADS("is TERMINATED", t);
 
-       threadlist_unlock();
+       ThreadList::unlock();
 }
 
 
@@ -1157,51 +914,15 @@ void thread_set_state_terminated(threadobject *t)
    RETURN VALUE:
        the thread object
 
+   NOTE:
+       Usage of this function without the thread list lock held is
+       almost certainly a bug.
+
 *******************************************************************************/
 
 threadobject *thread_get_thread(java_handle_t *h)
 {
-       threadobject       *t;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_lang_VMThread *vmto;
-       java_lang_Object   *to;
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       bool                equal;
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-       vmto = (java_lang_VMThread *) h;
-
-       LLNI_field_get_val(vmto, vmdata, to);
-
-       t = (threadobject *) to;
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-       /* XXX This is just a quick hack. */
-
-       threadlist_lock();
-
-       for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
-               LLNI_equals(t->object, h, equal);
-
-               if (equal == true)
-                       break;
-       }
-
-       threadlist_unlock();
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
-       log_println("threads_get_thread: IMPLEMENT ME!");
-
-#else
-# error unknown classpath configuration
-#endif
-
-       return t;
+       return ThreadRuntime::get_threadobject_from_thread(h);
 }
 
 
@@ -1226,6 +947,8 @@ bool threads_thread_is_alive(threadobject *t)
        case THREAD_STATE_BLOCKED:
        case THREAD_STATE_WAITING:
        case THREAD_STATE_TIMED_WAITING:
+       case THREAD_STATE_PARKED:
+       case THREAD_STATE_TIMED_PARKED:
                return true;
 
        default:
@@ -1237,65 +960,117 @@ bool threads_thread_is_alive(threadobject *t)
        return false;
 }
 
+/* thread_is_interrupted *******************************************************
+
+   Check if the given thread has been interrupted.
 
-/* threads_dump ****************************************************************
+   ARGUMENTS:
+       t ... the thread to check
 
-   Dumps info for all threads running in the JVM.  This function is
-   called when SIGQUIT (<ctrl>-\) is sent to CACAO.
+   RETURN VALUE:
+      true, if the given thread had been interrupted
 
 *******************************************************************************/
 
-void threads_dump(void)
+bool thread_is_interrupted(threadobject *t)
 {
-       threadobject *t;
+       /* We need the mutex because classpath will call this function when
+          a blocking system call is interrupted. The mutex ensures that it will
+          see the correct value for the interrupted flag. */
 
-       /* XXX we should stop the world here */
+       t->waitmutex->lock();
+       bool interrupted = t->interrupted;
+       t->waitmutex->unlock();
 
-       /* Lock the thread lists. */
+       return interrupted;
+}
 
-       threadlist_lock();
 
-       printf("Full thread dump CACAO "VERSION":\n");
+/* thread_set_interrupted ******************************************************
 
-       /* iterate over all started threads */
+   Set the interrupted flag to the given value.
 
-       for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
-               /* ignore threads which are in state NEW */
-               if (t->state == THREAD_STATE_NEW)
-                       continue;
+   ARGUMENTS:
+       interrupted ... value to set
 
-#if defined(ENABLE_GC_CACAO)
-               /* Suspend the thread. */
-               /* XXX Is the suspend reason correct? */
+*******************************************************************************/
 
-               if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
-                       vm_abort("threads_dump: threads_suspend_thread failed");
-#endif
+void thread_set_interrupted(threadobject *t, bool interrupted)
+{
+       t->waitmutex->lock();
+       t->interrupted = interrupted;
+       t->waitmutex->unlock();
+}
 
-               /* Print thread info. */
+/* thread_handle_set_priority **************************************************
 
-               printf("\n");
-               thread_print_info(t);
-               printf("\n");
+   Calls threads_set_thread_priority for the threadobject associated
+   with the thread indicated by handle th, while holding the thread
+   list lock.
 
-               /* Print trace of thread. */
+*******************************************************************************/
 
-               stacktrace_print_of_thread(t);
+void thread_handle_set_priority(java_handle_t *th, int priority)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       /* For GNU classpath, this should not happen, because both
+          setPriority() and start() are synchronized. */
+       assert(t != 0);
+       threads_set_thread_priority(t->tid, priority);
+}
 
-#if defined(ENABLE_GC_CACAO)
-               /* Resume the thread. */
+/* thread_handle_is_interrupted ************************************************
 
-               if (threads_resume_thread(t) == false)
-                       vm_abort("threads_dump: threads_resume_thread failed");
-#endif
-       }
+   Calls thread_is_interrupted for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
 
-       /* Unlock the thread lists. */
+*******************************************************************************/
 
-       threadlist_unlock();
+bool thread_handle_is_interrupted(java_handle_t *th)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       return t ? thread_is_interrupted(t) : false;
 }
 
-} // extern "C"
+/* thread_handle_interrupt *****************************************************
+
+   Calls threads_thread_interrupt for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+void thread_handle_interrupt(java_handle_t *th)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       /* For GNU classpath, this should not happen, because both
+          interrupt() and start() are synchronized. */
+       assert(t != 0);
+       threads_thread_interrupt(t);
+}
+
+/* thread_handle_get_state *****************************************************
+
+   Calls cacaothread_get_state for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+int thread_handle_get_state(java_handle_t *th)
+{
+       ThreadListLocker l;
+
+       threadobject *t = thread_get_thread(th);
+       return t ? cacaothread_get_state(t) : THREAD_STATE_NEW;
+}
 
 
 /*