* Removed all Id tags.
[cacao.git] / src / threads / native / threads.c
index b7ab5a4fafc04cf344fa8d60b8b8643762882e78..a2dd4de09d22b0081ddf883e0b0ec19c7e9a0691 100644 (file)
@@ -22,8 +22,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: threads.c 7246 2007-01-29 18:49:05Z twisti $
-
 */
 
 
@@ -57,6 +55,7 @@
 #include "mm/memory.h"
 
 #include "native/jni.h"
+#include "native/llni.h"
 #include "native/native.h"
 #include "native/include/java_lang_Object.h"
 #include "native/include/java_lang_String.h"
 # include "native/include/java_lang_VMThread.h"
 #endif
 
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
+
 #include "threads/native/threads.h"
 
-#include "toolbox/avl.h"
 #include "toolbox/logging.h"
 
 #include "vm/builtin.h"
 
 #include "vmcore/options.h"
 
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
 #if !defined(__DARWIN__)
 # if defined(__LINUX__)
 #  define GC_LINUX_THREADS
@@ -183,8 +188,6 @@ static int sem_destroy(sem_t *sem)
 #define STOPWORLD_FROM_GC               1
 #define STOPWORLD_FROM_CLASS_NUMBERING  2
 
-#define THREADS_INITIAL_TABLE_SIZE      8
-
 
 /* startupinfo *****************************************************************
 
@@ -204,22 +207,13 @@ typedef struct {
 
 /* prototypes *****************************************************************/
 
-static void threads_table_init(void);
-static s4 threads_table_add(threadobject *thread);
-static void threads_table_remove(threadobject *thread);
 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
 
-#if !defined(NDEBUG) && 0
-static void threads_table_dump(FILE *file);
-#endif
 
 /******************************************************************************/
 /* GLOBAL VARIABLES                                                           */
 /******************************************************************************/
 
-/* the main thread                                                            */
-threadobject *mainthreadobj;
-
 static methodinfo *method_thread_init;
 
 /* the thread object of the current thread                                    */
@@ -231,18 +225,21 @@ __thread threadobject *threads_current_threadobject;
 pthread_key_t threads_current_threadobject_key;
 #endif
 
-/* global threads table                                                       */
-static threads_table_t threads_table;
-
-/* global compiler mutex                                                      */
-static pthread_mutex_t compiler_mutex;
-
-/* global mutex for changing the thread list                                  */
-static pthread_mutex_t threadlistlock;
+/* global mutex for the threads table */
+static pthread_mutex_t mutex_threads_list;
 
 /* global mutex for stop-the-world                                            */
 static pthread_mutex_t stopworldlock;
 
+/* global mutex and condition for joining threads on exit */
+static pthread_mutex_t mutex_join;
+static pthread_cond_t  cond_join;
+
+/* XXX We disable that whole bunch of code until we have the exact-GC
+   running. */
+
+#if 0
+
 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
 /* being stopped                                                              */
 static volatile int stopworldwhere;
@@ -254,7 +251,7 @@ static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
 #endif
 
-static pthread_attr_t threadattr;
+#endif /* 0 */
 
 /* mutexes used by the fake atomic instructions                               */
 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
@@ -344,30 +341,6 @@ void threads_sem_post(sem_t *sem)
 }
 
 
-/* compiler_lock ***************************************************************
-
-   Enter the compiler lock.
-
-******************************************************************************/
-
-void compiler_lock(void)
-{
-       pthread_mutex_lock(&compiler_mutex);
-}
-
-
-/* compiler_unlock *************************************************************
-
-   Release the compiler lock.
-
-******************************************************************************/
-
-void compiler_unlock(void)
-{
-       pthread_mutex_unlock(&compiler_mutex);
-}
-
-
 /* lock_stopworld **************************************************************
 
    Enter the stopworld lock, specifying why the world shall be stopped.
@@ -381,7 +354,7 @@ void compiler_unlock(void)
 void lock_stopworld(int where)
 {
        pthread_mutex_lock(&stopworldlock);
-       stopworldwhere = where;
+/*     stopworldwhere = where; */
 }
 
 
@@ -393,34 +366,51 @@ void lock_stopworld(int where)
 
 void unlock_stopworld(void)
 {
-       stopworldwhere = 0;
+/*     stopworldwhere = 0; */
        pthread_mutex_unlock(&stopworldlock);
 }
 
+/* XXX We disable that whole bunch of code until we have the exact-GC
+   running. */
+
+#if 0
+
 #if !defined(__DARWIN__)
 /* Caller must hold threadlistlock */
-static int threads_cast_sendsignals(int sig, int count)
+static s4 threads_cast_sendsignals(s4 sig)
 {
-       /* Count threads */
-       threadobject *tobj = mainthreadobj;
-       threadobject *self = THREADOBJECT;
+       threadobject *t;
+       threadobject *self;
+       s4            count;
 
-       if (count == 0) {
-               do {
-                       count++;
-                       tobj = tobj->next;
-               } while (tobj != mainthreadobj);
-       }
+       self = THREADOBJECT;
 
-       assert(tobj == mainthreadobj);
+       /* iterate over all started threads */
 
-       do {
-               if (tobj != self)
-                       pthread_kill(tobj->tid, sig);
-               tobj = tobj->next;
-       } while (tobj != mainthreadobj);
+       count = 0;
+
+       for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
+               /* don't send the signal to ourself */
+
+               if (t == self)
+                       continue;
+
+               /* don't send the signal to NEW threads (because they are not
+                  completely initialized) */
+
+               if (t->state == THREAD_STATE_NEW)
+                       continue;
+
+               /* send the signal */
 
-       return count - 1;
+               pthread_kill(t->tid, sig);
+
+               /* increase threads count */
+
+               count++;
+       }
+
+       return count;
 }
 
 #else
@@ -454,7 +444,7 @@ static void threads_cast_darwinstop(void)
                        if (r != KERN_SUCCESS)
                                vm_abort("thread_get_state failed");
 
-                       thread_restartcriticalsection((ucontext_t *) &thread_state);
+                       md_critical_section_restart((ucontext_t *) &thread_state);
 
                        r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
                                                                 thread_state_count);
@@ -504,11 +494,14 @@ static void threads_cast_irixresume(void)
 void threads_cast_stopworld(void)
 {
 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
-       int count, i;
+       s4 count, i;
 #endif
 
        lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
-       pthread_mutex_lock(&threadlistlock);
+
+       /* lock the threads lists */
+
+       threads_list_lock();
 
 #if defined(__DARWIN__)
        threads_cast_darwinstop();
@@ -516,17 +509,24 @@ void threads_cast_stopworld(void)
        /* TODO */
        assert(0);
 #else
-       count = threads_cast_sendsignals(GC_signum1(), 0);
+       /* send all threads the suspend signal */
+
+       count = threads_cast_sendsignals(GC_signum1());
+
+       /* wait for all threads signaled to suspend */
+
        for (i = 0; i < count; i++)
                threads_sem_wait(&suspend_ack);
 #endif
 
-       pthread_mutex_unlock(&threadlistlock);
+       /* ATTENTION: Don't unlock the threads-lists here so that
+          non-signaled NEW threads can't change their state and execute
+          code. */
 }
 
+
 void threads_cast_startworld(void)
 {
-       pthread_mutex_lock(&threadlistlock);
 #if defined(__DARWIN__)
        threads_cast_darwinresume();
 #elif defined(__MIPS__)
@@ -535,22 +535,26 @@ void threads_cast_startworld(void)
        /* TODO */
        assert(0);
 #else
-       threads_cast_sendsignals(GC_signum2(), -1);
+       (void) threads_cast_sendsignals(GC_signum2());
 #endif
-       pthread_mutex_unlock(&threadlistlock);
+
+       /* unlock the threads lists */
+
+       threads_list_unlock();
+
        unlock_stopworld();
 }
 
 
 #if !defined(__DARWIN__)
-static void threads_sigsuspend_handler(ucontext_t *ctx)
+static void threads_sigsuspend_handler(ucontext_t *_uc)
 {
        int sig;
        sigset_t sigs;
 
        /* XXX TWISTI: this is just a quick hack */
 #if defined(ENABLE_JIT)
-       thread_restartcriticalsection(ctx);
+       md_critical_section_restart(_uc);
 #endif
 
        /* Do as Boehm does. On IRIX a condition variable is used for wake-up
@@ -573,20 +577,25 @@ static void threads_sigsuspend_handler(ucontext_t *ctx)
 #endif
 }
 
+#endif
+
+
 /* This function is called from Boehm GC code. */
 
-int cacao_suspendhandler(ucontext_t *ctx)
+int cacao_suspendhandler(ucontext_t *_uc)
 {
        if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
                return 0;
 
-       threads_sigsuspend_handler(ctx);
+       threads_sigsuspend_handler(_uc);
        return 1;
 }
-#endif
 
 #endif /* DISABLE_GC */
 
+#endif /* 0 */
+
+
 /* threads_set_current_threadobject ********************************************
 
    Set the current thread object.
@@ -596,41 +605,70 @@ int cacao_suspendhandler(ucontext_t *ctx)
 
 *******************************************************************************/
 
-static void threads_set_current_threadobject(threadobject *thread)
+void threads_set_current_threadobject(threadobject *thread)
 {
 #if !defined(HAVE___THREAD)
-       pthread_setspecific(threads_current_threadobject_key, thread);
+       if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
+               vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
 #else
        threads_current_threadobject = thread;
 #endif
 }
 
 
-/* threads_init_threadobject **************************************************
+/* threads_impl_thread_new *****************************************************
 
    Initialize implementation fields of a threadobject.
 
    IN:
-      thread............the threadobject
+      t....the threadobject
 
-******************************************************************************/
+*******************************************************************************/
 
-static void threads_init_threadobject(threadobject *thread)
+void threads_impl_thread_new(threadobject *t)
 {
-       thread->tid = pthread_self();
+       /* get the pthread id */
 
-       thread->index = 0;
+       t->tid = pthread_self();
 
-       /* TODO destroy all those things */
-       pthread_mutex_init(&(thread->joinmutex), NULL);
-       pthread_cond_init(&(thread->joincond), NULL);
+       /* initialize the mutex and the condition */
 
-       pthread_mutex_init(&(thread->waitmutex), NULL);
-       pthread_cond_init(&(thread->waitcond), NULL);
+       pthread_mutex_init(&(t->waitmutex), NULL);
+       pthread_cond_init(&(t->waitcond), NULL);
 
-       thread->interrupted = false;
-       thread->signaled = false;
-       thread->sleeping = false;
+#if defined(ENABLE_DEBUG_FILTER)
+       /* Initialize filter counters */
+       t->filterverbosecallctr[0] = 0;
+       t->filterverbosecallctr[1] = 0;
+#endif
+
+#if !defined(NDEBUG)
+       t->tracejavacallindent = 0;
+       t->tracejavacallcount = 0;
+#endif
+}
+
+
+/* threads_impl_thread_free ****************************************************
+
+   Cleanup thread stuff.
+
+   IN:
+      t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_free(threadobject *t)
+{
+       /* destroy the mutex and the condition */
+
+       if (pthread_mutex_destroy(&(t->waitmutex)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
+                                strerror(errno));
+
+       if (pthread_cond_destroy(&(t->waitcond)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
+                                strerror(errno));
 }
 
 
@@ -649,7 +687,7 @@ threadobject *threads_get_current_threadobject(void)
 }
 
 
-/* threads_preinit *************************************************************
+/* threads_impl_preinit ********************************************************
 
    Do some early initialization of stuff required.
 
@@ -658,38 +696,86 @@ threadobject *threads_get_current_threadobject(void)
 
 *******************************************************************************/
 
-void threads_preinit(void)
+void threads_impl_preinit(void)
 {
-       pthread_mutexattr_t mutexattr;
-       pthread_mutexattr_init(&mutexattr);
-       pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
-       pthread_mutex_init(&compiler_mutex, &mutexattr);
-       pthread_mutexattr_destroy(&mutexattr);
-
-       pthread_mutex_init(&threadlistlock, NULL);
        pthread_mutex_init(&stopworldlock, NULL);
 
-       mainthreadobj = NEW(threadobject);
-       mainthreadobj->tid      = pthread_self();
-       mainthreadobj->index    = 1;
-       mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
-       
+       /* initialize exit mutex and condition (on exit we join all
+          threads) */
+
+       pthread_mutex_init(&mutex_join, NULL);
+       pthread_cond_init(&cond_join, NULL);
+
+       /* initialize the threads-list mutex */
+
+       pthread_mutex_init(&mutex_threads_list, NULL);
+
 #if !defined(HAVE___THREAD)
        pthread_key_create(&threads_current_threadobject_key, NULL);
 #endif
-       threads_set_current_threadobject(mainthreadobj);
 
-       threads_sem_init(&suspend_ack, 0, 0);
+/*     threads_sem_init(&suspend_ack, 0, 0); */
+}
+
 
-       /* initialize the threads table */
+/* threads_list_lock ***********************************************************
 
-       threads_table_init();
+   Enter the threads table mutex.
 
-       /* initialize subsystems */
+   NOTE: We need this function as we can't use an internal lock for
+         the threads lists because the thread's lock is initialized in
+         threads_table_add (when we have the thread index), but we
+         already need the lock at the entry of the function.
 
-       lock_init();
+*******************************************************************************/
 
-       critical_init();
+void threads_list_lock(void)
+{
+       if (pthread_mutex_lock(&mutex_threads_list) != 0)
+               vm_abort("threads_list_lock: pthread_mutex_lock failed: %s",
+                                strerror(errno));
+}
+
+
+/* threads_list_unlock *********************************************************
+
+   Leave the threads list mutex.
+
+*******************************************************************************/
+
+void threads_list_unlock(void)
+{
+       if (pthread_mutex_unlock(&mutex_threads_list) != 0)
+               vm_abort("threads_list_unlock: pthread_mutex_unlock failed: %s",
+                                strerror(errno));
+}
+
+
+/* threads_mutex_join_lock *****************************************************
+
+   Enter the join mutex.
+
+*******************************************************************************/
+
+void threads_mutex_join_lock(void)
+{
+       if (pthread_mutex_lock(&mutex_join) != 0)
+               vm_abort("threads_mutex_join_lock: pthread_mutex_lock failed: %s",
+                                strerror(errno));
+}
+
+
+/* threads_mutex_join_unlock ***************************************************
+
+   Leave the join mutex.
+
+*******************************************************************************/
+
+void threads_mutex_join_unlock(void)
+{
+       if (pthread_mutex_unlock(&mutex_join) != 0)
+               vm_abort("threads_mutex_join_unlock: pthread_mutex_unlock failed: %s",
+                                strerror(errno));
 }
 
 
@@ -701,31 +787,21 @@ void threads_preinit(void)
 
 bool threads_init(void)
 {
-       java_lang_String      *threadname;
-       threadobject          *tempthread;
-       java_objectheader     *o;
+       threadobject     *mainthread;
+       java_handle_t    *threadname;
+       java_lang_Thread *t;
+       java_handle_t    *o;
 
 #if defined(ENABLE_JAVASE)
        java_lang_ThreadGroup *threadgroup;
        methodinfo            *m;
-       java_lang_Thread      *t;
 #endif
 
 #if defined(WITH_CLASSPATH_GNU)
        java_lang_VMThread    *vmt;
 #endif
 
-       tempthread = mainthreadobj;
-
-       /* XXX We have to find a new way to free lock records */
-       /*     with the new locking algorithm.                */
-       /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
-
-       /* This is kinda tricky, we grow the java.lang.Thread object so we
-          can keep the execution environment there. No Thread object must
-          have been created at an earlier time. */
-
-       class_java_lang_Thread->instancesize = sizeof(threadobject);
+       pthread_attr_t attr;
 
        /* get methods we need in this file */
 
@@ -736,48 +812,49 @@ bool threads_init(void)
                                                                 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
                                                                 class_java_lang_Thread,
                                                                 true);
-#else
+#elif defined(WITH_CLASSPATH_SUN)
        method_thread_init =
                class_resolveclassmethod(class_java_lang_Thread,
                                                                 utf_init,
                                                                 utf_new_char("(Ljava/lang/String;)V"),
                                                                 class_java_lang_Thread,
                                                                 true);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       method_thread_init =
+               class_resolveclassmethod(class_java_lang_Thread,
+                                                                utf_init,
+                                                                utf_new_char("(Ljava/lang/String;)V"),
+                                                                class_java_lang_Thread,
+                                                                true);
+#else
+# error unknown classpath configuration
 #endif
 
        if (method_thread_init == NULL)
                return false;
 
-       /* create a java.lang.Thread for the main thread */
-
-       mainthreadobj = (threadobject *) builtin_new(class_java_lang_Thread);
-
-       if (mainthreadobj == NULL)
-               return false;
-
-       FREE(tempthread, threadobject);
-
-       threads_init_threadobject(mainthreadobj);
+       /* Get the main-thread (NOTE: The main threads is always the first
+          thread in the list). */
 
-       threads_set_current_threadobject(mainthreadobj);
+       mainthread = threads_list_first();
 
-       lock_init_execution_env(mainthreadobj);
+       /* create a java.lang.Thread for the main thread */
 
-       mainthreadobj->next = mainthreadobj;
-       mainthreadobj->prev = mainthreadobj;
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       threads_table_add(mainthreadobj);
+       if (t == NULL)
+               return false;
 
-       /* mark main thread as Java thread */
+       /* set the object in the internal data structure */
 
-       mainthreadobj->flags = THREAD_FLAG_JAVA;
+       mainthread->object = t;
 
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
 
        if (opt_intrp) {
                MSET(intrp_main_stack, 0, u1, opt_stacksize);
-               mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
+               mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
        }
 #endif
 
@@ -790,7 +867,7 @@ bool threads_init(void)
                native_new_and_init(class_java_lang_ThreadGroup);
 
        if (threadgroup == NULL)
-               throw_exception_exit();
+               return false;
 #endif
 
 #if defined(WITH_CLASSPATH_GNU)
@@ -799,32 +876,54 @@ bool threads_init(void)
        vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
        if (vmt == NULL)
-               throw_exception_exit();
+               return false;
 
        /* set the thread */
 
-       t           = (java_lang_Thread *) mainthreadobj;
-       vmt->thread = t;
+       LLNI_field_set_ref(vmt, thread, t);
+       LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) mainthread);
 
        /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
-       o = (java_objectheader *) mainthreadobj;
+       o = (java_handle_t *) t;
 
        (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
                                                  false);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+       /* We trick java.lang.Thread.<init>, which sets the priority of
+          the current thread to the parent's one. */
+
+       t->priority = NORM_PRIORITY;
+
+       /* Call java.lang.Thread.<init>(Ljava/lang/String;)V */
+
+       o = (java_object_t *) t;
+
+       (void) vm_call_method(method_thread_init, o, threadname);
+
 #elif defined(WITH_CLASSPATH_CLDC1_1)
+
+       /* set the thread */
+
+       t->vm_thread = (java_lang_Object *) mainthread;
+
        /* call public Thread(String name) */
 
-       o = (java_objectheader *) mainthreadobj;
+       o = (java_handle_t *) t;
 
        (void) vm_call_method(method_thread_init, o, threadname);
+#else
+# error unknown classpath configuration
 #endif
 
-       if (*exceptionptr)
+       if (exceptions_get_exception())
                return false;
 
 #if defined(ENABLE_JAVASE)
-       mainthreadobj->o.group = threadgroup;
+       LLNI_field_set_ref(t, group, threadgroup);
 
+# if defined(WITH_CLASSPATH_GNU)
        /* add main thread to java.lang.ThreadGroup */
 
        m = class_resolveclassmethod(class_java_lang_ThreadGroup,
@@ -833,153 +932,39 @@ bool threads_init(void)
                                                                 class_java_lang_ThreadGroup,
                                                                 true);
 
-       o = (java_objectheader *) threadgroup;
-       t = (java_lang_Thread *) mainthreadobj;
+       o = (java_handle_t *) threadgroup;
 
        (void) vm_call_method(m, o, t);
 
-       if (*exceptionptr)
+       if (exceptions_get_exception())
                return false;
-
+# else
+#  warning Do not know what to do here
+# endif
 #endif
 
        threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
 
        /* initialize the thread attribute object */
 
-       if (pthread_attr_init(&threadattr)) {
-               log_println("pthread_attr_init failed: %s", strerror(errno));
-               return false;
-       }
-
-       pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
-
-       /* everything's ok */
-
-       return true;
-}
-
-
-/* threads_table_init *********************************************************
-
-   Initialize the global threads table.
-
-******************************************************************************/
-
-static void threads_table_init(void)
-{
-       s4 size;
-       s4 i;
-
-       size = THREADS_INITIAL_TABLE_SIZE;
-
-       threads_table.size = size;
-       threads_table.table = MNEW(threads_table_entry_t, size);
-
-       /* link the entries in a freelist */
-
-       for (i=0; i<size; ++i) {
-               threads_table.table[i].nextfree = i+1;
-       }
-
-       /* terminate the freelist */
-
-       threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
-}
-
-
-/* threads_table_add **********************************************************
-
-   Add a thread to the global threads table. The index is entered in the
-   threadobject. The thinlock value for the thread is pre-computed.
-
-   IN:
-      thread............the thread to add
-
-   RETURN VALUE:
-      The table index for the newly added thread. This value has also been
-         entered in the threadobject.
-
-   PRE-CONDITION:
-      The caller must hold the threadlistlock!
-
-******************************************************************************/
-
-static s4 threads_table_add(threadobject *thread)
-{
-       s4 index;
-       s4 oldsize;
-       s4 newsize;
-       s4 i;
-
-       /* table[0] serves as the head of the freelist */
-
-       index = threads_table.table[0].nextfree;
-
-       /* if we got a free index, use it */
-
-       if (index) {
-got_an_index:
-               threads_table.table[0].nextfree = threads_table.table[index].nextfree;
-               threads_table.table[index].thread = thread;
-               thread->index = index;
-               thread->thinlock = lock_pre_compute_thinlock(index);
-               return index;
-       }
-
-       /* we must grow the table */
-
-       oldsize = threads_table.size;
-       newsize = oldsize * 2;
-
-       threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
-                                                                  oldsize, newsize);
-       threads_table.size = newsize;
+       if (pthread_attr_init(&attr) != 0)
+               vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
 
-       /* link the new entries to a free list */
+       if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+               vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
+                                strerror(errno));
 
-       for (i=oldsize; i<newsize; ++i) {
-               threads_table.table[i].nextfree = i+1;
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Starting thread ");
+               threads_thread_print_info(mainthread);
+               printf("]\n");
        }
+#endif
 
-       /* terminate the freelist */
-
-       threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
-
-       /* use the first of the new entries */
-
-       index = oldsize;
-       goto got_an_index;
-}
-
-
-/* threads_table_remove *******************************************************
-
-   Remove a thread from the global threads table.
-
-   IN:
-      thread............the thread to remove
-
-   PRE-CONDITION:
-      The caller must hold the threadlistlock!
-
-******************************************************************************/
-
-static void threads_table_remove(threadobject *thread)
-{
-       s4 index;
-
-       index = thread->index;
-
-       /* put the index into the freelist */
-
-       threads_table.table[index] = threads_table.table[0];
-       threads_table.table[0].nextfree = index;
+       /* everything's ok */
 
-       /* delete the index in the threadobject to discover bugs */
-#if !defined(NDEBUG)
-       thread->index = 0;
-#endif
+       return true;
 }
 
 
@@ -995,14 +980,14 @@ static void threads_table_remove(threadobject *thread)
                 threads_startup.
 
    IN:
-      t............the argument passed to pthread_create, ie. a pointer to
+      arg..........the argument passed to pthread_create, ie. a pointer to
                       a startupinfo struct. CAUTION: When the `psem` semaphore
                                   is posted, the startupinfo struct becomes invalid! (It
                                   is allocated on the stack of threads_start_thread.)
 
 ******************************************************************************/
 
-static void *threads_startup_thread(void *t)
+static void *threads_startup_thread(void *arg)
 {
        startupinfo        *startup;
        threadobject       *thread;
@@ -1010,10 +995,9 @@ static void *threads_startup_thread(void *t)
        java_lang_VMThread *vmt;
 #endif
        sem_t              *psem;
-       threadobject       *tnext;
        classinfo          *c;
        methodinfo         *m;
-       java_objectheader  *o;
+       java_handle_t      *o;
        functionptr         function;
 
 #if defined(ENABLE_INTRP)
@@ -1031,41 +1015,33 @@ static void *threads_startup_thread(void *t)
 
        /* get passed startupinfo structure and the values in there */
 
-       startup = t;
-       t = NULL; /* make sure it's not used wrongly */
+       startup = arg;
 
        thread   = startup->thread;
        function = startup->function;
        psem     = startup->psem;
 
-       /* Seems like we've encountered a situation where thread->tid was not set by
-        * pthread_create. We alleviate this problem by waiting for pthread_create
-        * to return. */
-       threads_sem_wait(startup->psem_first);
+       /* Seems like we've encountered a situation where thread->tid was
+          not set by pthread_create. We alleviate this problem by waiting
+          for pthread_create to return. */
 
-       /* set the thread object */
+       threads_sem_wait(startup->psem_first);
 
 #if defined(__DARWIN__)
        thread->mach_thread = mach_thread_self();
 #endif
-       threads_set_current_threadobject(thread);
-
-       /* insert the thread into the threadlist and the threads table */
 
-       pthread_mutex_lock(&threadlistlock);
+       /* store the internal thread data-structure in the TSD */
 
-       thread->prev = mainthreadobj;
-       thread->next = tnext = mainthreadobj->next;
-       mainthreadobj->next = thread;
-       tnext->prev = thread;
+       threads_set_current_threadobject(thread);
 
-       threads_table_add(thread);
+       /* set our priority */
 
-       pthread_mutex_unlock(&threadlistlock);
+       threads_set_thread_priority(thread->tid, LLNI_field_direct(thread->object, priority));
 
-       /* init data structures of this thread */
+       /* thread is completely initialized */
 
-       lock_init_execution_env(thread);
+       threads_thread_state_runnable(thread);
 
        /* tell threads_startup_thread that we registered ourselves */
        /* CAUTION: *startup becomes invalid with this!             */
@@ -1073,10 +1049,6 @@ static void *threads_startup_thread(void *t)
        startup = NULL;
        threads_sem_post(psem);
 
-       /* set our priority */
-
-       threads_set_thread_priority(thread->tid, thread->o.priority);
-
 #if defined(ENABLE_INTRP)
        /* set interpreter stack */
 
@@ -1091,27 +1063,33 @@ static void *threads_startup_thread(void *t)
                jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
 #endif
 
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Starting thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
+       }
+#endif
+
        /* find and run the Thread.run()V method if no other function was passed */
 
        if (function == NULL) {
-               /* this is a normal Java thread */
-
-               thread->flags |= THREAD_FLAG_JAVA;
-
 #if defined(WITH_CLASSPATH_GNU)
                /* We need to start the run method of
                   java.lang.VMThread. Since this is a final class, we can use
                   the class object directly. */
 
-               c   = class_java_lang_VMThread;
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-               c   = thread->o.header.vftbl->class;
+               c = class_java_lang_VMThread;
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+               c = thread->object->header.vftbl->class;
+#else
+# error unknown classpath configuration
 #endif
 
                m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
 
                if (m == NULL)
-                       throw_exception();
+                       vm_abort("threads_startup_thread: run() method not found in class");
 
                /* set ThreadMXBean variables */
 
@@ -1126,20 +1104,20 @@ static void *threads_startup_thread(void *t)
 #if defined(WITH_CLASSPATH_GNU)
                /* we need to start the run method of java.lang.VMThread */
 
-               vmt = (java_lang_VMThread *) thread->o.vmThread;
-               o   = (java_objectheader *) vmt;
+               vmt = (java_lang_VMThread *) LLNI_field_direct(thread->object, vmThread);
+               o   = (java_handle_t *) vmt;
 
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-               o   = (java_objectheader *) thread;
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+               o   = (java_handle_t *) thread->object;
+#else
+# error unknown classpath configuration
 #endif
 
+               /* run the thread */
+
                (void) vm_call_method(m, o);
        }
        else {
-               /* this is an internal thread */
-
-               thread->flags |= THREAD_FLAG_INTERNAL;
-
                /* set ThreadMXBean variables */
 
                _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
@@ -1155,6 +1133,14 @@ static void *threads_startup_thread(void *t)
                (function)();
        }
 
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Stopping thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
+       }
+#endif
+
 #if defined(ENABLE_JVMTI)
        /* fire thread end event */
 
@@ -1162,7 +1148,9 @@ static void *threads_startup_thread(void *t)
                jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
 #endif
 
-       threads_detach_thread(thread);
+       /* We ignore the return value. */
+
+       (void) threads_detach_thread(thread);
 
        /* set ThreadMXBean variables */
 
@@ -1172,49 +1160,68 @@ static void *threads_startup_thread(void *t)
 }
 
 
-/* threads_start_thread ********************************************************
+/* threads_impl_thread_start ***************************************************
 
-   Start a thread in the JVM.
+   Start a thread in the JVM.  Both (vm internal and java) thread
+   objects exist.
 
    IN:
-      thread.......the thread object
-         function.....function to run in the new thread. NULL means that the
-                      "run" method of the object `t` should be called
+      thread....the thread object
+         f.........function to run in the new thread. NULL means that the
+                   "run" method of the object `t` should be called
 
 ******************************************************************************/
 
-void threads_start_thread(threadobject *thread, functionptr function)
+void threads_impl_thread_start(threadobject *thread, functionptr f)
 {
        sem_t          sem;
        sem_t          sem_first;
        pthread_attr_t attr;
        startupinfo    startup;
+       int            ret;
 
        /* fill startupinfo structure passed by pthread_create to
         * threads_startup_thread */
 
        startup.thread     = thread;
-       startup.function   = function;       /* maybe we don't call Thread.run()V */
+       startup.function   = f;              /* maybe we don't call Thread.run()V */
        startup.psem       = &sem;
        startup.psem_first = &sem_first;
 
        threads_sem_init(&sem, 0, 0);
        threads_sem_init(&sem_first, 0, 0);
 
-       /* initialize thread attribute object */
+       /* initialize thread attributes */
+
+       if (pthread_attr_init(&attr) != 0)
+               vm_abort("threads_impl_thread_start: pthread_attr_init failed: %s",
+                                strerror(errno));
 
-       if (pthread_attr_init(&attr))
-               vm_abort("pthread_attr_init failed: %s", strerror(errno));
+    if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+               vm_abort("threads_impl_thread_start: pthread_attr_setdetachstate failed: %s",
+                                strerror(errno));
 
        /* initialize thread stacksize */
 
        if (pthread_attr_setstacksize(&attr, opt_stacksize))
-               vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
+               vm_abort("threads_impl_thread_start: pthread_attr_setstacksize failed: %s",
+                                strerror(errno));
 
        /* create the thread */
 
-       if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
-               vm_abort("pthread_create failed: %s", strerror(errno));
+       ret = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
+
+       /* destroy the thread attributes */
+
+       if (pthread_attr_destroy(&attr) != 0)
+               vm_abort("threads_impl_thread_start: pthread_attr_destroy failed: %s",
+                                strerror(errno));
+
+       /* check for pthread_create error */
+
+       if (ret != 0)
+               vm_abort("threads_impl_thread_start: pthread_create failed: %s",
+                                strerror(errno));
 
        /* signal that pthread_create has returned, so thread->tid is valid */
 
@@ -1246,14 +1253,6 @@ void threads_set_thread_priority(pthread_t tid, int priority)
        struct sched_param schedp;
        int policy;
 
-#if defined(ENABLE_JAVAME_CLDC1_1)
-       /* The thread id is zero when a thread is created in Java.  The
-          priority is set later during startup. */
-
-       if (tid == NULL)
-               return;
-#endif
-
        pthread_getschedparam(tid, &policy, &schedp);
        schedp.sched_priority = priority;
        pthread_setschedparam(tid, policy, &schedp);
@@ -1270,12 +1269,14 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 {
        threadobject          *thread;
        utf                   *u;
-       java_lang_String      *s;
-       java_objectheader     *o;
+       java_handle_t         *s;
+       java_handle_t         *o;
        java_lang_Thread      *t;
 
 #if defined(ENABLE_JAVASE)
        java_lang_ThreadGroup *group;
+       threadobject          *mainthread;
+       classinfo             *c;
        methodinfo            *m;
 #endif
 
@@ -1283,40 +1284,49 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        java_lang_VMThread    *vmt;
 #endif
 
-       /* create a java.lang.Thread object */
+       /* Enter the join-mutex, so if the main-thread is currently
+          waiting to join all threads, the number of non-daemon threads
+          is correct. */
 
-       thread = (threadobject *) builtin_new(class_java_lang_Thread);
+       threads_mutex_join_lock();
 
-       if (thread == NULL)
-               return false;
+       /* create internal thread data-structure */
 
-       /* cast for convenience */
+       thread = threads_thread_new();
 
-       t = (java_lang_Thread *) thread;
+       /* thread is a Java thread and running */
 
-       threads_init_threadobject(thread);
-       threads_set_current_threadobject(thread);
-       lock_init_execution_env(thread);
+       thread->flags = THREAD_FLAG_JAVA;
 
-       /* insert the thread into the threadlist and the threads table */
+       if (isdaemon)
+               thread->flags |= THREAD_FLAG_DAEMON;
 
-       pthread_mutex_lock(&threadlistlock);
+       /* The thread is flagged and (non-)daemon thread, we can leave the
+          mutex. */
 
-       thread->prev        = mainthreadobj;
-       thread->next        = mainthreadobj->next;
-       mainthreadobj->next = thread;
-       thread->next->prev  = thread;
+       threads_mutex_join_unlock();
 
-       threads_table_add(thread);
+       /* create a java.lang.Thread object */
 
-       pthread_mutex_unlock(&threadlistlock);
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       /* mark thread as Java thread */
+       /* XXX memory leak!!! */
+       if (t == NULL)
+               return false;
 
-       thread->flags = THREAD_FLAG_JAVA;
+       thread->object = t;
 
-       if (isdaemon)
-               thread->flags |= THREAD_FLAG_DAEMON;
+       /* thread is completely initialized */
+
+       threads_thread_state_runnable(thread);
+
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Attaching thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
+       }
+#endif
 
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
@@ -1328,16 +1338,30 @@ 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);
 
+       /* XXX memory leak!!! */
        if (vmt == NULL)
                return false;
 
        /* set the thread */
 
-       vmt->thread = t;
+       LLNI_field_set_ref(vmt, thread, t);
+       LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+       vm_abort("threads_attach_current_thread: IMPLEMENT ME!");
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+
+       LLNI_field_set_val(t, vm_thread, (java_lang_Object *) thread);
+
+#else
+# error unknown classpath configuration
 #endif
 
        if (vm_aargs != NULL) {
@@ -1349,13 +1373,20 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        else {
                u     = utf_null;
 #if defined(ENABLE_JAVASE)
-               group = mainthreadobj->o.group;
+               /* get the main thread */
+
+               mainthread = threads_list_first();
+               group = LLNI_field_direct(mainthread->object, group);
 #endif
        }
 
+       /* the the thread name */
+
        s = javastring_new(u);
 
-       o = (java_objectheader *) thread;
+       /* for convenience */
+
+       o = (java_handle_t *) thread->object;
 
 #if defined(WITH_CLASSPATH_GNU)
        (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
@@ -1364,27 +1395,29 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        (void) vm_call_method(method_thread_init, o, s);
 #endif
 
-       if (*exceptionptr)
+       if (exceptions_get_exception())
                return false;
 
 #if defined(ENABLE_JAVASE)
        /* store the thread group in the object */
 
-       thread->o.group = group;
+       LLNI_field_direct(thread->object, group) = group;
 
        /* add thread to given thread-group */
 
-       m = class_resolveclassmethod(group->header.vftbl->class,
+       LLNI_class_get(group, c);
+
+       m = class_resolveclassmethod(c,
                                                                 utf_addThread,
                                                                 utf_java_lang_Thread__V,
                                                                 class_java_lang_ThreadGroup,
                                                                 true);
 
-       o = (java_objectheader *) group;
+       o = (java_handle_t *) group;
 
        (void) vm_call_method(m, o, t);
 
-       if (*exceptionptr)
+       if (exceptions_get_exception())
                return false;
 #endif
 
@@ -1398,100 +1431,130 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
 *******************************************************************************/
 
-bool threads_detach_thread(threadobject *thread)
+bool threads_detach_thread(threadobject *t)
 {
 #if defined(ENABLE_JAVASE)
+       java_lang_Thread      *object;
        java_lang_ThreadGroup *group;
+       java_handle_t         *e;
+       java_lang_Object      *handler;
+       classinfo             *c;
        methodinfo            *m;
-       java_objectheader     *o;
-       java_lang_Thread      *t;
+       java_handle_t         *o;
 #endif
 
-       /* Allow lock record pools to be used by other threads. They
-          cannot be deleted so we'd better not waste them. */
+#if defined(ENABLE_JAVASE)
+       object = t->object;
 
-       /* XXX We have to find a new way to free lock records */
-       /*     with the new locking algorithm.                */
-       /* lock_record_free_pools(thread->ee.lockrecordpools); */
+       group = LLNI_field_direct(object, group);
 
-       /* XXX implement uncaught exception stuff (like JamVM does) */
+    /* If there's an uncaught exception, call uncaughtException on the
+       thread's exception handler, or the thread's group if this is
+       unset. */
 
-#if defined(ENABLE_JAVASE)
-       /* remove thread from the thread group */
+       e = exceptions_get_and_clear_exception();
 
-       group = thread->o.group;
+    if (e != NULL) {
+               /* We use a java_lang_Object here, as it's not trivial to
+                  build the java_lang_Thread_UncaughtExceptionHandler header
+                  file. */
+
+# if defined(WITH_CLASSPATH_GNU)
+               handler = (java_lang_Object *) LLNI_field_direct(object, exceptionHandler);
+# elif defined(WITH_CLASSPATH_SUN)
+               handler = (java_lang_Object *) LLNI_field_direct(object, uncaughtExceptionHandler);
+# endif
+
+               if (handler != NULL) {
+                       LLNI_class_get(handler, c);
+                       o = (java_handle_t *) handler;
+               }
+               else {
+                       LLNI_class_get(group, c);
+                       o = (java_handle_t *) group;
+               }
+
+               m = class_resolveclassmethod(c,
+                                                                        utf_uncaughtException,
+                                                                        utf_java_lang_Thread_java_lang_Throwable__V,
+                                                                        NULL,
+                                                                        true);
+
+               if (m == NULL)
+                       return false;
+
+               (void) vm_call_method(m, o, object, e);
+
+               if (exceptions_get_exception())
+                       return false;
+    }
 
        /* XXX TWISTI: should all threads be in a ThreadGroup? */
 
+       /* Remove thread from the thread group. */
+
        if (group != NULL) {
-               m = class_resolveclassmethod(group->header.vftbl->class,
+               LLNI_class_get(group, c);
+
+# if defined(WITH_CLASSPATH_GNU)
+               m = class_resolveclassmethod(c,
                                                                         utf_removeThread,
                                                                         utf_java_lang_Thread__V,
                                                                         class_java_lang_ThreadGroup,
                                                                         true);
+# elif defined(WITH_CLASSPATH_SUN)
+               m = class_resolveclassmethod(c,
+                                                                        utf_remove,
+                                                                        utf_java_lang_Thread__V,
+                                                                        class_java_lang_ThreadGroup,
+                                                                        true);
+# else
+#  error unknown classpath configuration
+# endif
 
                if (m == NULL)
                        return false;
 
-               o = (java_objectheader *) group;
-               t = (java_lang_Thread *) thread;
+               o = (java_handle_t *) group;
 
-               (void) vm_call_method(m, o, t);
+               (void) vm_call_method(m, o, object);
 
-               if (*exceptionptr)
+               if (exceptions_get_exception())
                        return false;
        }
 #endif
 
-       /* remove thread from thread list and threads table, do this
-          inside a lock */
+       /* thread is terminated */
 
-       pthread_mutex_lock(&threadlistlock);
+       threads_thread_state_terminated(t);
 
-       thread->next->prev = thread->prev;
-       thread->prev->next = thread->next;
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Detaching thread ");
+               threads_thread_print_info(t);
+               printf("]\n");
+       }
+#endif
 
-       threads_table_remove(thread);
+       /* Enter the join-mutex before calling threads_thread_free, so
+          threads_join_all_threads gets the correct number of non-daemon
+          threads. */
 
-       pthread_mutex_unlock(&threadlistlock);
+       threads_mutex_join_lock();
 
-       /* reset thread id (lock on joinmutex? TWISTI) */
+       /* free the vm internal thread object */
 
-       pthread_mutex_lock(&(thread->joinmutex));
-       thread->tid = 0;
-       pthread_mutex_unlock(&(thread->joinmutex));
+       threads_thread_free(t);
 
-       /* tell everyone that a thread has finished */
+       /* Signal that this thread has finished and leave the mutex. */
 
-       pthread_cond_broadcast(&(thread->joincond));
+       pthread_cond_signal(&cond_join);
+       threads_mutex_join_unlock();
 
        return true;
 }
 
 
-/* threads_find_non_daemon_thread **********************************************
-
-   Helper function used by threads_join_all_threads for finding
-   non-daemon threads that are still running.
-
-*******************************************************************************/
-
-/* At the end of the program, we wait for all running non-daemon
-   threads to die. */
-
-static threadobject *threads_find_non_daemon_thread(threadobject *thread)
-{
-       while (thread != mainthreadobj) {
-               if (!(thread->flags & THREAD_FLAG_DAEMON))
-                       return thread;
-
-               thread = thread->prev;
-       }
-
-       return NULL;
-}
-
-
 /* threads_join_all_threads ****************************************************
 
    Join all non-daemon threads.
@@ -1500,24 +1563,30 @@ static threadobject *threads_find_non_daemon_thread(threadobject *thread)
 
 void threads_join_all_threads(void)
 {
-       threadobject *thread;
+       threadobject *t;
 
-       pthread_mutex_lock(&threadlistlock);
+       /* get current thread */
 
-       while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
-               pthread_mutex_lock(&(thread->joinmutex));
+       t = THREADOBJECT;
 
-               pthread_mutex_unlock(&threadlistlock);
+       /* this thread is waiting for all non-daemon threads to exit */
 
-               while (thread->tid)
-                       pthread_cond_wait(&(thread->joincond), &(thread->joinmutex));
+       threads_thread_state_waiting(t);
 
-               pthread_mutex_unlock(&(thread->joinmutex));
+       /* enter join mutex */
 
-               pthread_mutex_lock(&threadlistlock);
-       }
+       threads_mutex_join_lock();
+
+       /* Wait for condition as long as we have non-daemon threads.  We
+          compare against 1 because the current (main thread) is also a
+          non-daemon thread. */
 
-       pthread_mutex_unlock(&threadlistlock);
+       while (threads_list_get_non_daemons() > 1)
+               pthread_cond_wait(&cond_join, &mutex_join);
+
+       /* leave join mutex */
+
+       threads_mutex_join_unlock();
 }
 
 
@@ -1613,14 +1682,23 @@ static bool threads_wait_with_timeout(threadobject *thread,
                while (!thread->interrupted && !thread->signaled
                           && threads_current_time_is_earlier_than(wakeupTime))
                {
+                       threads_thread_state_timed_waiting(thread);
+
                        pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
                                                                   wakeupTime);
+
+                       threads_thread_state_runnable(thread);
                }
        }
        else {
                /* no timeout */
-               while (!thread->interrupted && !thread->signaled)
+               while (!thread->interrupted && !thread->signaled) {
+                       threads_thread_state_waiting(thread);
+
                        pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
+
+                       threads_thread_state_runnable(thread);
+               }
        }
 
        /* check if we were interrupted */
@@ -1818,107 +1896,6 @@ void threads_yield(void)
 }
 
 
-/* threads_dump ****************************************************************
-
-   Dumps info for all threads running in the JVM. This function is
-   called when SIGQUIT (<ctrl>-\) is sent to CACAO.
-
-*******************************************************************************/
-
-void threads_dump(void)
-{
-       threadobject     *thread;
-       java_lang_Thread *t;
-       utf              *name;
-
-       thread = mainthreadobj;
-
-       /* XXX we should stop the world here */
-
-       printf("Full thread dump CACAO "VERSION":\n");
-
-       /* iterate over all started threads */
-
-       do {
-               /* get thread object */
-
-               t = (java_lang_Thread *) thread;
-
-               /* the thread may be currently in initalization, don't print it */
-
-               if (t != NULL) {
-                       /* get thread name */
-
-#if defined(ENABLE_JAVASE)
-                       name = javastring_toutf(t->name, false);
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-                       name = t->name;
-#endif
-
-                       printf("\n\"");
-                       utf_display_printable_ascii(name);
-                       printf("\" ");
-
-                       if (thread->flags & THREAD_FLAG_DAEMON)
-                               printf("daemon ");
-
-#if SIZEOF_VOID_P == 8
-                       printf("prio=%d tid=0x%016lx\n", t->priority, (long) thread->tid);
-#else
-                       printf("prio=%d tid=0x%08lx\n", t->priority, (long) thread->tid);
-#endif
-
-                       /* dump trace of thread */
-
-                       stacktrace_dump_trace(thread);
-               }
-
-               thread = thread->next;
-       } while ((thread != NULL) && (thread != mainthreadobj));
-}
-
-
-/* threads_table_dump *********************************************************
-
-   Dump the threads table for debugging purposes.
-
-   IN:
-      file..............stream to write to
-
-******************************************************************************/
-
-#if !defined(NDEBUG) && 0
-static void threads_table_dump(FILE *file)
-{
-       s4 i;
-       s4 size;
-       ptrint index;
-
-       pthread_mutex_lock(&threadlistlock);
-
-       size = threads_table.size;
-
-       fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
-
-       for (i=0; i<size; ++i) {
-               index = threads_table.table[i].nextfree;
-
-               fprintf(file, "%4d: ", i);
-
-               if (index < size) {
-                       fprintf(file, "free, nextfree = %d\n", (int) index);
-               }
-               else {
-                       fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
-               }
-       }
-
-       fprintf(file, "======== END OF THREADS TABLE ========\n");
-
-       pthread_mutex_unlock(&threadlistlock);
-}
-#endif
-
 /*
  * 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