Merged revisions 8299-8320 via svnmerge from
[cacao.git] / src / threads / native / threads.c
index ec7c2cd98ec62a35ca5a55e54c163b8eb64efe60..09985a6cfa7cdb90dcb39ba19070da5758e785b8 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/native/threads.c - native threads support
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Stefan Ring
-
-   Changes: Christian Thalinger
-                       Edwin Steiner
-
-   $Id: threads.c 4919 2006-05-15 12:23:13Z twisti $
+   $Id: threads.c 8321 2007-08-16 11:37:25Z michi $
 
 */
 
 # include "threads/native/generic-primitives.h"
 #endif
 
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "mm/memory.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "mm/cacao-gc/gc.h"
+#endif
+
+#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_Throwable.h"
 #include "native/include/java_lang_Thread.h"
-#include "native/include/java_lang_ThreadGroup.h"
-#include "native/include/java_lang_VMThread.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/include/java_lang_ThreadGroup.h"
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+# 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 "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
 #if !defined(__DARWIN__)
 # if defined(__LINUX__)
 #  define GC_LINUX_THREADS
 #  define GC_IRIX_THREADS
 # endif
 # include <semaphore.h>
-# include "boehm-gc/include/gc.h"
+# if defined(ENABLE_GC_BOEHM)
+#  include "mm/boehm-gc/include/gc.h"
+# endif
 #endif
 
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
 
 #if defined(__DARWIN__)
 /* Darwin has no working semaphore implementation.  This one is taken
@@ -172,8 +194,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 *****************************************************************
 
@@ -193,21 +213,14 @@ 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)
-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                                    */
 /* This is either a thread-local variable defined with __thread, or           */
@@ -218,18 +231,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_rec_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 1
+
 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
 /* being stopped                                                              */
 static volatile int stopworldwhere;
@@ -241,7 +257,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)
@@ -251,56 +267,6 @@ pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
 #endif
 
 
-/******************************************************************************/
-/* Recursive Mutex Implementation for Darwin                                  */
-/******************************************************************************/
-
-#if defined(MUTEXSIM)
-
-/* We need this for older MacOSX (10.1.x) */
-
-void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_init(&m->mutex, NULL);
-       m->count = 0;
-}
-
-void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_destroy(&m->mutex);
-}
-
-void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
-{
-       for (;;) {
-               if (!m->count)
-               {
-                       pthread_mutex_lock(&m->mutex);
-                       m->owner = pthread_self();
-                       m->count++;
-                       break;
-               }
-               else {
-                       if (m->owner != pthread_self()) {
-                               pthread_mutex_lock(&m->mutex);
-                       }
-                       else {
-                               m->count++;
-                               break;
-                       }
-               }
-       }
-}
-
-void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
-{
-       if (!--m->count)
-               pthread_mutex_unlock(&m->mutex);
-}
-
-#endif /* defined(MUTEXSIM) */
-
-
 /* threads_sem_init ************************************************************
  
    Initialize a semaphore. Checks against errors and interruptions.
@@ -324,9 +290,7 @@ void threads_sem_init(sem_t *sem, bool shared, int value)
                        return;
        } while (errno == EINTR);
 
-       fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
-                       errno, strerror(errno));
-       abort();
+       vm_abort("sem_init failed: %s", strerror(errno));
 }
 
 
@@ -354,9 +318,7 @@ void threads_sem_wait(sem_t *sem)
                        return;
        } while (errno == EINTR);
 
-       fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
-                       errno, strerror(errno));
-       abort();
+       vm_abort("sem_wait failed: %s", strerror(errno));
 }
 
 
@@ -381,54 +343,7 @@ void threads_sem_post(sem_t *sem)
        if (r == 0)
                return;
 
-       fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
-                       errno, strerror(errno));
-       abort();
-}
-
-
-/* threads_set_thread_priority *************************************************
-
-   Set the priority of the given thread.
-
-   IN:
-      tid..........thread id
-         priority.....priority to set
-
-******************************************************************************/
-
-static void threads_set_thread_priority(pthread_t tid, int priority)
-{
-       struct sched_param schedp;
-       int policy;
-
-       pthread_getschedparam(tid, &policy, &schedp);
-       schedp.sched_priority = priority;
-       pthread_setschedparam(tid, policy, &schedp);
-}
-
-
-/* compiler_lock ***************************************************************
-
-   Enter the compiler lock.
-
-******************************************************************************/
-
-void compiler_lock(void)
-{
-       pthread_mutex_lock_rec(&compiler_mutex);
-}
-
-
-/* compiler_unlock *************************************************************
-
-   Release the compiler lock.
-
-******************************************************************************/
-
-void compiler_unlock(void)
-{
-       pthread_mutex_unlock_rec(&compiler_mutex);
+       vm_abort("sem_post failed: %s", strerror(errno));
 }
 
 
@@ -445,7 +360,7 @@ void compiler_unlock(void)
 void lock_stopworld(int where)
 {
        pthread_mutex_lock(&stopworldlock);
-       stopworldwhere = where;
+/*     stopworldwhere = where; */
 }
 
 
@@ -457,34 +372,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 */
+
+               pthread_kill(t->tid, sig);
 
-       return count - 1;
+               /* increase threads count */
+
+               count++;
+       }
+
+       return count;
 }
 
 #else
@@ -497,34 +429,36 @@ static void threads_cast_darwinstop(void)
        do {
                if (tobj != self)
                {
-                       thread_state_flavor_t flavor = PPC_THREAD_STATE;
-                       mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
+                       thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
+                       mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
+#if defined(__I386__)
+                       i386_thread_state_t thread_state;
+#else
                        ppc_thread_state_t thread_state;
+#endif
                        mach_port_t thread = tobj->mach_thread;
                        kern_return_t r;
 
                        r = thread_suspend(thread);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_suspend failed");
-                               assert(0);
-                       }
-
-                       r = thread_get_state(thread, flavor,
-                               (natural_t*)&thread_state, &thread_state_count);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_get_state failed");
-                               assert(0);
-                       }
-
-                       thread_restartcriticalsection(&thread_state);
-
-                       r = thread_set_state(thread, flavor,
-                               (natural_t*)&thread_state, thread_state_count);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_set_state failed");
-                               assert(0);
-                       }
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_suspend failed");
+
+                       r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
+                                                                &thread_state_count);
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_get_state failed");
+
+                       md_critical_section_restart((ucontext_t *) &thread_state);
+
+                       r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
+                                                                thread_state_count);
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_set_state failed");
                }
+
                tobj = tobj->next;
        } while (tobj != mainthreadobj);
 }
@@ -541,11 +475,11 @@ static void threads_cast_darwinresume(void)
                        kern_return_t r;
 
                        r = thread_resume(thread);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_resume failed");
-                               assert(0);
-                       }
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_resume failed");
                }
+
                tobj = tobj->next;
        } while (tobj != mainthreadobj);
 }
@@ -560,45 +494,17 @@ static void threads_cast_irixresume(void)
        pthread_mutex_unlock(&suspend_ack_lock);
 }
 #endif
-
-void threads_cast_stopworld(void)
-{
-       int count, i;
-       lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
-       pthread_mutex_lock(&threadlistlock);
-#if defined(__DARWIN__)
-       threads_cast_darwinstop();
-#else
-       count = threads_cast_sendsignals(GC_signum1(), 0);
-       for (i=0; i<count; i++)
-               threads_sem_wait(&suspend_ack);
-#endif
-       pthread_mutex_unlock(&threadlistlock);
-}
-
-void threads_cast_startworld(void)
-{
-       pthread_mutex_lock(&threadlistlock);
-#if defined(__DARWIN__)
-       threads_cast_darwinresume();
-#elif defined(__MIPS__)
-       threads_cast_irixresume();
-#else
-       threads_cast_sendsignals(GC_signum2(), -1);
 #endif
-       pthread_mutex_unlock(&threadlistlock);
-       unlock_stopworld();
-}
 
-#if !defined(__DARWIN__)
-static void threads_sigsuspend_handler(ucontext_t *ctx)
+#if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
+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
@@ -608,8 +514,10 @@ static void threads_sigsuspend_handler(ucontext_t *ctx)
        threads_sem_post(&suspend_ack);
        pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
        pthread_mutex_unlock(&suspend_ack_lock);
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
 #else
-       threads_sem_post(&suspend_ack);
 
        sig = GC_signum2();
        sigfillset(&sigs);
@@ -617,377 +525,513 @@ static void threads_sigsuspend_handler(ucontext_t *ctx)
        sigsuspend(&sigs);
 #endif
 }
-
-/* This function is called from Boehm GC code. */
-
-int cacao_suspendhandler(ucontext_t *ctx)
-{
-       if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
-               return 0;
-
-       threads_sigsuspend_handler(ctx);
-       return 1;
-}
 #endif
 
+/* threads_stopworld ***********************************************************
 
-/* threads_set_current_threadobject ********************************************
-
-   Set the current thread object.
-   
-   IN:
-      thread.......the thread object to set
+   Stops the world from turning. All threads except the calling one
+   are suspended. The function returns as soon as all threads have
+   acknowledged their suspension.
 
 *******************************************************************************/
 
-#if !defined(ENABLE_JVMTI)
-static void threads_set_current_threadobject(threadobject *thread)
-#else
-void threads_set_current_threadobject(threadobject *thread)
-#endif
+#if !defined(DISABLE_GC)
+void threads_stopworld(void)
 {
-#if !defined(HAVE___THREAD)
-       pthread_setspecific(threads_current_threadobject_key, thread);
-#else
-       threads_current_threadobject = thread;
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+       threadobject *t;
+       threadobject *self;
+       bool result;
+       s4 count, i;
 #endif
-}
-
-
-/* threads_get_current_threadobject ********************************************
 
-   Return the threadobject of the current thread.
-   
-   RETURN VALUE:
-       the current threadobject * (an instance of java.lang.VMThread)
-
-*******************************************************************************/
-
-threadobject *threads_get_current_threadobject(void)
-{
-       return THREADOBJECT;
-}
+       lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
 
+       /* lock the threads lists */
 
-/* threads_preinit *************************************************************
+       threads_list_lock();
 
-   Do some early initialization of stuff required.
+#if defined(__DARWIN__)
+       threads_cast_darwinstop();
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
+#else
+       self = THREADOBJECT;
 
-*******************************************************************************/
+       count = 0;
 
-void threads_preinit(void)
-{
-#ifndef MUTEXSIM
-       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);
-#else
-       pthread_mutex_init_rec(&compiler_mutex);
-#endif
+       /* suspend all running threads */
+       for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
+               /* don't send the signal to ourself */
 
-       pthread_mutex_init(&threadlistlock, NULL);
-       pthread_mutex_init(&stopworldlock, NULL);
+               if (t == self)
+                       continue;
 
-       /* Allocate something so the garbage collector's signal handlers
-          are installed. */
-       heap_allocate(1, false, NULL);
+               /* don't send the signal to NEW threads (because they are not
+                  completely initialized) */
 
-       mainthreadobj = NEW(threadobject);
-       mainthreadobj->tid = pthread_self();
-       mainthreadobj->index = 1;
-       mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
-       
-#if !defined(HAVE___THREAD)
-       pthread_key_create(&threads_current_threadobject_key, NULL);
-#endif
-       threads_set_current_threadobject(mainthreadobj);
+               if (t->state == THREAD_STATE_NEW)
+                       continue;
 
-       threads_sem_init(&suspend_ack, 0, 0);
+               /* send the signal */
 
-       /* initialize the threads table */
+               result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
+               assert(result);
 
-       threads_table_init();
+               /* increase threads count */
 
-       /* initialize subsystems */
+               count++;
+       }
 
-       lock_init();
+       /* wait for all threads signaled to suspend */
+       for (i = 0; i < count; i++)
+               threads_sem_wait(&suspend_ack);
+#endif
 
-       critical_init();
+       /* ATTENTION: Don't unlock the threads-lists here so that
+          non-signaled NEW threads can't change their state and execute
+          code. */
 }
+#endif /* !defined(DISABLE_GC) */
 
 
-/* threads_init ****************************************************************
+/* threads_startworld **********************************************************
 
-   Initializes the threads required by the JVM: main, finalizer.
+   Starts the world again after it has previously been stopped. 
 
 *******************************************************************************/
 
-bool threads_init(u1 *stackbottom)
+#if !defined(DISABLE_GC)
+void threads_startworld(void)
 {
-       java_lang_String      *threadname;
-       java_lang_Thread      *mainthread;
-       java_lang_ThreadGroup *threadgroup;
-       threadobject          *tempthread;
-       methodinfo            *method;
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+       threadobject *t;
+       threadobject *self;
+       bool result;
+       s4 count, i;
+#endif
 
-       tempthread = mainthreadobj;
+#if defined(__DARWIN__)
+       threads_cast_darwinresume();
+#elif defined(__MIPS__)
+       threads_cast_irixresume();
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
+#else
+       self = THREADOBJECT;
 
-       /* XXX We have to find a new way to free lock records */
-       /*     with the new locking algorithm.                */
-       /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
+       count = 0;
 
-       /* 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. */
+       /* resume all thread we haltet */
+       for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
+               /* don't send the signal to ourself */
 
-       class_java_lang_VMThread->instancesize = sizeof(threadobject);
+               if (t == self)
+                       continue;
 
-       /* create a VMThread */
+               /* don't send the signal to NEW threads (because they are not
+                  completely initialized) */
 
-       mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
+               if (t->state == THREAD_STATE_NEW)
+                       continue;
 
-       if (!mainthreadobj)
-               return false;
+               /* send the signal */
 
-       FREE(tempthread, threadobject);
+               result = threads_resume_thread(t);
+               assert(result);
 
-       threads_init_threadobject(&mainthreadobj->o);
+               /* increase threads count */
 
-       threads_set_current_threadobject(mainthreadobj);
+               count++;
+       }
 
-       lock_init_execution_env(mainthreadobj);
+       /* wait for all threads signaled to suspend */
+       for (i = 0; i < count; i++)
+               threads_sem_wait(&suspend_ack);
 
-       mainthreadobj->next = mainthreadobj;
-       mainthreadobj->prev = mainthreadobj;
+#endif
 
-       threads_table_add(mainthreadobj);
+       /* unlock the threads lists */
 
-#if defined(ENABLE_INTRP)
-       /* create interpreter stack */
+       threads_list_unlock();
 
-       if (opt_intrp) {
-               MSET(intrp_main_stack, 0, u1, opt_stacksize);
-               mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
-       }
+       unlock_stopworld();
+}
 #endif
 
-       threadname = javastring_new(utf_new_char("main"));
 
-       /* allocate and init ThreadGroup */
+/* threads_set_current_threadobject ********************************************
 
-       threadgroup = (java_lang_ThreadGroup *)
-               native_new_and_init(class_java_lang_ThreadGroup);
+   Set the current thread object.
+   
+   IN:
+      thread.......the thread object to set
 
-       if (!threadgroup)
-               throw_exception_exit();
+*******************************************************************************/
 
-       /* create a Thread */
+void threads_set_current_threadobject(threadobject *thread)
+{
+#if !defined(HAVE___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
+}
 
-       mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       if (!mainthread)
-               throw_exception_exit();
+/* threads_impl_thread_new *****************************************************
 
-       mainthreadobj->o.thread = mainthread;
+   Initialize implementation fields of a threadobject.
 
-       /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+   IN:
+      t....the threadobject
 
-       method = class_resolveclassmethod(class_java_lang_Thread,
-                                                                         utf_init,
-                                                                         utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
-                                                                         class_java_lang_Thread,
-                                                                         true);
+*******************************************************************************/
 
-       if (!method)
-               return false;
+void threads_impl_thread_new(threadobject *t)
+{
+       /* get the pthread id */
 
-       (void) vm_call_method(method, (java_objectheader *) mainthread,
-                                                 mainthreadobj, threadname, 5, false);
+       t->tid = pthread_self();
 
-       if (*exceptionptr)
-               return false;
+       /* initialize the mutex and the condition */
 
-       mainthread->group = threadgroup;
+       pthread_mutex_init(&(t->waitmutex), NULL);
+       pthread_cond_init(&(t->waitcond), NULL);
+       pthread_mutex_init(&(t->suspendmutex), NULL);
+       pthread_cond_init(&(t->suspendcond), NULL);
 
-       /* add mainthread to ThreadGroup */
+#if defined(ENABLE_DEBUG_FILTER)
+       /* Initialize filter counters */
+       t->filterverbosecallctr[0] = 0;
+       t->filterverbosecallctr[1] = 0;
+#endif
 
-       method = class_resolveclassmethod(class_java_lang_ThreadGroup,
-                                                                         utf_new_char("addThread"),
-                                                                         utf_new_char("(Ljava/lang/Thread;)V"),
-                                                                         class_java_lang_ThreadGroup,
-                                                                         true);
+#if !defined(NDEBUG)
+       t->tracejavacallindent = 0;
+       t->tracejavacallcount = 0;
+#endif
+}
 
-       if (!method)
-               return false;
 
-       (void) vm_call_method(method, (java_objectheader *) threadgroup,
-                                                 mainthread);
+/* threads_impl_thread_free ****************************************************
 
-       if (*exceptionptr)
-               return false;
+   Cleanup thread stuff.
 
-       threads_set_thread_priority(pthread_self(), 5);
+   IN:
+      t....the threadobject
 
-       pthread_attr_init(&threadattr);
-       pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
+*******************************************************************************/
 
-       /* everything's ok */
+void threads_impl_thread_free(threadobject *t)
+{
+       /* destroy the mutex and the condition */
 
-       return true;
-}
+       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));
 
-/* threads_table_init *********************************************************
+       if (pthread_mutex_destroy(&(t->suspendmutex)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
+                                strerror(errno));
 
-   Initialize the global threads table.
+       if (pthread_cond_destroy(&(t->suspendcond)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
+                                strerror(errno));
+}
 
-******************************************************************************/
 
-static void threads_table_init(void)
-{
-       s4 size;
-       s4 i;
+/* threads_get_current_threadobject ********************************************
 
-       size = THREADS_INITIAL_TABLE_SIZE;
+   Return the threadobject of the current thread.
+   
+   RETURN VALUE:
+       the current threadobject *
 
-       threads_table.size = size;
-       threads_table.table = MNEW(threads_table_entry_t, size);
+*******************************************************************************/
 
-       /* link the entries in a freelist */
+threadobject *threads_get_current_threadobject(void)
+{
+       return THREADOBJECT;
+}
 
-       for (i=0; i<size; ++i) {
-               threads_table.table[i].nextfree = i+1;
-       }
 
-       /* terminate the freelist */
+/* threads_impl_preinit ********************************************************
 
-       threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
-}
+   Do some early initialization of stuff required.
 
+   ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
+   is called AFTER this function!
 
-/* 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.
+void threads_impl_preinit(void)
+{
+       pthread_mutex_init(&stopworldlock, NULL);
 
-   IN:
-      thread............the thread to add
+       /* initialize exit mutex and condition (on exit we join all
+          threads) */
 
-   RETURN VALUE:
-      The table index for the newly added thread. This value has also been
-         entered in the threadobject.
+       pthread_mutex_init(&mutex_join, NULL);
+       pthread_cond_init(&cond_join, NULL);
 
-   PRE-CONDITION:
-      The caller must hold the threadlistlock!
+       /* initialize the threads-list mutex */
 
-******************************************************************************/
+       pthread_mutex_init(&mutex_threads_list, NULL);
 
-static s4 threads_table_add(threadobject *thread)
-{
-       s4 index;
-       s4 oldsize;
-       s4 newsize;
-       s4 i;
+#if !defined(HAVE___THREAD)
+       pthread_key_create(&threads_current_threadobject_key, NULL);
+#endif
 
-       /* table[0] serves as the head of the freelist */
+       threads_sem_init(&suspend_ack, 0, 0);
+}
 
-       index = threads_table.table[0].nextfree;
 
-       /* if we got a free index, use it */
+/* threads_list_lock ***********************************************************
 
-       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;
-       }
+   Enter the threads table mutex.
 
-       /* we must grow the table */
+   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.
 
-       oldsize = threads_table.size;
-       newsize = oldsize * 2;
+*******************************************************************************/
 
-       threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
-                                                                  oldsize, newsize);
-       threads_table.size = newsize;
+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));
+}
 
-       /* link the new entries to a free list */
 
-       for (i=oldsize; i<newsize; ++i) {
-               threads_table.table[i].nextfree = i+1;
-       }
+/* 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));
+}
 
-       /* terminate the freelist */
 
-       threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
+/* threads_mutex_join_lock *****************************************************
 
-       /* use the first of the new entries */
+   Enter the join mutex.
 
-       index = oldsize;
-       goto got_an_index;
+*******************************************************************************/
+
+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_table_remove *******************************************************
+/* threads_mutex_join_unlock ***************************************************
 
-   Remove a thread from the global threads table.
+   Leave the join mutex.
 
-   IN:
-      thread............the thread to remove
+*******************************************************************************/
 
-   PRE-CONDITION:
-      The caller must hold the threadlistlock!
+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));
+}
 
-******************************************************************************/
 
-static void threads_table_remove(threadobject *thread)
+/* threads_init ****************************************************************
+
+   Initializes the threads required by the JVM: main, finalizer.
+
+*******************************************************************************/
+
+bool threads_init(void)
 {
-       s4 index;
+       threadobject     *mainthread;
+       java_handle_t    *threadname;
+       java_lang_Thread *t;
+       java_handle_t    *o;
 
-       index = thread->index;
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *threadgroup;
+       methodinfo            *m;
+#endif
 
-       /* put the index into the freelist */
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
 
-       threads_table.table[index] = threads_table.table[0];
-       threads_table.table[0].nextfree = index;
+       pthread_attr_t attr;
 
-       /* delete the index in the threadobject to discover bugs */
-#if !defined(NDEBUG)
-       thread->index = 0;
+       /* get methods we need in this file */
+
+#if defined(WITH_CLASSPATH_GNU)
+       method_thread_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);
+#else
+       method_thread_init =
+               class_resolveclassmethod(class_java_lang_Thread,
+                                                                utf_init,
+                                                                utf_new_char("(Ljava/lang/String;)V"),
+                                                                class_java_lang_Thread,
+                                                                true);
 #endif
-}
 
-/* threads_init_threadobject **************************************************
+       if (method_thread_init == NULL)
+               return false;
 
-   Initialize implementation fields of a java.lang.VMThread.
+       /* Get the main-thread (NOTE: The main threads is always the first
+          thread in the list). */
 
-   IN:
-      t............the java.lang.VMThread
+       mainthread = threads_list_first();
 
-******************************************************************************/
+#if defined(ENABLE_GC_CACAO)
+       /* register reference to java.lang.Thread with the GC */
 
-void threads_init_threadobject(java_lang_VMThread *t)
-{
-       threadobject *thread = (threadobject*) t;
+       gc_reference_register((java_objectheader **) &(mainthread->object));
+#endif
 
-       thread->tid = pthread_self();
+       /* create a java.lang.Thread for the main thread */
 
-       thread->index = 0;
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       /* TODO destroy all those things */
-       pthread_mutex_init(&(thread->joinmutex), NULL);
-       pthread_cond_init(&(thread->joincond), NULL);
+       if (t == NULL)
+               return false;
 
-       pthread_mutex_init(&(thread->waitmutex), NULL);
-       pthread_cond_init(&(thread->waitcond), NULL);
+       /* set the object in the internal data structure */
 
-       thread->interrupted = false;
-       thread->signaled = false;
-       thread->sleeping = false;
+       mainthread->object = t;
+
+#if defined(ENABLE_INTRP)
+       /* create interpreter stack */
+
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
+       }
+#endif
+
+       threadname = javastring_new(utf_new_char("main"));
+
+#if defined(ENABLE_JAVASE)
+       /* allocate and init ThreadGroup */
+
+       threadgroup = (java_lang_ThreadGroup *)
+               native_new_and_init(class_java_lang_ThreadGroup);
+
+       if (threadgroup == NULL)
+               return false;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread for the main thread */
+
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+
+       if (vmt == NULL)
+               return false;
+
+       /* set the thread */
+
+       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_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;
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+
+       /* set the thread */
+
+       t->vm_thread = (java_lang_Object *) mainthread;
+
+       /* call public Thread(String name) */
+
+       o = (java_handle_t *) t;
+
+       (void) vm_call_method(method_thread_init, o, threadname);
+#else
+# error unknown classpath configuration
+#endif
+
+       if (exceptions_get_exception())
+               return false;
+
+#if defined(ENABLE_JAVASE)
+       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,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
+
+       o = (java_handle_t *) threadgroup;
+
+       (void) vm_call_method(m, o, t);
+
+       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(&attr) != 0)
+               vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
+
+       if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+               vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
+                                strerror(errno));
+
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Starting thread ");
+               threads_thread_print_info(mainthread);
+               printf("]\n");
+       }
+#endif
+
+       /* everything's ok */
+
+       return true;
 }
 
 
@@ -995,26 +1039,33 @@ void threads_init_threadobject(java_lang_VMThread *t)
 
    Thread startup function called by pthread_create.
 
+   Thread which have a startup.function != NULL are marked as internal
+   threads. All other threads are threated as normal Java threads.
+
    NOTE: This function is not called directly by pthread_create. The Boehm GC
          inserts its own GC_start_routine in between, which then calls
                 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;
-       sem_t        *psem;
-       threadobject *tnext;
-       methodinfo   *method;
-       functionptr   function;
+       startupinfo        *startup;
+       threadobject       *thread;
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread *vmt;
+#endif
+       sem_t              *psem;
+       classinfo          *c;
+       methodinfo         *m;
+       java_handle_t      *o;
+       functionptr         function;
 
 #if defined(ENABLE_INTRP)
        u1 *intrp_thread_stack;
@@ -1022,50 +1073,42 @@ static void *threads_startup_thread(void *t)
        /* create interpreter stack */
 
        if (opt_intrp) {
-               intrp_thread_stack = (u1 *) alloca(opt_stacksize);
+               intrp_thread_stack = GCMNEW(u1, opt_stacksize);
                MSET(intrp_thread_stack, 0, u1, opt_stacksize);
-       } else {
-               intrp_thread_stack = NULL;
        }
+       else
+               intrp_thread_stack = NULL;
 #endif
 
        /* 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,108 +1116,178 @@ static void *threads_startup_thread(void *t)
        startup = NULL;
        threads_sem_post(psem);
 
-       /* set our priority */
-
-       threads_set_thread_priority(thread->tid, thread->o.thread->priority);
-
 #if defined(ENABLE_INTRP)
        /* set interpreter stack */
 
        if (opt_intrp)
-               thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
+#endif
+
+#if defined(ENABLE_JVMTI)
+       /* fire thread start event */
+
+       if (jvmti) 
+               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) {
-               method = class_resolveclassmethod(thread->o.header.vftbl->class,
-                                                                                 utf_run,
-                                                                                 utf_void__void,
-                                                                                 thread->o.header.vftbl->class,
-                                                                                 true);
+#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_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+               c = thread->object->header.vftbl->class;
+#else
+# error unknown classpath configuration
+#endif
 
-               if (!method)
-                       throw_exception();
+               m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
 
-               (void) vm_call_method(method, (java_objectheader *) thread);
+               if (m == NULL)
+                       vm_abort("threads_startup_thread: run() method not found in class");
 
-       }
-       else {
-               /* call passed function, e.g. finalizer_thread */
+               /* set ThreadMXBean variables */
 
-               (function)();
-       }
+               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+               _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+               if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+                               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
+
+#if defined(WITH_CLASSPATH_GNU)
+               /* we need to start the run method of java.lang.VMThread */
 
-       /* Allow lock record pools to be used by other threads. They
-          cannot be deleted so we'd better not waste them. */
+               vmt = (java_lang_VMThread *) LLNI_field_direct(thread->object, vmThread);
+               o   = (java_handle_t *) vmt;
 
-       /* XXX We have to find a new way to free lock records */
-       /*     with the new locking algorithm.                */
-       /* lock_record_free_pools(thread->ee.lockrecordpools); */
+#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 {
+               /* set ThreadMXBean variables */
+
+               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+               _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
 
-       /* remove thread from thread list and threads table, do this inside a lock */
+               if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+                               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
 
-       pthread_mutex_lock(&threadlistlock);
+               /* call passed function, e.g. finalizer_thread */
 
-       thread->next->prev = thread->prev;
-       thread->prev->next = thread->next;
+               (function)();
+       }
 
-       threads_table_remove(thread);
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Stopping thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
+       }
+#endif
 
-       pthread_mutex_unlock(&threadlistlock);
+#if defined(ENABLE_JVMTI)
+       /* fire thread end event */
 
-       /* reset thread id (lock on joinmutex? TWISTI) */
+       if (jvmti)
+               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
 
-       pthread_mutex_lock(&thread->joinmutex);
-       thread->tid = 0;
-       pthread_mutex_unlock(&thread->joinmutex);
+       if (!threads_detach_thread(thread))
+               vm_abort("threads_startup_thread: threads_detach_thread failed");
 
-       /* tell everyone that a thread has finished */
+       /* set ThreadMXBean variables */
 
-       pthread_cond_broadcast(&thread->joincond);
+       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
 
        return NULL;
 }
 
 
-/* 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:
-      t............the java.lang.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(java_lang_Thread *t, functionptr function)
+void threads_impl_thread_start(threadobject *thread, functionptr f)
 {
-       sem_t         sem;
-       sem_t         sem_first;
-       startupinfo   startup;
-       threadobject *thread;
-
-       thread = (threadobject *) t->vmThread;
+       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 attributes */
+
+       if (pthread_attr_init(&attr) != 0)
+               vm_abort("threads_impl_thread_start: 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("threads_impl_thread_start: pthread_attr_setstacksize failed: %s",
+                                strerror(errno));
+
        /* create the thread */
 
-       if (pthread_create(&thread->tid, &threadattr, threads_startup_thread,
-                                          &startup)) {
-               log_text("pthread_create failed");
-               assert(0);
-       }
+       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 */
 
@@ -1191,25 +1304,410 @@ void threads_start_thread(java_lang_Thread *t, functionptr function)
 }
 
 
-/* threads_find_non_daemon_thread **********************************************
+/* threads_set_thread_priority *************************************************
+
+   Set the priority of the given thread.
+
+   IN:
+      tid..........thread id
+         priority.....priority to set
+
+******************************************************************************/
+
+void threads_set_thread_priority(pthread_t tid, int priority)
+{
+       struct sched_param schedp;
+       int policy;
+
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
+}
+
+
+/* threads_attach_current_thread ***********************************************
 
-   Helper function used by threads_join_all_threads for finding non-daemon threads
-   that are still running.
+   Attaches the current thread to the VM.  Used in JNI.
 
 *******************************************************************************/
 
-/* At the end of the program, we wait for all running non-daemon threads to die
- */
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+       threadobject          *thread;
+       utf                   *u;
+       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
+
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
+
+       /* Enter the join-mutex, so if the main-thread is currently
+          waiting to join all threads, the number of non-daemon threads
+          is correct. */
+
+       threads_mutex_join_lock();
+
+       /* create internal thread data-structure */
+
+       thread = threads_thread_new();
 
-static threadobject *threads_find_non_daemon_thread(threadobject *thread)
+       /* thread is a Java thread and running */
+
+       thread->flags = THREAD_FLAG_JAVA;
+
+       if (isdaemon)
+               thread->flags |= THREAD_FLAG_DAEMON;
+
+       /* The thread is flagged and (non-)daemon thread, we can leave the
+          mutex. */
+
+       threads_mutex_join_unlock();
+
+       /* create a java.lang.Thread object */
+
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       /* XXX memory leak!!! */
+       if (t == NULL)
+               return false;
+
+       thread->object = t;
+
+       /* 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 */
+
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
+       }
+#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 */
+
+       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) {
+               u     = utf_new_char(vm_aargs->name);
+#if defined(ENABLE_JAVASE)
+               group = (java_lang_ThreadGroup *) vm_aargs->group;
+#endif
+       }
+       else {
+               u     = utf_null;
+#if defined(ENABLE_JAVASE)
+               /* get the main thread */
+
+               mainthread = threads_list_first();
+               group = LLNI_field_direct(mainthread->object, group);
+#endif
+       }
+
+       /* the the thread name */
+
+       s = javastring_new(u);
+
+       /* 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,
+                                                 isdaemon);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       (void) vm_call_method(method_thread_init, o, s);
+#endif
+
+       if (exceptions_get_exception())
+               return false;
+
+#if defined(ENABLE_JAVASE)
+       /* store the thread group in the object */
+
+       LLNI_field_direct(thread->object, group) = group;
+
+       /* add thread to given thread-group */
+
+       LLNI_class_get(group, c);
+
+       m = class_resolveclassmethod(c,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
+
+       o = (java_handle_t *) group;
+
+       (void) vm_call_method(m, o, t);
+
+       if (exceptions_get_exception())
+               return false;
+#endif
+
+       return true;
+}
+
+
+/* threads_detach_thread *******************************************************
+
+   Detaches the passed thread from the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_detach_thread(threadobject *thread)
+{
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       classinfo             *c;
+       methodinfo            *m;
+       java_handle_t         *o;
+       java_lang_Thread      *t;
+#endif
+
+       /* XXX implement uncaught exception stuff (like JamVM does) */
+
+#if defined(ENABLE_JAVASE)
+       /* remove thread from the thread group */
+
+       group = LLNI_field_direct(thread->object, group);
+
+       /* XXX TWISTI: should all threads be in a ThreadGroup? */
+
+       if (group != NULL) {
+               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_handle_t *) group;
+               t = thread->object;
+
+               (void) vm_call_method(m, o, t);
+
+               if (exceptions_get_exception())
+                       return false;
+       }
+#endif
+
+       /* thread is terminated */
+
+       threads_thread_state_terminated(thread);
+
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Detaching thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
+       }
+#endif
+
+       /* Enter the join-mutex before calling threads_thread_free, so
+          threads_join_all_threads gets the correct number of non-daemon
+          threads. */
+
+       threads_mutex_join_lock();
+
+       /* free the vm internal thread object */
+
+       threads_thread_free(thread);
+
+       /* Signal that this thread has finished and leave the mutex. */
+
+       pthread_cond_signal(&cond_join);
+       threads_mutex_join_unlock();
+
+       return true;
+}
+
+
+/* threads_suspend_thread ******************************************************
+
+   Suspend the passed thread. Execution stops until the thread
+   is explicitly resumend again.
+
+   IN:
+     reason.....Reason for suspending this thread.
+
+*******************************************************************************/
+
+bool threads_suspend_thread(threadobject *thread, s4 reason)
 {
-       while (thread != mainthreadobj) {
-               if (!thread->o.thread->daemon)
-                       return thread;
-               thread = thread->prev;
+       /* acquire the suspendmutex */
+       if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
+               vm_abort("threads_suspend_thread: pthread_mutex_lock failed: %s",
+                                strerror(errno));
+
+       if (thread->suspended) {
+               pthread_mutex_unlock(&(thread->suspendmutex));
+               return false;
        }
 
-       return NULL;
+       /* set the reason for the suspension */
+       thread->suspend_reason = reason;
+
+       /* send the suspend signal to the thread */
+       assert(thread != THREADOBJECT);
+       if (pthread_kill(thread->tid, SIGUSR1) != 0)
+               vm_abort("threads_suspend_thread: pthread_kill failed: %s",
+                                strerror(errno));
+
+       /* REMEMBER: do not release the suspendmutex, this is done
+          by the thread itself in threads_suspend_ack().  */
+
+       return true;
+}
+
+
+/* threads_suspend_ack *********************************************************
+
+   Acknowledges the suspension of the current thread.
+
+   IN:
+     pc.....The PC where the thread suspended its execution.
+     sp.....The SP before the thread suspended its execution.
+
+*******************************************************************************/
+
+void threads_suspend_ack(u1* pc, u1* sp)
+{
+       threadobject *thread;
+
+       thread = THREADOBJECT;
+
+       assert(thread->suspend_reason != 0);
+
+       /* TODO: remember dump memory size */
+
+#if defined(ENABLE_GC_CACAO)
+       /* inform the GC about the suspension */
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
+
+               /* check if the GC wants to leave the thread running */
+               if (!gc_suspend(thread, pc, sp)) {
+
+                       /* REMEMBER: we do not unlock the suspendmutex because the thread
+                          will suspend itself again at a later time */
+                       return;
+
+               }
+       }
+#endif
+
+       /* mark this thread as suspended and remember the PC */
+       thread->pc        = pc;
+       thread->suspended = true;
+
+       /* if we are stopping the world, we should send a global ack */
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+               threads_sem_post(&suspend_ack);
+       }
+
+       /* release the suspension mutex and wait till we are resumed */
+       /*printf("thread down %p\n", thread);*/
+       pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
+       /*printf("thread up %p\n", thread);*/
+
+       /* if we are stopping the world, we should send a global ack */
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+               threads_sem_post(&suspend_ack);
+       }
+
+       /* TODO: free dump memory */
+
+       /* release the suspendmutex */
+       if (pthread_mutex_unlock(&(thread->suspendmutex)) != 0)
+               vm_abort("threads_suspend_ack: pthread_mutex_unlock failed: %s",
+                                strerror(errno));
+}
+
+
+/* threads_resume_thread *******************************************************
+
+   Resumes the execution of the passed thread.
+
+*******************************************************************************/
+
+bool threads_resume_thread(threadobject *thread)
+{
+       /* acquire the suspendmutex */
+       if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
+               vm_abort("threads_resume_ack: pthread_mutex_unlock failed: %s",
+                                strerror(errno));
+
+       if (!thread->suspended) {
+               pthread_mutex_unlock(&(thread->suspendmutex));
+               return false;
+       }
+
+       thread->suspended = false;
+
+       /* tell everyone that the thread should resume */
+       assert(thread != THREADOBJECT);
+       pthread_cond_broadcast(&(thread->suspendcond));
+
+       /* release the suspendmutex */
+       pthread_mutex_unlock(&(thread->suspendmutex));
+
+       return true;
 }
 
 
@@ -1221,25 +1719,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) {
+       t = THREADOBJECT;
 
-               pthread_mutex_lock(&thread->joinmutex);
+       /* this thread is waiting for all non-daemon threads to exit */
 
-               pthread_mutex_unlock(&threadlistlock);
+       threads_thread_state_waiting(t);
 
-               while (thread->tid)
-                       pthread_cond_wait(&thread->joincond, &thread->joinmutex);
+       /* enter join mutex */
 
-               pthread_mutex_unlock(&thread->joinmutex);
+       threads_mutex_join_lock();
 
-               pthread_mutex_lock(&threadlistlock);
-       }
+       /* 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();
 }
 
 
@@ -1284,11 +1787,8 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
        /* get current time */
 
-       if (gettimeofday(&tvnow, NULL) != 0) {
-               fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
-                               errno, strerror(errno));
-               abort();
-       }
+       if (gettimeofday(&tvnow, NULL) != 0)
+               vm_abort("gettimeofday failed: %s\n", strerror(errno));
 
        /* convert it to a timespec */
 
@@ -1318,48 +1818,58 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
 *******************************************************************************/
 
-static bool threads_wait_with_timeout(threadobject *t,
+static bool threads_wait_with_timeout(threadobject *thread,
                                                                          struct timespec *wakeupTime)
 {
        bool wasinterrupted;
 
        /* acquire the waitmutex */
 
-       pthread_mutex_lock(&t->waitmutex);
+       pthread_mutex_lock(&thread->waitmutex);
 
        /* mark us as sleeping */
 
-       t->sleeping = true;
+       thread->sleeping = true;
 
        /* wait on waitcond */
 
        if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
                /* with timeout */
-               while (!t->interrupted && !t->signaled
+               while (!thread->interrupted && !thread->signaled
                           && threads_current_time_is_earlier_than(wakeupTime))
                {
-                       pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
+                       threads_thread_state_timed_waiting(thread);
+
+                       pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
+                                                                  wakeupTime);
+
+                       threads_thread_state_runnable(thread);
                }
        }
        else {
                /* no timeout */
-               while (!t->interrupted && !t->signaled)
-                       pthread_cond_wait(&t->waitcond, &t->waitmutex);
+               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 */
 
-       wasinterrupted = t->interrupted;
+       wasinterrupted = thread->interrupted;
 
        /* reset all flags */
 
-       t->interrupted = false;
-       t->signaled = false;
-       t->sleeping = false;
+       thread->interrupted = false;
+       thread->signaled    = false;
+       thread->sleeping    = false;
 
        /* release the waitmutex */
 
-       pthread_mutex_unlock(&t->waitmutex);
+       pthread_mutex_unlock(&thread->waitmutex);
 
        return wasinterrupted;
 }
@@ -1381,8 +1891,7 @@ static bool threads_wait_with_timeout(threadobject *t,
 
 *******************************************************************************/
 
-bool threads_wait_with_timeout_relative(threadobject *t,
-                                                                               s8 millis,
+bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
                                                                                s4 nanos)
 {
        struct timespec wakeupTime;
@@ -1393,7 +1902,7 @@ bool threads_wait_with_timeout_relative(threadobject *t,
 
        /* wait */
 
-       return threads_wait_with_timeout(t, &wakeupTime);
+       return threads_wait_with_timeout(thread, &wakeupTime);
 }
 
 
@@ -1429,7 +1938,7 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 }
 
 
-/* threads_interrupt_thread ****************************************************
+/* threads_thread_interrupt ****************************************************
 
    Interrupt the given thread.
 
@@ -1441,18 +1950,23 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 
 *******************************************************************************/
 
-void threads_interrupt_thread(java_lang_VMThread *thread)
+void threads_thread_interrupt(threadobject *thread)
 {
-       threadobject *t = (threadobject*) thread;
+       /* Signal the thread a "waitcond" and tell it that it has been
+          interrupted. */
+
+       pthread_mutex_lock(&thread->waitmutex);
 
-       /* signal the thread a "waitcond" and tell it that it has been */
-       /* interrupted                                                 */
+       /* Interrupt blocking system call using a signal. */
 
-       pthread_mutex_lock(&t->waitmutex);
-       if (t->sleeping)
-               pthread_cond_signal(&t->waitcond);
-       t->interrupted = true;
-       pthread_mutex_unlock(&t->waitmutex);
+       pthread_kill(thread->tid, SIGHUP);
+
+       if (thread->sleeping)
+               pthread_cond_signal(&thread->waitcond);
+
+       thread->interrupted = true;
+
+       pthread_mutex_unlock(&thread->waitmutex);
 }
 
 
@@ -1468,20 +1982,24 @@ void threads_interrupt_thread(java_lang_VMThread *thread)
 
 bool threads_check_if_interrupted_and_reset(void)
 {
-       threadobject *t;
+       threadobject *thread;
        bool intr;
 
-       t = (threadobject*) THREADOBJECT;
+       thread = THREADOBJECT;
+
+       /* get interrupted flag */
+
+       intr = thread->interrupted;
 
-       intr = t->interrupted;
+       /* reset interrupted flag */
 
-       t->interrupted = false;
+       thread->interrupted = false;
 
        return intr;
 }
 
 
-/* threads_thread_has_been_interrupted *********************************************************
+/* threads_thread_has_been_interrupted *****************************************
 
    Check if the given thread has been interrupted
 
@@ -1493,13 +2011,9 @@ bool threads_check_if_interrupted_and_reset(void)
 
 *******************************************************************************/
 
-bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
+bool threads_thread_has_been_interrupted(threadobject *thread)
 {
-       threadobject *t;
-
-       t = (threadobject*) thread;
-
-       return t->interrupted;
+       return thread->interrupted;
 }
 
 
@@ -1511,22 +2025,22 @@ bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
 
 void threads_sleep(s8 millis, s4 nanos)
 {
-       threadobject       *t;
-       struct timespec    wakeupTime;
-       bool               wasinterrupted;
+       threadobject    *thread;
+       struct timespec  wakeupTime;
+       bool             wasinterrupted;
 
-       t = (threadobject *) THREADOBJECT;
+       thread = THREADOBJECT;
 
        threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-       wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
+       wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
 
        if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+               exceptions_throw_interruptedexception();
 }
 
 
-/* threads_yield *****************************************************************
+/* threads_yield ***************************************************************
 
    Yield to the scheduler.
 
@@ -1538,127 +2052,6 @@ void threads_yield(void)
 }
 
 
-/* threads_java_lang_Thread_set_priority ***********************************************************
-
-   Set the priority for the given java.lang.Thread.
-
-   IN:
-      t............the java.lang.Thread
-         priority.....the priority
-
-*******************************************************************************/
-
-void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
-{
-       threadobject *thread;
-
-       thread = (threadobject*) t->vmThread;
-
-       threads_set_thread_priority(thread->tid, priority);
-}
-
-
-/* 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       *tobj;
-       java_lang_VMThread *vmt;
-       java_lang_Thread   *t;
-       utf                *name;
-
-       tobj = mainthreadobj;
-
-       printf("Full thread dump CACAO "VERSION":\n");
-
-       /* iterate over all started threads */
-
-       do {
-               /* get thread objects */
-
-               vmt = &tobj->o;
-               t   = vmt->thread;
-
-               /* the thread may be currently in initalization, don't print it */
-
-               if (t) {
-                       /* get thread name */
-
-                       name = javastring_toutf(t->name, false);
-
-                       printf("\n\"");
-                       utf_display_printable_ascii(name);
-                       printf("\" ");
-
-                       if (t->daemon)
-                               printf("daemon ");
-
-#if SIZEOF_VOID_P == 8
-                       printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
-#else
-                       printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
-#endif
-
-                       /* send SIGUSR1 to thread to print stacktrace */
-
-                       pthread_kill(tobj->tid, SIGUSR1);
-
-                       /* sleep this thread a bit, so the signal can reach the thread */
-
-                       threads_sleep(10, 0);
-               }
-
-               tobj = tobj->next;
-       } while (tobj && (tobj != mainthreadobj));
-}
-
-
-/* threads_table_dump *********************************************************
-
-   Dump the threads table for debugging purposes.
-
-   IN:
-      file..............stream to write to
-
-******************************************************************************/
-
-#if !defined(NDEBUG)
-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", 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