Merged revisions 8299-8320 via svnmerge from
[cacao.git] / src / threads / native / threads.c
index 13900d50ed4c8fad50d77024ba0b92a7e1da2df0..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 4728 2006-04-04 09:17:05Z twisti $
+   $Id: threads.c 8321 2007-08-16 11:37:25Z michi $
 
 */
 
 
 #include "config.h"
 
+/* XXX cleanup these includes */
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <errno.h>
 
 #include <pthread.h>
-#include <semaphore.h>
 
 #include "vm/types.h"
 
 #include "arch.h"
 
-#ifndef USE_MD_THREAD_STUFF
-#include "machine-instr.h"
+#if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
+# include "machine-instr.h"
 #else
-#include "threads/native/generic-primitives.h"
+# 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"
 
-#if !defined(__DARWIN__)
-#if defined(__LINUX__)
-#define GC_LINUX_THREADS
-#elif defined(__MIPS__)
-#define GC_IRIX_THREADS
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
 #endif
-#include "boehm-gc/include/gc.h"
+
+#if !defined(__DARWIN__)
+# if defined(__LINUX__)
+#  define GC_LINUX_THREADS
+# elif defined(__MIPS__)
+#  define GC_IRIX_THREADS
+# endif
+# include <semaphore.h>
+# if defined(ENABLE_GC_BOEHM)
+#  include "mm/boehm-gc/include/gc.h"
+# endif
 #endif
 
-#ifdef USE_MD_THREAD_STUFF
-pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
 #endif
 
-#ifdef MUTEXSIM
+#if defined(__DARWIN__)
+/* Darwin has no working semaphore implementation.  This one is taken
+   from Boehm-GC. */
 
-/* We need this for older MacOSX (10.1.x) */
+/*
+   This is a very simple semaphore implementation for darwin. It
+   is implemented in terms of pthreads calls so it isn't async signal
+   safe. This isn't a problem because signals aren't used to
+   suspend threads on darwin.
+*/
+   
+static int sem_init(sem_t *sem, int pshared, int value)
+{
+       if (pshared)
+               assert(0);
 
-typedef struct {
-       pthread_mutex_t mutex;
-       pthread_t owner;
-       int count;
-} pthread_mutex_rec_t;
+       sem->value = value;
+    
+       if (pthread_mutex_init(&sem->mutex, NULL) < 0)
+               return -1;
 
-static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_init(&m->mutex, NULL);
-       m->count = 0;
+       if (pthread_cond_init(&sem->cond, NULL) < 0)
+               return -1;
+
+       return 0;
 }
 
-static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
+static int sem_post(sem_t *sem)
 {
-       pthread_mutex_destroy(&m->mutex);
+       if (pthread_mutex_lock(&sem->mutex) < 0)
+               return -1;
+
+       sem->value++;
+
+       if (pthread_cond_signal(&sem->cond) < 0) {
+               pthread_mutex_unlock(&sem->mutex);
+               return -1;
+       }
+
+       if (pthread_mutex_unlock(&sem->mutex) < 0)
+               return -1;
+
+       return 0;
 }
 
-static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
+static int sem_wait(sem_t *sem)
 {
-       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;
-                       }
-               }
+       if (pthread_mutex_lock(&sem->mutex) < 0)
+               return -1;
+
+       while (sem->value == 0) {
+               pthread_cond_wait(&sem->cond, &sem->mutex);
        }
+
+       sem->value--;
+
+       if (pthread_mutex_unlock(&sem->mutex) < 0)
+               return -1;    
+
+       return 0;
 }
 
-static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
+static int sem_destroy(sem_t *sem)
 {
-       if (!--m->count)
-               pthread_mutex_unlock(&m->mutex);
+       if (pthread_cond_destroy(&sem->cond) < 0)
+               return -1;
+
+       if (pthread_mutex_destroy(&sem->mutex) < 0)
+               return -1;
+
+       return 0;
 }
+#endif /* defined(__DARWIN__) */
 
-#else /* MUTEXSIM */
 
-#define pthread_mutex_lock_rec pthread_mutex_lock
-#define pthread_mutex_unlock_rec pthread_mutex_unlock
-#define pthread_mutex_rec_t pthread_mutex_t
+/* internally used constants **************************************************/
 
-#endif /* MUTEXSIM */
+/* CAUTION: Do not change these values. Boehm GC code depends on them.        */
+#define STOPWORLD_FROM_GC               1
+#define STOPWORLD_FROM_CLASS_NUMBERING  2
 
-static void setPriority(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);
-}
+/* startupinfo *****************************************************************
 
+   Struct used to pass info from threads_start_thread to 
+   threads_startup_thread.
+
+******************************************************************************/
+
+typedef struct {
+       threadobject *thread;      /* threadobject for this thread             */
+       functionptr   function;    /* function to run in the new thread        */
+       sem_t        *psem;        /* signals when thread has been entered     */
+                                  /* in the thread list                       */
+       sem_t        *psem_first;  /* signals when pthread_create has returned */
+} startupinfo;
+
+
+/* prototypes *****************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
 
-static avl_tree *criticaltree;
-threadobject *mainthreadobj;
 
-#ifndef HAVE___THREAD
-pthread_key_t tkey_threadinfo;
+/******************************************************************************/
+/* GLOBAL VARIABLES                                                           */
+/******************************************************************************/
+
+static methodinfo *method_thread_init;
+
+/* the thread object of the current thread                                    */
+/* This is either a thread-local variable defined with __thread, or           */
+/* a thread-specific value stored with key threads_current_threadobject_key.  */
+#if defined(HAVE___THREAD)
+__thread threadobject *threads_current_threadobject;
 #else
-__thread threadobject *threadobj;
+pthread_key_t threads_current_threadobject_key;
 #endif
 
-static pthread_mutex_rec_t compiler_mutex;
+/* global mutex for the threads table */
+static pthread_mutex_t mutex_threads_list;
 
-void compiler_lock()
-{
-       pthread_mutex_lock_rec(&compiler_mutex);
-}
+/* global mutex for stop-the-world                                            */
+static pthread_mutex_t stopworldlock;
 
-void compiler_unlock()
-{
-       pthread_mutex_unlock_rec(&compiler_mutex);
-}
+/* global mutex and condition for joining threads on exit */
+static pthread_mutex_t mutex_join;
+static pthread_cond_t  cond_join;
 
-static s4 criticalcompare(const void *pa, const void *pb)
-{
-       const threadcritnode *na = pa;
-       const threadcritnode *nb = pb;
+/* XXX We disable that whole bunch of code until we have the exact-GC
+   running. */
 
-       if (na->mcodebegin < nb->mcodebegin)
-               return -1;
-       if (na->mcodebegin > nb->mcodebegin)
-               return 1;
-       return 0;
-}
+#if 1
 
+/* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
+/* being stopped                                                              */
+static volatile int stopworldwhere;
 
-static const threadcritnode *findcritical(u1 *mcodeptr)
-{
-    avl_node *n;
-    const threadcritnode *m;
-
-    n = criticaltree->root;
-       m = NULL;
-
-    if (!n)
-        return NULL;
-
-    for (;;) {
-        const threadcritnode *d = n->data;
-
-        if (mcodeptr == d->mcodebegin)
-            return d;
-
-        if (mcodeptr < d->mcodebegin) {
-            if (n->childs[0]) {
-                n = n->childs[0];
-                       }
-            else {
-                return m;
-                       }
-        } 
-               else {
-            if (n->childs[1]) {
-                m = n->data;
-                n = n->childs[1];
-            } 
-                       else {
-                return n->data;
-                       }
-        }
-    }
-}
+/* semaphore used for acknowleding thread suspension                          */
+static sem_t suspend_ack;
+#if defined(__MIPS__)
+static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
+#endif
+
+#endif /* 0 */
+
+/* mutexes used by the fake atomic instructions                               */
+#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
+pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
 
 
-void thread_registercritical(threadcritnode *n)
+/* threads_sem_init ************************************************************
+   Initialize a semaphore. Checks against errors and interruptions.
+
+   IN:
+       sem..............the semaphore to initialize
+          shared...........true if this semaphore will be shared between processes
+          value............the initial value for the semaphore
+   
+*******************************************************************************/
+
+void threads_sem_init(sem_t *sem, bool shared, int value)
 {
-       avl_insert(criticaltree, n);
+       int r;
+
+       assert(sem);
+
+       do {
+               r = sem_init(sem, shared, value);
+               if (r == 0)
+                       return;
+       } while (errno == EINTR);
+
+       vm_abort("sem_init failed: %s", strerror(errno));
 }
 
-u1 *thread_checkcritical(u1 *mcodeptr)
+
+/* threads_sem_wait ************************************************************
+   Wait for a semaphore, non-interruptible.
+
+   IMPORTANT: Always use this function instead of `sem_wait` directly, as
+              `sem_wait` may be interrupted by signals!
+  
+   IN:
+       sem..............the semaphore to wait on
+   
+*******************************************************************************/
+
+void threads_sem_wait(sem_t *sem)
 {
-       const threadcritnode *n = findcritical(mcodeptr);
-       return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
+       int r;
+
+       assert(sem);
+
+       do {
+               r = sem_wait(sem);
+               if (r == 0)
+                       return;
+       } while (errno == EINTR);
+
+       vm_abort("sem_wait failed: %s", strerror(errno));
 }
 
-static void thread_addstaticcritical()
+
+/* threads_sem_post ************************************************************
+   Increase the count of a semaphore. Checks for errors.
+
+   IN:
+       sem..............the semaphore to increase the count of
+   
+*******************************************************************************/
+
+void threads_sem_post(sem_t *sem)
 {
-       /* XXX TWISTI: this is just a quick hack */
-#if defined(ENABLE_JIT)
-       threadcritnode *n = &asm_criticalsections;
+       int r;
 
-       while (n->mcodebegin)
-               thread_registercritical(n++);
-#endif
+       assert(sem);
+
+       /* unlike sem_wait, sem_post is not interruptible */
+
+       r = sem_post(sem);
+       if (r == 0)
+               return;
+
+       vm_abort("sem_post failed: %s", strerror(errno));
 }
 
-static pthread_mutex_t threadlistlock;
 
-static pthread_mutex_t stopworldlock;
-volatile int stopworldwhere;
+/* lock_stopworld **************************************************************
 
-static sem_t suspend_ack;
-#if defined(__MIPS__)
-static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
-#endif
+   Enter the stopworld lock, specifying why the world shall be stopped.
+
+   IN:
+      where........ STOPWORLD_FROM_GC              (1) from within GC
+                    STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
+
+******************************************************************************/
 
-/*
- * where - 1 from within GC
-           2 class numbering
- */
 void lock_stopworld(int where)
 {
        pthread_mutex_lock(&stopworldlock);
-       stopworldwhere = where;
+/*     stopworldwhere = where; */
 }
 
-void unlock_stopworld()
+
+/* unlock_stopworld ************************************************************
+
+   Release the stopworld lock.
+
+******************************************************************************/
+
+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 cast_sendsignals(int sig, int count)
+static s4 threads_cast_sendsignals(s4 sig)
 {
-       /* Count threads */
-       threadobject *tobj = mainthreadobj;
-       nativethread *infoself = THREADINFO;
+       threadobject *t;
+       threadobject *self;
+       s4            count;
+
+       self = THREADOBJECT;
+
+       /* iterate over all started threads */
+
+       count = 0;
 
-       if (count == 0) {
-               do {
-                       count++;
-                       tobj = tobj->info.next;
-               } while (tobj != mainthreadobj);
+       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);
+
+               /* increase threads count */
+
+               count++;
        }
-       
-       do {
-               nativethread *info = &tobj->info;
-               if (info != infoself)
-                       pthread_kill(info->tid, sig);
-               tobj = tobj->info.next;
-       } while (tobj != mainthreadobj);
 
-       return count-1;
+       return count;
 }
 
 #else
 
-static void cast_darwinstop()
+static void threads_cast_darwinstop(void)
 {
        threadobject *tobj = mainthreadobj;
-       nativethread *infoself = THREADINFO;
+       threadobject *self = THREADOBJECT;
 
        do {
-               nativethread *info = &tobj->info;
-               if (info != infoself)
+               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;
-                       mach_port_t thread = info->mach_thread;
+#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->info.next;
+
+               tobj = tobj->next;
        } while (tobj != mainthreadobj);
 }
 
-static void cast_darwinresume()
+static void threads_cast_darwinresume(void)
 {
        threadobject *tobj = mainthreadobj;
-       nativethread *infoself = THREADINFO;
+       threadobject *self = THREADOBJECT;
 
        do {
-               nativethread *info = &tobj->info;
-               if (info != infoself)
+               if (tobj != self)
                {
-                       mach_port_t thread = info->mach_thread;
+                       mach_port_t thread = tobj->mach_thread;
                        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->info.next;
+
+               tobj = tobj->next;
        } while (tobj != mainthreadobj);
 }
 
 #endif
 
 #if defined(__MIPS__)
-static void cast_irixresume()
+static void threads_cast_irixresume(void)
 {
        pthread_mutex_lock(&suspend_ack_lock);
        pthread_cond_broadcast(&suspend_cond);
        pthread_mutex_unlock(&suspend_ack_lock);
 }
 #endif
-
-void cast_stopworld()
-{
-       int count, i;
-       lock_stopworld(2);
-       pthread_mutex_lock(&threadlistlock);
-#if defined(__DARWIN__)
-       cast_darwinstop();
-#else
-       count = cast_sendsignals(GC_signum1(), 0);
-       for (i=0; i<count; i++)
-               sem_wait(&suspend_ack);
-#endif
-       pthread_mutex_unlock(&threadlistlock);
-}
-
-void cast_startworld()
-{
-       pthread_mutex_lock(&threadlistlock);
-#if defined(__DARWIN__)
-       cast_darwinresume();
-#elif defined(__MIPS__)
-       cast_irixresume();
-#else
-       cast_sendsignals(GC_signum2(), -1);
 #endif
-       pthread_mutex_unlock(&threadlistlock);
-       unlock_stopworld();
-}
 
-#if !defined(__DARWIN__)
-static void 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
           (not POSIX async-safe). */
 #if defined(__IRIX__)
        pthread_mutex_lock(&suspend_ack_lock);
-       sem_post(&suspend_ack);
+       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
-       sem_post(&suspend_ack);
 
        sig = GC_signum2();
        sigfillset(&sigs);
@@ -440,264 +525,547 @@ static void sigsuspend_handler(ucontext_t *ctx)
        sigsuspend(&sigs);
 #endif
 }
-
-int cacao_suspendhandler(ucontext_t *ctx)
-{
-       if (stopworldwhere != 2)
-               return 0;
-
-       sigsuspend_handler(ctx);
-       return 1;
-}
-#endif
-
-#if !defined(ENABLE_JVMTI)
-static void setthreadobject(threadobject *thread)
-#else
-void setthreadobject(threadobject *thread)
-#endif
-{
-#if !defined(HAVE___THREAD)
-       pthread_setspecific(tkey_threadinfo, thread);
-#else
-       threadobj = thread;
 #endif
-}
-
 
-/* thread_setself **************************************************************
+/* threads_stopworld ***********************************************************
 
-   XXX
+   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.
 
 *******************************************************************************/
 
-void *thread_getself(void)
+#if !defined(DISABLE_GC)
+void threads_stopworld(void)
 {
-       return THREADOBJECT;
-}
-
-
-static monitorLockRecord *dummyLR;
-
-static void initPools();
-
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+       threadobject *t;
+       threadobject *self;
+       bool result;
+       s4 count, i;
+#endif
 
-/* thread_preinit **************************************************************
+       lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
 
-   Do some early initialization of stuff required.
+       /* lock the threads lists */
 
-*******************************************************************************/
+       threads_list_lock();
 
-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);
+#if defined(__DARWIN__)
+       threads_cast_darwinstop();
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
 #else
-       pthread_mutex_init_rec(&compiler_mutex);
-#endif
+       self = THREADOBJECT;
 
-       pthread_mutex_init(&threadlistlock, NULL);
-       pthread_mutex_init(&stopworldlock, NULL);
+       count = 0;
 
-       /* Allocate something so the garbage collector's signal handlers
-          are installed. */
-       heap_allocate(1, false, NULL);
+       /* suspend all running threads */
+       for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
+               /* don't send the signal to ourself */
 
-       mainthreadobj = NEW(threadobject);
-       mainthreadobj->info.tid = pthread_self();
-#if !defined(HAVE___THREAD)
-       pthread_key_create(&tkey_threadinfo, NULL);
-#endif
-       setthreadobject(mainthreadobj);
-       initPools();
+               if (t == self)
+                       continue;
 
-       /* Every newly created object's monitorPtr points here so we save
-          a check against NULL */
+               /* don't send the signal to NEW threads (because they are not
+                  completely initialized) */
 
-       dummyLR = NEW(monitorLockRecord);
-       dummyLR->o = NULL;
-       dummyLR->ownerThread = NULL;
-       dummyLR->waiting = NULL;
-       dummyLR->incharge = dummyLR;
+               if (t->state == THREAD_STATE_NEW)
+                       continue;
 
-       /* we need a working dummyLR before initializing the critical
-          section tree */
+               /* send the signal */
 
-    criticaltree = avl_create(&criticalcompare);
+               result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
+               assert(result);
 
-       thread_addstaticcritical();
-       sem_init(&suspend_ack, 0, 0);
-}
+               /* increase threads count */
 
+               count++;
+       }
 
-static pthread_attr_t threadattr;
+       /* wait for all threads signaled to suspend */
+       for (i = 0; i < count; i++)
+               threads_sem_wait(&suspend_ack);
+#endif
 
-static void freeLockRecordPools(lockRecordPool *);
+       /* 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;
 
-       freeLockRecordPools(mainthreadobj->ee.lrpool);
+       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);
 
-       initThread(&mainthreadobj->o);
+               /* increase threads count */
 
-       setthreadobject(mainthreadobj);
+               count++;
+       }
 
-       initLocks();
+       /* wait for all threads signaled to suspend */
+       for (i = 0; i < count; i++)
+               threads_sem_wait(&suspend_ack);
 
-       mainthreadobj->info.next = mainthreadobj;
-       mainthreadobj->info.prev = mainthreadobj;
+#endif
 
-#if defined(ENABLE_INTRP)
-       /* create interpreter stack */
+       /* unlock the threads lists */
 
-       if (opt_intrp) {
-               MSET(intrp_main_stack, 0, u1, opt_stacksize);
-               mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
-       }
+       threads_list_unlock();
+
+       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();
+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
+}
 
-       /* create a Thread */
 
-       mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+/* threads_impl_thread_new *****************************************************
 
-       if (!mainthread)
-               throw_exception_exit();
+   Initialize implementation fields of a threadobject.
 
-       mainthreadobj->o.thread = mainthread;
+   IN:
+      t....the threadobject
 
-       /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+*******************************************************************************/
 
-       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);
+void threads_impl_thread_new(threadobject *t)
+{
+       /* get the pthread id */
 
-       if (!method)
-               return false;
+       t->tid = pthread_self();
 
-       (void) vm_call_method(method, (java_objectheader *) mainthread,
-                                                 mainthreadobj, threadname, 5, false);
+       /* initialize the mutex and the condition */
 
-       if (*exceptionptr)
-               return false;
+       pthread_mutex_init(&(t->waitmutex), NULL);
+       pthread_cond_init(&(t->waitcond), NULL);
+       pthread_mutex_init(&(t->suspendmutex), NULL);
+       pthread_cond_init(&(t->suspendcond), NULL);
 
-       mainthread->group = threadgroup;
+#if defined(ENABLE_DEBUG_FILTER)
+       /* Initialize filter counters */
+       t->filterverbosecallctr[0] = 0;
+       t->filterverbosecallctr[1] = 0;
+#endif
 
-       /* add mainthread to ThreadGroup */
+#if !defined(NDEBUG)
+       t->tracejavacallindent = 0;
+       t->tracejavacallcount = 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 (!method)
-               return false;
+/* threads_impl_thread_free ****************************************************
 
-       (void) vm_call_method(method, (java_objectheader *) threadgroup,
-                                                 mainthread);
+   Cleanup thread stuff.
 
-       if (*exceptionptr)
-               return false;
+   IN:
+      t....the threadobject
 
-       setPriority(pthread_self(), 5);
+*******************************************************************************/
 
-       pthread_attr_init(&threadattr);
-       pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
+void threads_impl_thread_free(threadobject *t)
+{
+       /* destroy the mutex and the condition */
 
-       /* everything's ok */
+       if (pthread_mutex_destroy(&(t->waitmutex)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
+                                strerror(errno));
 
-       return true;
-}
+       if (pthread_cond_destroy(&(t->waitcond)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
+                                strerror(errno));
 
+       if (pthread_mutex_destroy(&(t->suspendmutex)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
+                                strerror(errno));
 
-void initThread(java_lang_VMThread *t)
-{
-       threadobject *thread = (threadobject*) t;
-       nativethread *info = &thread->info;
-       info->tid = pthread_self();
-       /* TODO destroy all those things */
-       pthread_mutex_init(&info->joinMutex, NULL);
-       pthread_cond_init(&info->joinCond, NULL);
-
-       pthread_mutex_init(&thread->waitLock, NULL);
-       pthread_cond_init(&thread->waitCond, NULL);
-       thread->interrupted = false;
-       thread->signaled = false;
-       thread->isSleeping = false;
+       if (pthread_cond_destroy(&(t->suspendcond)) != 0)
+               vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
+                                strerror(errno));
 }
 
-static void initThreadLocks(threadobject *);
 
+/* threads_get_current_threadobject ********************************************
 
-typedef struct {
-       threadobject *thread;
-       functionptr   function;
-       sem_t        *psem;
-       sem_t        *psem_first;
-} startupinfo;
+   Return the threadobject of the current thread.
+   
+   RETURN VALUE:
+       the current threadobject *
+
+*******************************************************************************/
+
+threadobject *threads_get_current_threadobject(void)
+{
+       return THREADOBJECT;
+}
+
+
+/* threads_impl_preinit ********************************************************
+
+   Do some early initialization of stuff required.
+
+   ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
+   is called AFTER this function!
+
+*******************************************************************************/
+
+void threads_impl_preinit(void)
+{
+       pthread_mutex_init(&stopworldlock, NULL);
+
+       /* 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_sem_init(&suspend_ack, 0, 0);
+}
+
+
+/* threads_list_lock ***********************************************************
+
+   Enter the threads table mutex.
+
+   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.
+
+*******************************************************************************/
+
+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));
+}
+
+
+/* threads_init ****************************************************************
+
+   Initializes the threads required by the JVM: main, finalizer.
+
+*******************************************************************************/
+
+bool threads_init(void)
+{
+       threadobject     *mainthread;
+       java_handle_t    *threadname;
+       java_lang_Thread *t;
+       java_handle_t    *o;
+
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *threadgroup;
+       methodinfo            *m;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
+
+       pthread_attr_t attr;
+
+       /* 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
+
+       if (method_thread_init == NULL)
+               return false;
+
+       /* Get the main-thread (NOTE: The main threads is always the first
+          thread in the list). */
+
+       mainthread = threads_list_first();
+
+#if defined(ENABLE_GC_CACAO)
+       /* register reference to java.lang.Thread with the GC */
+
+       gc_reference_register((java_objectheader **) &(mainthread->object));
+#endif
+
+       /* create a java.lang.Thread for the main thread */
+
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       if (t == NULL)
+               return false;
+
+       /* set the object in the internal data structure */
+
+       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;
 
-/* threads_startup *************************************************************
+       (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;
+}
+
+
+/* threads_startup_thread ******************************************************
 
    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:
+      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;
-       nativethread *info;
-       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;
@@ -705,555 +1073,855 @@ 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;
+       startup = arg;
 
        thread   = startup->thread;
        function = startup->function;
        psem     = startup->psem;
 
-       info = &thread->info;
+       /* 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. */
 
-       /* Seems like we've encountered a situation where info->tid was not set by
-        * pthread_create. We alleviate this problem by waiting for pthread_create
-        * to return. */
-       sem_wait(startup->psem_first);
+       threads_sem_wait(startup->psem_first);
 
-       t = NULL;
 #if defined(__DARWIN__)
-       info->mach_thread = mach_thread_self();
+       thread->mach_thread = mach_thread_self();
 #endif
-       setthreadobject(thread);
 
-       /* insert the thread into the threadlist */
+       /* store the internal thread data-structure in the TSD */
 
-       pthread_mutex_lock(&threadlistlock);
+       threads_set_current_threadobject(thread);
 
-       info->prev = mainthreadobj;
-       info->next = tnext = mainthreadobj->info.next;
-       mainthreadobj->info.next = thread;
-       tnext->info.prev = thread;
+       /* set our priority */
 
-       pthread_mutex_unlock(&threadlistlock);
+       threads_set_thread_priority(thread->tid, LLNI_field_direct(thread->object, priority));
 
-       initThreadLocks(thread);
+       /* thread is completely initialized */
 
-       startup = NULL;
-       sem_post(psem);
+       threads_thread_state_runnable(thread);
+
+       /* tell threads_startup_thread that we registered ourselves */
+       /* CAUTION: *startup becomes invalid with this!             */
 
-       setPriority(info->tid, thread->o.thread->priority);
+       startup = NULL;
+       threads_sem_post(psem);
 
 #if defined(ENABLE_INTRP)
        /* set interpreter stack */
 
        if (opt_intrp)
-               THREADINFO->_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
+
+               m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
+
+               if (m == NULL)
+                       vm_abort("threads_startup_thread: run() method not found in class");
+
+               /* set ThreadMXBean variables */
 
-               if (!method)
-                       throw_exception();
+               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+               _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
 
-               (void) vm_call_method(method, (java_objectheader *) thread);
+               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 */
+
+               vmt = (java_lang_VMThread *) LLNI_field_direct(thread->object, vmThread);
+               o   = (java_handle_t *) vmt;
+
+#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++;
+
+               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;
+
                /* call passed function, e.g. finalizer_thread */
 
                (function)();
        }
 
-       /* Allow lock record pools to be used by other threads. They
-          cannot be deleted so we'd better not waste them. */
-
-       freeLockRecordPools(thread->ee.lrpool);
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Stopping thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
+       }
+#endif
 
-       /* remove thread from thread list, do this inside a lock */
+#if defined(ENABLE_JVMTI)
+       /* fire thread end event */
 
-       pthread_mutex_lock(&threadlistlock);
-       info->next->info.prev = info->prev;
-       info->prev->info.next = info->next;
-       pthread_mutex_unlock(&threadlistlock);
+       if (jvmti)
+               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
 
-       /* reset thread id (lock on joinMutex? TWISTI) */
+       if (!threads_detach_thread(thread))
+               vm_abort("threads_startup_thread: threads_detach_thread failed");
 
-       pthread_mutex_lock(&info->joinMutex);
-       info->tid = 0;
-       pthread_mutex_unlock(&info->joinMutex);
+       /* set ThreadMXBean variables */
 
-       pthread_cond_broadcast(&info->joinCond);
+       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
 
        return NULL;
 }
 
 
-/* threads_start_thread ********************************************************
+/* threads_impl_thread_start ***************************************************
+
+   Start a thread in the JVM.  Both (vm internal and java) thread
+   objects exist.
 
-   Start a thread in the JVM.
+   IN:
+      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(thread *t, functionptr function)
+void threads_impl_thread_start(threadobject *thread, functionptr f)
 {
-       nativethread *info;
-       sem_t         sem;
-       sem_t         sem_first;
-       startupinfo   startup;
+       sem_t          sem;
+       sem_t          sem_first;
+       pthread_attr_t attr;
+       startupinfo    startup;
+       int            ret;
 
-       info = &((threadobject *) t->vmThread)->info;
+       /* fill startupinfo structure passed by pthread_create to
+        * threads_startup_thread */
 
-       /* fill startupinfo structure passed by pthread_create to XXX */
-
-       startup.thread     = (threadobject*) t->vmThread;
-       startup.function   = function;       /* maybe we don't call Thread.run()V */
+       startup.thread     = thread;
+       startup.function   = f;              /* maybe we don't call Thread.run()V */
        startup.psem       = &sem;
        startup.psem_first = &sem_first;
 
-       sem_init(&sem, 0, 0);
-       sem_init(&sem_first, 0, 0);
-       
-       if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
-                                          &startup)) {
-               log_text("pthread_create failed");
-               assert(0);
-       }
+       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));
 
-       sem_post(&sem_first);
+       /* create the thread */
+
+       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 */
+
+       threads_sem_post(&sem_first);
 
        /* wait here until the thread has entered itself into the thread list */
 
-       sem_wait(&sem);
+       threads_sem_wait(&sem);
+
+       /* cleanup */
+
        sem_destroy(&sem);
        sem_destroy(&sem_first);
 }
 
 
-/* At the end of the program, we wait for all running non-daemon threads to die
- */
+/* threads_set_thread_priority *************************************************
+
+   Set the priority of the given thread.
+
+   IN:
+      tid..........thread id
+         priority.....priority to set
 
-static threadobject *findNonDaemon(threadobject *thread)
+******************************************************************************/
+
+void threads_set_thread_priority(pthread_t tid, int priority)
 {
-       while (thread != mainthreadobj) {
-               if (!thread->o.thread->daemon)
-                       return thread;
-               thread = thread->info.prev;
-       }
+       struct sched_param schedp;
+       int policy;
 
-       return NULL;
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
 }
 
-void joinAllThreads()
+
+/* threads_attach_current_thread ***********************************************
+
+   Attaches the current thread to the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 {
-       threadobject *thread;
-       pthread_mutex_lock(&threadlistlock);
-       while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
-               nativethread *info = &thread->info;
-               pthread_mutex_lock(&info->joinMutex);
-               pthread_mutex_unlock(&threadlistlock);
-               while (info->tid)
-                       pthread_cond_wait(&info->joinCond, &info->joinMutex);
-               pthread_mutex_unlock(&info->joinMutex);
-               pthread_mutex_lock(&threadlistlock);
+       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();
+
+       /* 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");
        }
-       pthread_mutex_unlock(&threadlistlock);
-}
+#endif
 
-static void initLockRecord(monitorLockRecord *r, threadobject *t)
-{
-       r->lockCount = 1;
-       r->ownerThread = t;
-       r->queuers = 0;
-       r->o = NULL;
-       r->waiter = NULL;
-       r->incharge = (monitorLockRecord *) &dummyLR;
-       r->waiting = NULL;
-       sem_init(&r->queueSem, 0, 0);
-       pthread_mutex_init(&r->resolveLock, NULL);
-       pthread_cond_init(&r->resolveWait, NULL);
-}
+#if defined(ENABLE_INTRP)
+       /* create interpreter stack */
 
-/* No lock record must ever be destroyed because there may still be references
- * to it.
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
+       }
+#endif
 
-static void destroyLockRecord(monitorLockRecord *r)
-{
-       sem_destroy(&r->queueSem);
-       pthread_mutex_destroy(&r->resolveLock);
-       pthread_cond_destroy(&r->resolveWait);
-}
-*/
+#if defined(WITH_CLASSPATH_GNU)
 
-void initLocks()
-{
-       initThreadLocks(mainthreadobj);
-}
+       /* create a java.lang.VMThread object */
 
-static void initThreadLocks(threadobject *thread)
-{
-       thread->ee.firstLR = NULL;
-       thread->ee.lrpool = NULL;
-       thread->ee.numlr = 0;
-}
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
-static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
-{
-       lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
-       int i;
+       /* 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!");
 
-       p->header.size = size;
-       for (i=0; i<size; i++) {
-               initLockRecord(&p->lr[i], thread);
-               p->lr[i].nextFree = &p->lr[i+1];
+#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
        }
-       p->lr[i-1].nextFree = NULL;
-       return p;
-}
+       else {
+               u     = utf_null;
+#if defined(ENABLE_JAVASE)
+               /* get the main thread */
 
-#define INITIALLOCKRECORDS 8
+               mainthread = threads_list_first();
+               group = LLNI_field_direct(mainthread->object, group);
+#endif
+       }
 
-pthread_mutex_t pool_lock;
-lockRecordPool *global_pool;
+       /* the the thread name */
 
-static void initPools()
-{
-       pthread_mutex_init(&pool_lock, NULL);
+       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;
 }
 
-static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
+
+/* threads_detach_thread *******************************************************
+
+   Detaches the passed thread from the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_detach_thread(threadobject *thread)
 {
-       pthread_mutex_lock(&pool_lock);
-       if (global_pool) {
-               int i;
-               lockRecordPool *pool = global_pool;
-               global_pool = pool->header.next;
-               pthread_mutex_unlock(&pool_lock);
-
-               for (i=0; i < pool->header.size; i++) {
-                       pool->lr[i].ownerThread = t;
-                       pool->lr[i].nextFree = &pool->lr[i+1];
-               }
-               pool->lr[i-1].nextFree = NULL;
-               
-               return pool;
+#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;
        }
-       pthread_mutex_unlock(&pool_lock);
+#endif
 
-       return allocNewLockRecordPool(t, size);
-}
+       /* thread is terminated */
 
-static void freeLockRecordPools(lockRecordPool *pool)
-{
-       lockRecordPoolHeader *last;
-       pthread_mutex_lock(&pool_lock);
-       last = &pool->header;
-       while (last->next)
-               last = &last->next->header;
-       last->next = global_pool;
-       global_pool = pool;
-       pthread_mutex_unlock(&pool_lock);
-}
+       threads_thread_state_terminated(thread);
 
-static monitorLockRecord *allocLockRecordSimple(threadobject *t)
-{
-       monitorLockRecord *r;
-
-       assert(t);
-       r = t->ee.firstLR;
-
-       if (!r) {
-               int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
-               lockRecordPool *pool = allocLockRecordPool(t, poolsize);
-               pool->header.next = t->ee.lrpool;
-               t->ee.lrpool = pool;
-               r = &pool->lr[0];
-               t->ee.numlr += pool->header.size;
+#if !defined(NDEBUG)
+       if (opt_verbosethreads) {
+               printf("[Detaching thread ");
+               threads_thread_print_info(thread);
+               printf("]\n");
        }
-       
-       t->ee.firstLR = r->nextFree;
-#ifndef NDEBUG
-       r->nextFree = NULL; /* in order to find invalid uses of nextFree */
 #endif
-       return r;
-}
 
-static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
-{
-       assert(t);
-       assert(r);
-       assert(r->ownerThread == t);
-       assert(r->nextFree == NULL);
-       
-       r->nextFree = t->ee.firstLR;
-       t->ee.firstLR = r;
-}
+       /* Enter the join-mutex before calling threads_thread_free, so
+          threads_join_all_threads gets the correct number of non-daemon
+          threads. */
 
-void initObjectLock(java_objectheader *o)
-{
-       assert(o);
+       threads_mutex_join_lock();
 
-       o->monitorPtr = dummyLR;
+       /* 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;
 }
 
 
-/* get_dummyLR *****************************************************************
+/* threads_suspend_thread ******************************************************
+
+   Suspend the passed thread. Execution stops until the thread
+   is explicitly resumend again.
 
-   Returns the global dummy monitor lock record. The pointer is
-   required in the code generator to set up a virtual
-   java_objectheader for code patch locking.
+   IN:
+     reason.....Reason for suspending this thread.
 
 *******************************************************************************/
 
-monitorLockRecord *get_dummyLR(void)
+bool threads_suspend_thread(threadobject *thread, s4 reason)
 {
-       return dummyLR;
-}
+       /* 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;
+       }
 
-static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
-{
-       atomic_add(&lr->queuers, 1);
+       /* set the reason for the suspension */
+       thread->suspend_reason = reason;
 
-       MEMORY_BARRIER_AFTER_ATOMIC();
+       /* 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));
 
-       if (lr->o == o)
-               sem_wait(&lr->queueSem);
+       /* REMEMBER: do not release the suspendmutex, this is done
+          by the thread itself in threads_suspend_ack().  */
 
-       atomic_add(&lr->queuers, -1);
+       return true;
 }
 
-static void freeLockRecord(monitorLockRecord *lr)
-{
-       int q;
-       lr->o = NULL;
-       MEMORY_BARRIER();
-       q = lr->queuers;
-       while (q--)
-               sem_post(&lr->queueSem);
-}
 
-static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr, java_objectheader *o)
-{
-       if (lr->waiting == o)
-               mlr->waiter = lr;
-}
+/* threads_suspend_ack *********************************************************
+
+   Acknowledges the suspension of the current thread.
 
-monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
+   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)
 {
-       for (;;) {
-               monitorLockRecord *lr = o->monitorPtr;
-               if (lr->o != o) {
-                       /* the lock record does not lock this object */
-                       monitorLockRecord *nlr;
-                       monitorLockRecord *mlr;
-                  
-                       /* allocate a new lock record for this object */
-                       mlr     = allocLockRecordSimple(t);
-                       mlr->o = o;
-
-                       /* check if it is the same record the object refered to earlier */
-                       if (mlr == lr) {
-                               MEMORY_BARRIER();
-                               nlr = o->monitorPtr;
-                               if (nlr == lr) {
-                                       /* the object still refers to the same lock record */
-                                       /* got it! */
-                                       handleWaiter(mlr, lr, o);
-                                       return mlr;
-                               }
-                       } 
-                       else {
-                               /* no, it's another lock record */
-                               /* if we don't own the old record, set incharge XXX */
-                               if (lr->ownerThread != t)
-                                       mlr->incharge = lr;
-
-                               /* if the object still refers to lr, replace it by the new mlr */
-                               MEMORY_BARRIER_BEFORE_ATOMIC();
-                               nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
-                       }
-
-                       if (nlr == lr) {
-                               /* we swapped the new record in successfully */
-                               if (mlr == lr || lr->o != o) {
-                                       /* the old lock record is the same as the new one, or */
-                                       /* it locks another object.                           */
-                                       /* got it! */
-                                       handleWaiter(mlr, lr, o);
-                                       return mlr;
-                               }
-                               /* lr locks the object, we have to wait */
-                               while (lr->o == o)
-                                       queueOnLockRecord(lr, o);
-
-                               /* got it! */
-                               handleWaiter(mlr, lr, o);
-                               return mlr;
-                       }
-
-                       /* forget this mlr lock record, wait on nlr and try again */
-                       freeLockRecord(mlr);
-                       recycleLockRecord(t, mlr);
-                       queueOnLockRecord(nlr, o);
-               } 
-               else {
-                       /* the lock record is for the object we want */
-
-                       if (lr->ownerThread == t) {
-                               /* we own it already, just recurse */
-                               lr->lockCount++;
-                               return lr;
-                       }
-
-                       /* it's locked. we wait and then try again */
-                       queueOnLockRecord(lr, o);
+       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
 
-static void wakeWaiters(monitorLockRecord *lr)
-{
-       monitorLockRecord *tmplr;
-       s4 q;
+       /* mark this thread as suspended and remember the PC */
+       thread->pc        = pc;
+       thread->suspended = true;
 
-       /* assign lock record to a temporary variable */
+       /* if we are stopping the world, we should send a global ack */
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+               threads_sem_post(&suspend_ack);
+       }
 
-       tmplr = lr;
+       /* 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);*/
 
-       do {
-               q = tmplr->queuers;
+       /* if we are stopping the world, we should send a global ack */
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+               threads_sem_post(&suspend_ack);
+       }
 
-               while (q--)
-                       sem_post(&tmplr->queueSem);
+       /* TODO: free dump memory */
 
-               tmplr = tmplr->waiter;
-       } while (tmplr != NULL && tmplr != lr);
+       /* release the suspendmutex */
+       if (pthread_mutex_unlock(&(thread->suspendmutex)) != 0)
+               vm_abort("threads_suspend_ack: pthread_mutex_unlock failed: %s",
+                                strerror(errno));
 }
 
-#define GRAB_LR(lr,t) \
-    if (lr->ownerThread != t) { \
-               lr = lr->incharge; \
-       }
 
-#define CHECK_MONITORSTATE(lr,t,mo,a) \
-    if (lr->o != mo || lr->ownerThread != t) { \
-               *exceptionptr = new_illegalmonitorstateexception(); \
-               a; \
-       }
+/* threads_resume_thread *******************************************************
+
+   Resumes the execution of the passed thread.
 
-bool monitorExit(threadobject *t, java_objectheader *o)
+*******************************************************************************/
+
+bool threads_resume_thread(threadobject *thread)
 {
-       monitorLockRecord *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return false);
-
-       if (lr->lockCount > 1) {
-               /* we had locked this one recursively. just decrement, it will */
-               /* still be locked. */
-               lr->lockCount--;
-               return true;
-       }
-       
-       if (lr->waiter) {
-               monitorLockRecord *wlr = lr->waiter;
-               if (o->monitorPtr != lr ||
-                       (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
-               {
-                       monitorLockRecord *nlr = o->monitorPtr;
-                       nlr->waiter = wlr;
-                       STORE_ORDER_BARRIER();
-               } 
-               else {
-                       wakeWaiters(wlr);
-               }
-               lr->waiter = NULL;
+       /* 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;
        }
 
-       /* unlock and throw away this lock record */
-       freeLockRecord(lr);
-       recycleLockRecord(t, lr);
+       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;
 }
 
-static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
+
+/* threads_join_all_threads ****************************************************
+
+   Join all non-daemon threads.
+
+*******************************************************************************/
+
+void threads_join_all_threads(void)
 {
-       do {
-               if (lr->waiter == wlr) {
-                       lr->waiter = wlr->waiter;
-                       break;
-               }
-               lr = lr->waiter;
-       } while (lr); /* XXX need to break cycle? */
+       threadobject *t;
+
+       /* get current thread */
+
+       t = THREADOBJECT;
+
+       /* this thread is waiting for all non-daemon threads to exit */
+
+       threads_thread_state_waiting(t);
+
+       /* enter join mutex */
+
+       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. */
+
+       while (threads_list_get_non_daemons() > 1)
+               pthread_cond_wait(&cond_join, &mutex_join);
+
+       /* leave join mutex */
+
+       threads_mutex_join_unlock();
 }
 
-static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
+
+/* threads_timespec_earlier ****************************************************
+
+   Return true if timespec tv1 is earlier than timespec tv2.
+
+   IN:
+      tv1..........first timespec
+         tv2..........second timespec
+
+   RETURN VALUE:
+      true, if the first timespec is earlier
+
+*******************************************************************************/
+
+static inline bool threads_timespec_earlier(const struct timespec *tv1,
+                                                                                       const struct timespec *tv2)
 {
-       return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
+       return (tv1->tv_sec < tv2->tv_sec)
+                               ||
+               (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
 }
 
-static bool timeIsEarlier(const struct timespec *tv)
+
+/* threads_current_time_is_earlier_than ****************************************
+
+   Check if the current time is earlier than the given timespec.
+
+   IN:
+      tv...........the timespec to compare against
+
+   RETURN VALUE:
+      true, if the current time is earlier
+
+*******************************************************************************/
+
+static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 {
        struct timeval tvnow;
        struct timespec tsnow;
-       gettimeofday(&tvnow, NULL);
+
+       /* get current time */
+
+       if (gettimeofday(&tvnow, NULL) != 0)
+               vm_abort("gettimeofday failed: %s\n", strerror(errno));
+
+       /* convert it to a timespec */
+
        tsnow.tv_sec = tvnow.tv_sec;
        tsnow.tv_nsec = tvnow.tv_usec * 1000;
-       return timespec_less(&tsnow, tv);
+
+       /* compare current time with the given timespec */
+
+       return threads_timespec_earlier(&tsnow, tv);
 }
 
 
-/* waitWithTimeout *************************************************************
+/* threads_wait_with_timeout ***************************************************
 
-   XXX
+   Wait until the given point in time on a monitor until either
+   we are notified, we are interrupted, or the time is up.
+
+   IN:
+      t............the current thread
+         wakeupTime...absolute (latest) wakeup time
+                          If both tv_sec and tv_nsec are zero, this function
+                                          waits for an unlimited amount of time.
+
+   RETURN VALUE:
+      true.........if the wait has been interrupted,
+         false........if the wait was ended by notification or timeout
 
 *******************************************************************************/
 
-static bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
+static bool threads_wait_with_timeout(threadobject *thread,
+                                                                         struct timespec *wakeupTime)
 {
        bool wasinterrupted;
 
-       pthread_mutex_lock(&t->waitLock);
+       /* acquire the waitmutex */
+
+       pthread_mutex_lock(&thread->waitmutex);
+
+       /* mark us as sleeping */
 
-       t->isSleeping = true;
+       thread->sleeping = true;
+
+       /* wait on waitcond */
 
        if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
-               while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
-                       pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
+               /* with timeout */
+               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 {
-               while (!t->interrupted && !t->signaled)
-                       pthread_cond_wait(&t->waitCond, &t->waitLock);
+               /* no timeout */
+               while (!thread->interrupted && !thread->signaled) {
+                       threads_thread_state_waiting(thread);
+
+                       pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
+
+                       threads_thread_state_runnable(thread);
+               }
        }
 
-       wasinterrupted = t->interrupted;
-       t->interrupted = false;
-       t->signaled = false;
-       t->isSleeping = false;
+       /* check if we were interrupted */
 
-       pthread_mutex_unlock(&t->waitLock);
+       wasinterrupted = thread->interrupted;
+
+       /* reset all flags */
+
+       thread->interrupted = false;
+       thread->signaled    = false;
+       thread->sleeping    = false;
+
+       /* release the waitmutex */
+
+       pthread_mutex_unlock(&thread->waitmutex);
 
        return wasinterrupted;
 }
 
 
-static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
+/* threads_wait_with_timeout_relative ******************************************
+
+   Wait for the given maximum amount of time on a monitor until either
+   we are notified, we are interrupted, or the time is up.
+
+   IN:
+      t............the current thread
+         millis.......milliseconds to wait
+         nanos........nanoseconds to wait
+
+   RETURN VALUE:
+      true.........if the wait has been interrupted,
+         false........if the wait was ended by notification or timeout
+
+*******************************************************************************/
+
+bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
+                                                                               s4 nanos)
 {
-       if (millis || nanos) {
+       struct timespec wakeupTime;
+
+       /* calculate the the (latest) wakeup time */
+
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+       /* wait */
+
+       return threads_wait_with_timeout(thread, &wakeupTime);
+}
+
+
+/* threads_calc_absolute_time **************************************************
+
+   Calculate the absolute point in time a given number of ms and ns from now.
+
+   IN:
+      millis............milliseconds from now
+         nanos.............nanoseconds from now
+
+   OUT:
+      *tm...............receives the timespec of the absolute point in time
+
+*******************************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
+{
+       if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
                struct timeval tv;
                long nsec;
                gettimeofday(&tv, NULL);
@@ -1262,212 +1930,125 @@ static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
                nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
                tm->tv_sec = tv.tv_sec + nsec / 1000000000;
                tm->tv_nsec = nsec % 1000000000;
-       } 
+       }
        else {
                tm->tv_sec = 0;
                tm->tv_nsec = 0;
        }
 }
 
-void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
-{
-       bool wasinterrupted;
-       struct timespec wakeupTime;
-       monitorLockRecord *mlr, *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return);
-
-       calcAbsoluteTime(&wakeupTime, millis, nanos);
-       
-       if (lr->waiter)
-               wakeWaiters(lr->waiter);
-       lr->waiting = o;
-       STORE_ORDER_BARRIER();
-       freeLockRecord(lr);
-       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
-       mlr = monitorEnter(t, o);
-       removeFromWaiters(mlr, lr);
-       mlr->lockCount = lr->lockCount;
-       lr->lockCount = 1;
-       lr->waiting = NULL;
-       lr->waiter = NULL;
-       recycleLockRecord(t, lr);
 
-       if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
-}
+/* threads_thread_interrupt ****************************************************
 
-static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
-{
-       monitorLockRecord *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return);
-       do {
-               threadobject *wthread;
-               monitorLockRecord *wlr = lr->waiter;
-               if (!wlr)
-                       break;
-               wthread = wlr->ownerThread;
-               pthread_mutex_lock(&wthread->waitLock);
-               if (wthread->isSleeping)
-                       pthread_cond_signal(&wthread->waitCond);
-               wthread->signaled = true;
-               pthread_mutex_unlock(&wthread->waitLock);
-               lr = wlr;
-       } while (!one);
-}
+   Interrupt the given thread.
 
-bool threadHoldsLock(threadobject *t, java_objectheader *o)
-{
-       monitorLockRecord *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       /* The reason why we have to check against NULL is that
-        * dummyLR->incharge == NULL */
-       return lr->o == o && lr->ownerThread == t;
-}
+   The thread gets the "waitcond" signal and 
+   its interrupted flag is set to true.
 
-void interruptThread(java_lang_VMThread *thread)
-{
-       threadobject *t = (threadobject*) thread;
+   IN:
+      thread............the thread to interrupt
 
-       pthread_mutex_lock(&t->waitLock);
-       if (t->isSleeping)
-               pthread_cond_signal(&t->waitCond);
-       t->interrupted = true;
-       pthread_mutex_unlock(&t->waitLock);
-}
+*******************************************************************************/
 
-bool interruptedThread()
+void threads_thread_interrupt(threadobject *thread)
 {
-       threadobject *t = (threadobject*) THREADOBJECT;
-       bool intr = t->interrupted;
-       t->interrupted = false;
-       return intr;
-}
+       /* Signal the thread a "waitcond" and tell it that it has been
+          interrupted. */
 
-bool isInterruptedThread(java_lang_VMThread *thread)
-{
-       threadobject *t = (threadobject*) thread;
-       return t->interrupted;
-}
+       pthread_mutex_lock(&thread->waitmutex);
 
+       /* Interrupt blocking system call using a signal. */
 
-/* thread_sleep ****************************************************************
+       pthread_kill(thread->tid, SIGHUP);
 
-   Sleep the current thread for the specified amount of time.
+       if (thread->sleeping)
+               pthread_cond_signal(&thread->waitcond);
 
-*******************************************************************************/
+       thread->interrupted = true;
 
-void thread_sleep(s8 millis, s4 nanos)
-{
-       threadobject       *t;
-       struct timespec    wakeupTime;
-       monitorLockRecord *lr;
-       bool               wasinterrupted;
-
-       t = (threadobject *) THREADOBJECT;
+       pthread_mutex_unlock(&thread->waitmutex);
+}
 
-       calcAbsoluteTime(&wakeupTime, millis, nanos);
 
-       lr = allocLockRecordSimple(t);
+/* threads_check_if_interrupted_and_reset **************************************
 
-       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
+   Check if the current thread has been interrupted and reset the
+   interruption flag.
 
-       recycleLockRecord(t, lr);
+   RETURN VALUE:
+      true, if the current thread had been interrupted
 
-       if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
-}
+*******************************************************************************/
 
-void yieldThread()
+bool threads_check_if_interrupted_and_reset(void)
 {
-       sched_yield();
-}
+       threadobject *thread;
+       bool intr;
 
-void setPriorityThread(thread *t, s4 priority)
-{
-       nativethread *info = &((threadobject*) t->vmThread)->info;
-       setPriority(info->tid, priority);
-}
+       thread = THREADOBJECT;
 
-void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
-{
-       threadobject *t = (threadobject*) THREADOBJECT;
-       monitorWait(t, o, millis, nanos);
-}
+       /* get interrupted flag */
 
-void signal_cond_for_object(java_objectheader *o)
-{
-       threadobject *t = (threadobject*) THREADOBJECT;
-       notifyOneOrAll(t, o, true);
-}
+       intr = thread->interrupted;
 
-void broadcast_cond_for_object(java_objectheader *o)
-{
-       threadobject *t = (threadobject*) THREADOBJECT;
-       notifyOneOrAll(t, o, false);
+       /* reset interrupted flag */
+
+       thread->interrupted = false;
+
+       return intr;
 }
 
 
-/* threads_dump ****************************************************************
+/* threads_thread_has_been_interrupted *****************************************
 
-   Dumps info for all threads running in the JVM. This function is
-   called when SIGQUIT (<ctrl>-\) is sent to CACAO.
+   Check if the given thread has been interrupted
 
-*******************************************************************************/
+   IN:
+      t............the thread to check
 
-void threads_dump(void)
-{
-       threadobject       *tobj;
-       java_lang_VMThread *vmt;
-       nativethread       *nt;
-       java_lang_Thread   *t;
-       utf                *name;
+   RETURN VALUE:
+      true, if the given thread had been interrupted
 
-       tobj = mainthreadobj;
+*******************************************************************************/
 
-       printf("Full thread dump CACAO "VERSION":\n");
+bool threads_thread_has_been_interrupted(threadobject *thread)
+{
+       return thread->interrupted;
+}
 
-       /* iterate over all started threads */
 
-       do {
-               /* get thread objects */
+/* threads_sleep ***************************************************************
 
-               vmt = &tobj->o;
-               nt  = &tobj->info;
-               t   = vmt->thread;
+   Sleep the current thread for the specified amount of time.
 
-               /* the thread may be currently in initalization, don't print it */
+*******************************************************************************/
 
-               if (t) {
-                       /* get thread name */
+void threads_sleep(s8 millis, s4 nanos)
+{
+       threadobject    *thread;
+       struct timespec  wakeupTime;
+       bool             wasinterrupted;
 
-                       name = javastring_toutf(t->name, false);
+       thread = THREADOBJECT;
 
-                       printf("\n\"");
-                       utf_display(name);
-                       printf("\" ");
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-                       if (t->daemon)
-                               printf("daemon ");
+       wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
 
-#if SIZEOF_VOID_P == 8
-                       printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
-#else
-                       printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
-#endif
+       if (wasinterrupted)
+               exceptions_throw_interruptedexception();
+}
 
-                       /* send SIGUSR1 to thread to print stacktrace */
 
-                       pthread_kill(nt->tid, SIGUSR1);
+/* threads_yield ***************************************************************
 
-                       /* sleep this thread a bit, so the signal can reach the thread */
+   Yield to the scheduler.
 
-                       thread_sleep(10, 0);
-               }
+*******************************************************************************/
 
-               tobj = tobj->info.next;
-       } while (tobj && (tobj != mainthreadobj));
+void threads_yield(void)
+{
+       sched_yield();
 }