* src/threads/native/threads.c (threads_init) [!ENABLE_GC_CACAO]: Fixed bug for
[cacao.git] / src / threads / native / threads.c
index 5a3f032be461be98f5c1d048c7c259e98a8eabf5..c159e9ccc017000b3496a312568b9c5a0dcea816 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 4871 2006-05-03 23:04:30Z edwin $
+   $Id: threads.c 7478 2007-03-08 02:59:31Z 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"
+
+#include "native/jni.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/threads-common.h"
+
 #include "threads/native/threads.h"
+
 #include "toolbox/avl.h"
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
+#include "vmcore/options.h"
+
 #if !defined(__DARWIN__)
-#if defined(__LINUX__)
-#define GC_LINUX_THREADS
-#elif defined(__MIPS__)
-#define GC_IRIX_THREADS
-#endif
-#include "boehm-gc/include/gc.h"
+# 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
 
-/******************************************************************************/
-/* Recursive Mutex Implementation for Darwin                                  */
-/******************************************************************************/
+#if defined(__DARWIN__)
+/* Darwin has no working semaphore implementation.  This one is taken
+   from Boehm-GC. */
 
-#ifdef MUTEXSIM
+/*
+   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);
 
-/* We need this for older MacOSX (10.1.x) */
+       sem->value = value;
+    
+       if (pthread_mutex_init(&sem->mutex, NULL) < 0)
+               return -1;
 
-typedef struct {
-       pthread_mutex_t mutex;
-       pthread_t owner;
-       int count;
-} pthread_mutex_rec_t;
+       if (pthread_cond_init(&sem->cond, NULL) < 0)
+               return -1;
 
-static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_init(&m->mutex, NULL);
-       m->count = 0;
+       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__) */
+
+
+/* internally used constants **************************************************/
+
+/* CAUTION: Do not change these values. Boehm GC code depends on them.        */
+#define STOPWORLD_FROM_GC               1
+#define STOPWORLD_FROM_CLASS_NUMBERING  2
+
+#define THREADS_INITIAL_TABLE_SIZE      8
+
+
+/* startupinfo *****************************************************************
 
-#else /* MUTEXSIM */
+   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_table_init(void);
+static s4 threads_table_add(threadobject *thread);
+static void threads_table_remove(threadobject *thread);
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
+
+#if !defined(NDEBUG) && 0
+static void threads_table_dump(FILE *file);
+#endif
+
+/******************************************************************************/
+/* GLOBAL VARIABLES                                                           */
+/******************************************************************************/
+
+/* the main thread                                                            */
+threadobject *mainthreadobj;
+
+static methodinfo *method_thread_init;
+
+/* the thread object of the current thread                                    */
+/* 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
+pthread_key_t threads_current_threadobject_key;
+#endif
+
+/* global threads table                                                       */
+static threads_table_t threads_table;
+
+/* global compiler mutex                                                      */
+static pthread_mutex_t compiler_mutex;
+
+/* global mutex for changing the thread list                                  */
+static pthread_mutex_t threadlistlock;
+
+/* global mutex for stop-the-world                                            */
+static pthread_mutex_t stopworldlock;
 
-#define pthread_mutex_lock_rec pthread_mutex_lock
-#define pthread_mutex_unlock_rec pthread_mutex_unlock
-#define pthread_mutex_rec_t pthread_mutex_t
+/* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
+/* being stopped                                                              */
+static volatile int stopworldwhere;
+
+/* 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
+
+static pthread_attr_t threadattr;
+
+/* 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
 
-#endif /* MUTEXSIM */
 
 /* threads_sem_init ************************************************************
  
@@ -178,11 +289,10 @@ void threads_sem_init(sem_t *sem, bool shared, int value)
                        return;
        } while (errno == EINTR);
 
-       fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
-                       errno, strerror(errno));
-       abort();
+       vm_abort("sem_init failed: %s", strerror(errno));
 }
 
+
 /* threads_sem_wait ************************************************************
  
    Wait for a semaphore, non-interruptible.
@@ -207,11 +317,10 @@ void threads_sem_wait(sem_t *sem)
                        return;
        } while (errno == EINTR);
 
-       fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
-                       errno, strerror(errno));
-       abort();
+       vm_abort("sem_wait failed: %s", strerror(errno));
 }
 
+
 /* threads_sem_post ************************************************************
  
    Increase the count of a semaphore. Checks for errors.
@@ -233,148 +342,58 @@ void threads_sem_post(sem_t *sem)
        if (r == 0)
                return;
 
-       fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
-                       errno, strerror(errno));
-       abort();
+       vm_abort("sem_post failed: %s", strerror(errno));
 }
 
-/* threads_set_thread_priority *************************************************
 
-   Set the priority of the given thread.
+/* compiler_lock ***************************************************************
 
-   IN:
-      tid..........thread id
-         priority.....priority to set
+   Enter the compiler lock.
 
 ******************************************************************************/
 
-static void threads_set_thread_priority(pthread_t tid, int priority)
+void compiler_lock(void)
 {
-       struct sched_param schedp;
-       int policy;
-
-       pthread_getschedparam(tid, &policy, &schedp);
-       schedp.sched_priority = priority;
-       pthread_setschedparam(tid, policy, &schedp);
+       pthread_mutex_lock(&compiler_mutex);
 }
 
 
-static avl_tree *criticaltree;
-threadobject *mainthreadobj;
-
-#ifndef HAVE___THREAD
-pthread_key_t tkey_threadinfo;
-#else
-__thread threadobject *threadobj;
-#endif
-
-static pthread_mutex_rec_t compiler_mutex;
+/* compiler_unlock *************************************************************
 
-void compiler_lock()
-{
-       pthread_mutex_lock_rec(&compiler_mutex);
-}
+   Release the compiler lock.
 
-void compiler_unlock()
-{
-       pthread_mutex_unlock_rec(&compiler_mutex);
-}
+******************************************************************************/
 
-static s4 criticalcompare(const void *pa, const void *pb)
+void compiler_unlock(void)
 {
-       const threadcritnode *na = pa;
-       const threadcritnode *nb = pb;
-
-       if (na->mcodebegin < nb->mcodebegin)
-               return -1;
-       if (na->mcodebegin > nb->mcodebegin)
-               return 1;
-       return 0;
+       pthread_mutex_unlock(&compiler_mutex);
 }
 
 
-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;
+/* lock_stopworld **************************************************************
 
-        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;
-                       }
-        }
-    }
-}
+   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
 
-void thread_registercritical(threadcritnode *n)
-{
-       avl_insert(criticaltree, n);
-}
-
-u1 *thread_checkcritical(u1 *mcodeptr)
-{
-       const threadcritnode *n = findcritical(mcodeptr);
-       return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
-}
+******************************************************************************/
 
-static void thread_addstaticcritical()
+void lock_stopworld(int where)
 {
-       /* XXX TWISTI: this is just a quick hack */
-#if defined(ENABLE_JIT)
-       threadcritnode *n = &asm_criticalsections;
-
-       while (n->mcodebegin)
-               thread_registercritical(n++);
-#endif
+       pthread_mutex_lock(&stopworldlock);
+       stopworldwhere = where;
 }
 
-static pthread_mutex_t threadlistlock;
 
-static pthread_mutex_t stopworldlock;
-volatile int stopworldwhere;
+/* unlock_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
+   Release the stopworld lock.
 
-/*
- * where - 1 from within GC
-           2 class numbering
- */
-void lock_stopworld(int where)
-{
-       pthread_mutex_lock(&stopworldlock);
-       stopworldwhere = where;
-}
+******************************************************************************/
 
-void unlock_stopworld()
+void unlock_stopworld(void)
 {
        stopworldwhere = 0;
        pthread_mutex_unlock(&stopworldlock);
@@ -382,98 +401,99 @@ void unlock_stopworld()
 
 #if !defined(__DARWIN__)
 /* Caller must hold threadlistlock */
-static int cast_sendsignals(int sig, int count)
+static int threads_cast_sendsignals(int sig, int count)
 {
        /* Count threads */
        threadobject *tobj = mainthreadobj;
-       nativethread *infoself = THREADINFO;
+       threadobject *self = THREADOBJECT;
 
        if (count == 0) {
                do {
                        count++;
-                       tobj = tobj->info.next;
+                       tobj = tobj->next;
                } while (tobj != mainthreadobj);
        }
 
+       assert(tobj == mainthreadobj);
+
        do {
-               nativethread *info = &tobj->info;
-               if (info != infoself)
-                       pthread_kill(info->tid, sig);
-               tobj = tobj->info.next;
+               if (tobj != self)
+                       pthread_kill(tobj->tid, sig);
+               tobj = tobj->next;
        } while (tobj != mainthreadobj);
 
-       return count-1;
+       return count - 1;
 }
 
 #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");
+
+                       thread_restartcriticalsection((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);
@@ -481,37 +501,51 @@ static void cast_irixresume()
 }
 #endif
 
-void cast_stopworld()
+#if !defined(DISABLE_GC)
+
+void threads_cast_stopworld(void)
 {
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
        int count, i;
-       lock_stopworld(2);
+#endif
+
+       lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
        pthread_mutex_lock(&threadlistlock);
+
 #if defined(__DARWIN__)
-       cast_darwinstop();
+       threads_cast_darwinstop();
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
 #else
-       count = cast_sendsignals(GC_signum1(), 0);
-       for (i=0; i<count; i++)
+       count = threads_cast_sendsignals(GC_signum1(), 0);
+       for (i = 0; i < count; i++)
                threads_sem_wait(&suspend_ack);
 #endif
+
        pthread_mutex_unlock(&threadlistlock);
 }
 
-void cast_startworld()
+void threads_cast_startworld(void)
 {
        pthread_mutex_lock(&threadlistlock);
 #if defined(__DARWIN__)
-       cast_darwinresume();
+       threads_cast_darwinresume();
 #elif defined(__MIPS__)
-       cast_irixresume();
+       threads_cast_irixresume();
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
 #else
-       cast_sendsignals(GC_signum2(), -1);
+       threads_cast_sendsignals(GC_signum2(), -1);
 #endif
        pthread_mutex_unlock(&threadlistlock);
        unlock_stopworld();
 }
 
+
 #if !defined(__DARWIN__)
-static void sigsuspend_handler(ucontext_t *ctx)
+static void threads_sigsuspend_handler(ucontext_t *ctx)
 {
        int sig;
        sigset_t sigs;
@@ -528,6 +562,9 @@ static void sigsuspend_handler(ucontext_t *ctx)
        threads_sem_post(&suspend_ack);
        pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
        pthread_mutex_unlock(&suspend_ack_lock);
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
 #else
        threads_sem_post(&suspend_ack);
 
@@ -538,104 +575,125 @@ static void sigsuspend_handler(ucontext_t *ctx)
 #endif
 }
 
+/* This function is called from Boehm GC code. */
+
 int cacao_suspendhandler(ucontext_t *ctx)
 {
-       if (stopworldwhere != 2)
+       if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
                return 0;
 
-       sigsuspend_handler(ctx);
+       threads_sigsuspend_handler(ctx);
        return 1;
 }
 #endif
 
-#if !defined(ENABLE_JVMTI)
-static void setthreadobject(threadobject *thread)
-#else
-void setthreadobject(threadobject *thread)
-#endif
+#endif /* DISABLE_GC */
+
+/* threads_set_current_threadobject ********************************************
+
+   Set the current thread object.
+   
+   IN:
+      thread.......the thread object to set
+
+*******************************************************************************/
+
+static void threads_set_current_threadobject(threadobject *thread)
 {
 #if !defined(HAVE___THREAD)
-       pthread_setspecific(tkey_threadinfo, thread);
+       pthread_setspecific(threads_current_threadobject_key, thread);
 #else
-       threadobj = thread;
+       threads_current_threadobject = thread;
 #endif
 }
 
 
-/* thread_setself **************************************************************
+/* threads_init_threadobject **************************************************
+
+   Initialize implementation fields of a threadobject.
+
+   IN:
+      thread............the threadobject
+
+******************************************************************************/
+
+static void threads_init_threadobject(threadobject *thread)
+{
+       thread->tid = pthread_self();
+
+       thread->index = 0;
+
+       /* TODO destroy all those things */
+       pthread_mutex_init(&(thread->joinmutex), NULL);
+       pthread_cond_init(&(thread->joincond), NULL);
+
+       pthread_mutex_init(&(thread->waitmutex), NULL);
+       pthread_cond_init(&(thread->waitcond), NULL);
+
+       thread->interrupted = false;
+       thread->signaled = false;
+       thread->sleeping = false;
+}
+
+
+/* threads_get_current_threadobject ********************************************
 
    Return the threadobject of the current thread.
    
-   XXX The return value type should be changed to a typed pointer.
+   RETURN VALUE:
+       the current threadobject * (an instance of java.lang.Thread)
 
 *******************************************************************************/
 
-void *thread_getself(void)
+threadobject *threads_get_current_threadobject(void)
 {
        return THREADOBJECT;
 }
 
-/* unlocked dummy record - avoids NULL checks */
-static monitorLockRecord *dummyLR;
-
-static void initPools();
 
-
-/* thread_preinit **************************************************************
+/* threads_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_preinit(void)
 {
-#ifndef MUTEXSIM
        pthread_mutexattr_t mutexattr;
        pthread_mutexattr_init(&mutexattr);
        pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&compiler_mutex, &mutexattr);
        pthread_mutexattr_destroy(&mutexattr);
-#else
-       pthread_mutex_init_rec(&compiler_mutex);
-#endif
 
        pthread_mutex_init(&threadlistlock, NULL);
        pthread_mutex_init(&stopworldlock, NULL);
 
-       /* Allocate something so the garbage collector's signal handlers
-          are installed. */
-       heap_allocate(1, false, NULL);
-
        mainthreadobj = NEW(threadobject);
-       mainthreadobj->info.tid = pthread_self();
+       mainthreadobj->object   = NULL;
+       mainthreadobj->tid      = pthread_self();
+       mainthreadobj->index    = 1;
+       mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
+       
 #if !defined(HAVE___THREAD)
-       pthread_key_create(&tkey_threadinfo, NULL);
+       pthread_key_create(&threads_current_threadobject_key, NULL);
 #endif
-       setthreadobject(mainthreadobj);
-       initPools();
-
-       /* Every newly created object's monitorPtr points here so we save
-          a check against NULL */
+       threads_set_current_threadobject(mainthreadobj);
 
-       dummyLR = NEW(monitorLockRecord);
-       dummyLR->o = NULL;
-       dummyLR->ownerThread = NULL;
-       dummyLR->waiting = NULL;
-       dummyLR->incharge = dummyLR;
-
-       /* we need a working dummyLR before initializing the critical
-          section tree */
+       threads_sem_init(&suspend_ack, 0, 0);
 
-    criticaltree = avl_create(&criticalcompare);
+       /* initialize the threads table */
 
-       thread_addstaticcritical();
-       threads_sem_init(&suspend_ack, 0, 0);
-}
+       threads_table_init();
 
+       /* initialize subsystems */
 
-static pthread_attr_t threadattr;
+       lock_init();
 
-static void freeLockRecordPools(lockRecordPool *);
+       critical_init();
+}
 
 
 /* threads_init ****************************************************************
@@ -644,109 +702,178 @@ static void freeLockRecordPools(lockRecordPool *);
 
 *******************************************************************************/
 
-bool threads_init(u1 *stackbottom)
+bool threads_init(void)
 {
        java_lang_String      *threadname;
-       java_lang_Thread      *mainthread;
-       java_lang_ThreadGroup *threadgroup;
        threadobject          *tempthread;
-       methodinfo            *method;
+       java_objectheader     *o;
+
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *threadgroup;
+       methodinfo            *m;
+       java_lang_Thread      *t;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
 
        tempthread = mainthreadobj;
 
-       freeLockRecordPools(mainthreadobj->ee.lrpool);
+       /* XXX We have to find a new way to free lock records */
+       /*     with the new locking algorithm.                */
+       /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
 
+#if 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. */
 
-       class_java_lang_VMThread->instancesize = sizeof(threadobject);
+       class_java_lang_Thread->instancesize = sizeof(threadobject);
+#endif
+
+       /* 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;
+
+       /* create a vm internal thread object for the main thread */
+       /* XXX Michi: we do not need to do this here, we could use the one
+              created by threads_preinit() */
+
+#if defined(ENABLE_GC_CACAO)
+       mainthreadobj = NEW(threadobject);
+#else
+       mainthreadobj = GCNEW(threadobject);
+#endif
+
+       if (mainthreadobj == NULL)
+               return false;
 
-       /* create a VMThread */
+       /* create a java.lang.Thread for the main thread */
 
-       mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
+       mainthreadobj->object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       if (!mainthreadobj)
+       if (mainthreadobj->object == NULL)
                return false;
 
        FREE(tempthread, threadobject);
 
-       initThread(&mainthreadobj->o);
+       threads_init_threadobject(mainthreadobj);
+
+       threads_set_current_threadobject(mainthreadobj);
+
+       lock_init_execution_env(mainthreadobj);
 
-       setthreadobject(mainthreadobj);
+       mainthreadobj->next = mainthreadobj;
+       mainthreadobj->prev = mainthreadobj;
 
-       initLocks();
+       threads_table_add(mainthreadobj);
 
-       mainthreadobj->info.next = mainthreadobj;
-       mainthreadobj->info.prev = mainthreadobj;
+       /* mark main thread as Java thread */
+
+       mainthreadobj->flags = THREAD_FLAG_JAVA;
 
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
 
        if (opt_intrp) {
                MSET(intrp_main_stack, 0, u1, opt_stacksize);
-               mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
+               mainthreadobj->_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)
+       if (threadgroup == NULL)
                throw_exception_exit();
+#endif
 
-       /* create a Thread */
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread for the main thread */
 
-       mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
-       if (!mainthread)
+       if (vmt == NULL)
                throw_exception_exit();
 
-       mainthreadobj->o.thread = mainthread;
+       /* set the thread */
 
-       /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+       vmt->thread = mainthreadobj->object;
+       vmt->vmdata = (java_lang_Object *) mainthreadobj;
 
-       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);
+       /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+       o = (java_objectheader *) mainthreadobj->object;
 
-       if (!method)
-               return false;
+       (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
+                                                 false);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       /* set the thread */
 
-       (void) vm_call_method(method, (java_objectheader *) mainthread,
-                                                 mainthreadobj, threadname, 5, false);
+       mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
 
-       if (*exceptionptr)
+       /* call public Thread(String name) */
+
+       o = (java_objectheader *) mainthreadobj->object;
+
+       (void) vm_call_method(method_thread_init, o, threadname);
+#endif
+
+       if (*exceptionptr)
                return false;
 
-       mainthread->group = threadgroup;
+#if defined(ENABLE_JAVASE)
+       mainthreadobj->object->group = threadgroup;
 
-       /* add mainthread to ThreadGroup */
+       /* add main thread to java.lang.ThreadGroup */
 
-       method = class_resolveclassmethod(class_java_lang_ThreadGroup,
-                                                                         utf_new_char("addThread"),
-                                                                         utf_new_char("(Ljava/lang/Thread;)V"),
-                                                                         class_java_lang_ThreadGroup,
-                                                                         true);
+       m = class_resolveclassmethod(class_java_lang_ThreadGroup,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
 
-       if (!method)
-               return false;
+       o = (java_objectheader *) threadgroup;
+       t = mainthreadobj->object;
 
-       (void) vm_call_method(method, (java_objectheader *) threadgroup,
-                                                 mainthread);
+       (void) vm_call_method(m, o, t);
 
        if (*exceptionptr)
                return false;
 
-       threads_set_thread_priority(pthread_self(), 5);
+#endif
+
+       threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
+
+       /* initialize the thread attribute object */
+
+       if (pthread_attr_init(&threadattr)) {
+               log_println("pthread_attr_init failed: %s", strerror(errno));
+               return false;
+       }
 
-       pthread_attr_init(&threadattr);
        pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
 
        /* everything's ok */
@@ -755,45 +882,136 @@ bool threads_init(u1 *stackbottom)
 }
 
 
-void initThread(java_lang_VMThread *t)
+/* threads_table_init *********************************************************
+
+   Initialize the global threads table.
+
+******************************************************************************/
+
+static void threads_table_init(void)
 {
-       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);
+       s4 size;
+       s4 i;
 
-       pthread_mutex_init(&thread->waitLock, NULL);
-       pthread_cond_init(&thread->waitCond, NULL);
-       thread->interrupted = false;
-       thread->signaled = false;
-       thread->isSleeping = false;
+       size = THREADS_INITIAL_TABLE_SIZE;
+
+       threads_table.size = size;
+       threads_table.table = MNEW(threads_table_entry_t, size);
+
+       /* link the entries in a freelist */
+
+       for (i=0; i<size; ++i) {
+               threads_table.table[i].nextfree = i+1;
+       }
+
+       /* terminate the freelist */
+
+       threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
 }
 
-static void initThreadLocks(threadobject *);
 
+/* threads_table_add **********************************************************
 
-/* startupinfo *****************************************************************
+   Add a thread to the global threads table. The index is entered in the
+   threadobject. The thinlock value for the thread is pre-computed.
 
-   Struct used to pass info from threads_start_thread to 
-   threads_startup_thread.
+   IN:
+      thread............the thread to add
+
+   RETURN VALUE:
+      The table index for the newly added thread. This value has also been
+         entered in the threadobject.
+
+   PRE-CONDITION:
+      The caller must hold the threadlistlock!
 
 ******************************************************************************/
 
-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;
+static s4 threads_table_add(threadobject *thread)
+{
+       s4 index;
+       s4 oldsize;
+       s4 newsize;
+       s4 i;
+
+       /* table[0] serves as the head of the freelist */
+
+       index = threads_table.table[0].nextfree;
+
+       /* if we got a free index, use it */
+
+       if (index) {
+got_an_index:
+               threads_table.table[0].nextfree = threads_table.table[index].nextfree;
+               threads_table.table[index].thread = thread;
+               thread->index = index;
+               thread->thinlock = lock_pre_compute_thinlock(index);
+               return index;
+       }
+
+       /* we must grow the table */
+
+       oldsize = threads_table.size;
+       newsize = oldsize * 2;
+
+       threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
+                                                                  oldsize, newsize);
+       threads_table.size = newsize;
+
+       /* link the new entries to a free list */
+
+       for (i=oldsize; i<newsize; ++i) {
+               threads_table.table[i].nextfree = i+1;
+       }
+
+       /* terminate the freelist */
+
+       threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
+
+       /* use the first of the new entries */
+
+       index = oldsize;
+       goto got_an_index;
+}
+
+
+/* threads_table_remove *******************************************************
+
+   Remove a thread from the global threads table.
+
+   IN:
+      thread............the thread to remove
+
+   PRE-CONDITION:
+      The caller must hold the threadlistlock!
+
+******************************************************************************/
+
+static void threads_table_remove(threadobject *thread)
+{
+       s4 index;
+
+       index = thread->index;
+
+       /* put the index into the freelist */
+
+       threads_table.table[index] = threads_table.table[0];
+       threads_table.table[0].nextfree = index;
+
+       /* delete the index in the threadobject to discover bugs */
+#if !defined(NDEBUG)
+       thread->index = 0;
+#endif
+}
 
 
 /* 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.
@@ -808,13 +1026,17 @@ typedef struct {
 
 static void *threads_startup_thread(void *t)
 {
-       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;
+       threadobject       *tnext;
+       classinfo          *c;
+       methodinfo         *m;
+       java_objectheader  *o;
+       functionptr         function;
 
 #if defined(ENABLE_INTRP)
        u1 *intrp_thread_stack;
@@ -822,11 +1044,11 @@ 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 */
@@ -838,9 +1060,7 @@ static void *threads_startup_thread(void *t)
        function = startup->function;
        psem     = startup->psem;
 
-       info = &thread->info;
-
-       /* Seems like we've encountered a situation where info->tid was not set by
+       /* Seems like we've encountered a situation where thread->tid was not set by
         * pthread_create. We alleviate this problem by waiting for pthread_create
         * to return. */
        threads_sem_wait(startup->psem_first);
@@ -848,24 +1068,26 @@ static void *threads_startup_thread(void *t)
        /* set the thread object */
 
 #if defined(__DARWIN__)
-       info->mach_thread = mach_thread_self();
+       thread->mach_thread = mach_thread_self();
 #endif
-       setthreadobject(thread);
+       threads_set_current_threadobject(thread);
 
-       /* insert the thread into the threadlist */
+       /* insert the thread into the threadlist and the threads table */
 
        pthread_mutex_lock(&threadlistlock);
 
-       info->prev = mainthreadobj;
-       info->next = tnext = mainthreadobj->info.next;
-       mainthreadobj->info.next = thread;
-       tnext->info.prev = thread;
+       thread->prev = mainthreadobj;
+       thread->next = tnext = mainthreadobj->next;
+       mainthreadobj->next = thread;
+       tnext->prev = thread;
+
+       threads_table_add(thread);
 
        pthread_mutex_unlock(&threadlistlock);
 
        /* init data structures of this thread */
 
-       initThreadLocks(thread);
+       lock_init_execution_env(thread);
 
        /* tell threads_startup_thread that we registered ourselves */
        /* CAUTION: *startup becomes invalid with this!             */
@@ -875,86 +1097,162 @@ static void *threads_startup_thread(void *t)
 
        /* set our priority */
 
-       threads_set_thread_priority(info->tid, thread->o.thread->priority);
+       threads_set_thread_priority(thread->tid, thread->object->priority);
 
 #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
 
        /* 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);
+               /* this is a normal Java thread */
+
+               thread->flags |= THREAD_FLAG_JAVA;
 
-               if (!method)
+#if defined(WITH_CLASSPATH_GNU)
+               /* We need to start the run method of
+                  java.lang.VMThread. Since this is a final class, we can use
+                  the class object directly. */
+
+               c   = class_java_lang_VMThread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+               c   = thread->object->header.vftbl->class;
+#endif
+
+               m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
+
+               if (m == NULL)
                        throw_exception();
 
-               (void) vm_call_method(method, (java_objectheader *) thread);
+               /* 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;
 
+#if defined(WITH_CLASSPATH_GNU)
+               /* we need to start the run method of java.lang.VMThread */
+
+               vmt = (java_lang_VMThread *) thread->object->vmThread;
+               o   = (java_objectheader *) vmt;
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+               o   = (java_objectheader *) thread->object;
+#endif
+
+               (void) vm_call_method(m, o);
        }
        else {
+               /* this is an internal thread */
+
+               thread->flags |= THREAD_FLAG_INTERNAL;
+
+               /* set ThreadMXBean variables */
+
+               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+               _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. */
+#if defined(ENABLE_JVMTI)
+       /* fire thread end event */
 
-       freeLockRecordPools(thread->ee.lrpool);
+       if (jvmti)
+               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
 
-       /* remove thread from thread list, do this inside a lock */
+       threads_detach_thread(thread);
 
-       pthread_mutex_lock(&threadlistlock);
-       info->next->info.prev = info->prev;
-       info->prev->info.next = info->next;
-       pthread_mutex_unlock(&threadlistlock);
+       /* set ThreadMXBean variables */
 
-       /* reset thread id (lock on joinMutex? TWISTI) */
+       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
 
-       pthread_mutex_lock(&info->joinMutex);
-       info->tid = 0;
-       pthread_mutex_unlock(&info->joinMutex);
+       return NULL;
+}
 
-       /* tell everyone that a thread has finished */
 
-       pthread_cond_broadcast(&info->joinCond);
+/* threads_start_javathread ***************************************************
 
-       return NULL;
+   Start a thread in the JVM. Only the java thread object exists so far.
+
+   IN:
+      object.....the java thread object java.lang.Thread
+
+******************************************************************************/
+
+void threads_start_javathread(java_lang_Thread *object)
+{
+       threadobject *thread;
+
+       /* create the vm internal threadobject */
+
+       thread = NEW(threadobject);
+       assert(thread);
+
+       /* link the two objects together */
+
+       thread->object = object;
+
+#if defined(WITH_CLASSPATH_GNU)
+       assert(object->vmThread);
+       assert(object->vmThread->vmdata == NULL);
+       object->vmThread->vmdata = (java_lang_Object *) thread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       object->vm_thread = (java_lang_Object *) thread;
+#endif
+
+       /* actually start the thread */
+       /* don't pass a function pointer (NULL) since we want Thread.run()V here */
+
+       threads_start_thread(thread, NULL);
 }
 
 
 /* threads_start_thread ********************************************************
 
-   Start a thread in the JVM.
+   Start a thread in the JVM. Both (vm internal and java) thread objects exist.
 
    IN:
-      t............the java.lang.Thread object
+      thread.......the thread object
          function.....function to run in the new thread. NULL means that the
                       "run" method of the object `t` should be called
 
 ******************************************************************************/
 
-void threads_start_thread(thread *t, functionptr function)
+void threads_start_thread(threadobject *thread, functionptr function)
 {
-       nativethread *info;
-       sem_t         sem;
-       sem_t         sem_first;
-       startupinfo   startup;
-
-       info = &((threadobject *) t->vmThread)->info;
+       sem_t          sem;
+       sem_t          sem_first;
+       pthread_attr_t attr;
+       startupinfo    startup;
 
        /* fill startupinfo structure passed by pthread_create to
         * threads_startup_thread */
 
-       startup.thread     = (threadobject*) t->vmThread;
+       startup.thread     = thread;
        startup.function   = function;       /* maybe we don't call Thread.run()V */
        startup.psem       = &sem;
        startup.psem_first = &sem_first;
@@ -962,15 +1260,22 @@ void threads_start_thread(thread *t, functionptr function)
        threads_sem_init(&sem, 0, 0);
        threads_sem_init(&sem_first, 0, 0);
 
+       /* initialize thread attribute object */
+
+       if (pthread_attr_init(&attr))
+               vm_abort("pthread_attr_init failed: %s", strerror(errno));
+
+       /* initialize thread stacksize */
+
+       if (pthread_attr_setstacksize(&attr, opt_stacksize))
+               vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
+
        /* create the thread */
 
-       if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
-                                          &startup)) {
-               log_text("pthread_create failed");
-               assert(0);
-       }
+       if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
+               vm_abort("pthread_create failed: %s", strerror(errno));
 
-       /* signal that pthread_create has returned, so info->tid is valid */
+       /* signal that pthread_create has returned, so thread->tid is valid */
 
        threads_sem_post(&sem_first);
 
@@ -985,425 +1290,300 @@ void threads_start_thread(thread *t, functionptr function)
 }
 
 
-/* At the end of the program, we wait for all running non-daemon threads to die
- */
+/* threads_set_thread_priority *************************************************
 
-static threadobject *findNonDaemon(threadobject *thread)
-{
-       while (thread != mainthreadobj) {
-               if (!thread->o.thread->daemon)
-                       return thread;
-               thread = thread->info.prev;
-       }
+   Set the priority of the given thread.
 
-       return NULL;
-}
+   IN:
+      tid..........thread id
+         priority.....priority to set
 
-void joinAllThreads()
-{
-       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);
-       }
-       pthread_mutex_unlock(&threadlistlock);
-}
+******************************************************************************/
 
-static void initLockRecord(monitorLockRecord *r, threadobject *t)
+void threads_set_thread_priority(pthread_t tid, int priority)
 {
-       r->lockCount = 1;
-       r->ownerThread = t;
-       r->queuers = 0;
-       r->o = NULL;
-       r->waiter = NULL;
-       r->incharge = (monitorLockRecord *) &dummyLR;
-       r->waiting = NULL;
-       threads_sem_init(&r->queueSem, 0, 0);
-       pthread_mutex_init(&r->resolveLock, NULL);
-       pthread_cond_init(&r->resolveWait, NULL);
-}
+       struct sched_param schedp;
+       int policy;
 
-void initLocks()
-{
-       initThreadLocks(mainthreadobj);
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
 }
 
-static void initThreadLocks(threadobject *thread)
-{
-       thread->ee.firstLR = NULL;
-       thread->ee.lrpool = NULL;
-       thread->ee.numlr = 0;
-}
 
-static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
+/* threads_attach_current_thread ***********************************************
+
+   Attaches the current thread to the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 {
-       lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
-       int i;
+       threadobject          *thread;
+       utf                   *u;
+       java_lang_String      *s;
+       java_objectheader     *o;
+       java_lang_Thread      *t;
 
-       p->header.size = size;
-       for (i=0; i<size; i++) {
-               initLockRecord(&p->lr[i], thread);
-               p->lr[i].nextFree = &p->lr[i+1];
-       }
-       p->lr[i-1].nextFree = NULL;
-       return p;
-}
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+#endif
 
-#define INITIALLOCKRECORDS 8
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
 
-pthread_mutex_t pool_lock;
-lockRecordPool *global_pool;
+       /* create a vm internal thread object */
 
-static void initPools()
-{
-       pthread_mutex_init(&pool_lock, NULL);
-}
+       thread = NEW(threadobject);
 
-static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
-{
-       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;
+       if (thread == NULL)
+               return false;
 
-               return pool;
-       }
-       pthread_mutex_unlock(&pool_lock);
+       /* create a java.lang.Thread object */
 
-       return allocNewLockRecordPool(t, size);
-}
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-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);
-}
+       if (t == NULL)
+               return false;
 
-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;
-       }
+       thread->object = t;
 
-       t->ee.firstLR = r->nextFree;
-#ifndef NDEBUG
-       r->nextFree = NULL; /* in order to find invalid uses of nextFree */
-#endif
-       return r;
-}
+       threads_init_threadobject(thread);
+       threads_set_current_threadobject(thread);
+       lock_init_execution_env(thread);
 
-static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
-{
-       assert(t);
-       assert(r);
-       assert(r->ownerThread == t);
-       assert(r->nextFree == NULL);
+       /* insert the thread into the threadlist and the threads table */
 
-       r->nextFree = t->ee.firstLR;
-       t->ee.firstLR = r;
-}
+       pthread_mutex_lock(&threadlistlock);
 
-/* initObjectLock **************************************************************
+       thread->prev        = mainthreadobj;
+       thread->next        = mainthreadobj->next;
+       mainthreadobj->next = thread;
+       thread->next->prev  = thread;
 
-   Initialize the monitor pointer of the given object. The monitor gets
-   initialized to an unlocked state.
+       threads_table_add(thread);
 
-*******************************************************************************/
+       pthread_mutex_unlock(&threadlistlock);
 
-void initObjectLock(java_objectheader *o)
-{
-       assert(o);
+       /* mark thread as Java thread */
 
-       o->monitorPtr = dummyLR;
-}
+       thread->flags = THREAD_FLAG_JAVA;
 
+       if (isdaemon)
+               thread->flags |= THREAD_FLAG_DAEMON;
 
-/* get_dummyLR *****************************************************************
+#if defined(ENABLE_INTRP)
+       /* create interpreter stack */
 
-   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.
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
+       }
+#endif
 
-*******************************************************************************/
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread object */
 
-monitorLockRecord *get_dummyLR(void)
-{
-       return dummyLR;
-}
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
+       if (vmt == NULL)
+               return false;
 
-static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
-{
-       atomic_add(&lr->queuers, 1);
-       MEMORY_BARRIER_AFTER_ATOMIC();
+       /* set the thread */
 
-       if (lr->o == o)
-               threads_sem_wait(&lr->queueSem);
+       vmt->thread = t;
+       vmt->vmdata = (java_lang_Object *) thread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       t->vm_thread = (java_lang_Object *) thread;
+#endif
 
-       atomic_add(&lr->queuers, -1);
-}
+       if (vm_aargs != NULL) {
+               u     = utf_new_char(vm_aargs->name);
+#if defined(ENABLE_JAVASE)
+               group = (java_lang_ThreadGroup *) vm_aargs->group;
+#endif
+       }
+       else {
+               u     = utf_null;
+#if defined(ENABLE_JAVASE)
+               group = mainthreadobj->object->group;
+#endif
+       }
 
-static void freeLockRecord(monitorLockRecord *lr)
-{
-       int q;
-       lr->o = NULL;
-       MEMORY_BARRIER();
-       q = lr->queuers;
-       while (q--)
-               threads_sem_post(&lr->queueSem);
-}
+       s = javastring_new(u);
 
-static inline void handleWaiter(monitorLockRecord *newlr,
-                                                               monitorLockRecord *curlr,
-                                                               java_objectheader *o)
-{
-       /* if the current lock record is used for waiting on the object */
-       /* `o`, then record it as a waiter in the new lock record       */
+       o = (java_objectheader *) thread->object;
 
-       if (curlr->waiting == o)
-               newlr->waiter = curlr;
-}
+#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
 
-/* monitorEnter ****************************************************************
+       if (*exceptionptr)
+               return false;
 
-   Acquire the monitor of the given object. If the current thread already
-   owns the monitor, the lock counter is simply increased.
+#if defined(ENABLE_JAVASE)
+       /* store the thread group in the object */
 
-   This function blocks until it can acquire the monitor.
+       thread->object->group = group;
 
-   IN:
-      t............the current thread
-         o............the object of which to enter the monitor
+       /* add thread to given thread-group */
 
-   RETURN VALUE:
-      the new lock record of the object when it has been entered
+       m = class_resolveclassmethod(group->header.vftbl->class,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
 
-*******************************************************************************/
+       o = (java_objectheader *) group;
 
-monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
-{
-       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 = (monitorLockRecord *) 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 */
+       (void) vm_call_method(m, o, t);
 
-                       if (lr->ownerThread == t) {
-                               /* we own it already, just recurse */
-                               lr->lockCount++;
-                               return lr;
-                       }
+       if (*exceptionptr)
+               return false;
+#endif
 
-                       /* it's locked. we wait and then try again */
-                       queueOnLockRecord(lr, o);
-               }
-       }
+       return true;
 }
 
-/* threads_wake_waiters ********************************************************
 
-   For each lock record in the given waiter list, post the queueSem
-   once for each queuer of the lock record.
+/* threads_detach_thread *******************************************************
 
-   IN:
-      lr...........the head of the waiter list
+   Detaches the passed thread from the VM.  Used in JNI.
 
 *******************************************************************************/
 
-static void threads_wake_waiters(monitorLockRecord *lr)
+bool threads_detach_thread(threadobject *thread)
 {
-       monitorLockRecord *tmplr;
-       s4 q;
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+       java_objectheader     *o;
+       java_lang_Thread      *t;
+#endif
 
-       /* move it to a local variable (Stefan commented this especially.
-        * Might be important somehow...) */
+       /* Allow lock record pools to be used by other threads. They
+          cannot be deleted so we'd better not waste them. */
 
-       tmplr = lr;
+       /* XXX We have to find a new way to free lock records */
+       /*     with the new locking algorithm.                */
+       /* lock_record_free_pools(thread->ee.lockrecordpools); */
 
-       do {
-               q = tmplr->queuers;
+       /* XXX implement uncaught exception stuff (like JamVM does) */
 
-               while (q--)
-                       threads_sem_post(&tmplr->queueSem);
+#if defined(ENABLE_JAVASE)
+       /* remove thread from the thread group */
 
-               tmplr = tmplr->waiter;
-       } while (tmplr != NULL && tmplr != lr); /* this breaks cycles to lr */
-}
+       group = thread->object->group;
 
-#define GRAB_LR(lr,t) \
-    if (lr->ownerThread != t) { \
-               lr = lr->incharge; \
-       }
+       /* XXX TWISTI: should all threads be in a ThreadGroup? */
+
+       if (group != NULL) {
+               m = class_resolveclassmethod(group->header.vftbl->class,
+                                                                        utf_removeThread,
+                                                                        utf_java_lang_Thread__V,
+                                                                        class_java_lang_ThreadGroup,
+                                                                        true);
+
+               if (m == NULL)
+                       return false;
 
-#define CHECK_MONITORSTATE(lr,t,mo,a) \
-    if (lr->o != mo || lr->ownerThread != t) { \
-               *exceptionptr = new_illegalmonitorstateexception(); \
-               a; \
+               o = (java_objectheader *) group;
+               t = thread->object;
+
+               (void) vm_call_method(m, o, t);
+
+               if (*exceptionptr)
+                       return false;
        }
+#endif
 
-/* monitorExit *****************************************************************
+       /* remove thread from thread list and threads table, do this
+          inside a lock */
 
-   Decrement the counter of a (currently owned) monitor. If the counter
-   reaches zero, release the monitor.
+       pthread_mutex_lock(&threadlistlock);
 
-   If the current thread is not the owner of the monitor, an 
-   IllegalMonitorState exception is thrown.
+       thread->next->prev = thread->prev;
+       thread->prev->next = thread->next;
 
-   IN:
-      t............the current thread
-         o............the object of which to exit the monitor
+       threads_table_remove(thread);
 
-   RETURN VALUE:
-      true.........everything ok,
-         false........an exception has been thrown
+       pthread_mutex_unlock(&threadlistlock);
 
-*******************************************************************************/
+       /* reset thread id (lock on joinmutex? TWISTI) */
 
-bool monitorExit(threadobject *t, java_objectheader *o)
-{
-       monitorLockRecord *lr;
+       pthread_mutex_lock(&(thread->joinmutex));
+       thread->tid = 0;
+       pthread_mutex_unlock(&(thread->joinmutex));
 
-       lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return false);
+       /* tell everyone that a thread has finished */
 
-       /* { the current thread `t` owns the lock record `lr` on object `o` } */
+       pthread_cond_broadcast(&(thread->joincond));
 
-       if (lr->lockCount > 1) {
-               /* we had locked this one recursively. just decrement, it will */
-               /* still be locked. */
-               lr->lockCount--;
-               return true;
-       }
+       /* free the vm internal thread object */
 
-       /* we are going to unlock and recycle this lock record */
+       FREE(thread, threadobject);
 
-       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; /* XXX is it ok to overwrite the nlr->waiter field like that? */
-                       STORE_ORDER_BARRIER();
-               }
-               else {
-                       threads_wake_waiters(wlr);
-               }
-               lr->waiter = NULL;
+       return true;
+}
+
+
+/* threads_find_non_daemon_thread **********************************************
+
+   Helper function used by threads_join_all_threads for finding
+   non-daemon threads that are still running.
+
+*******************************************************************************/
+
+/* At the end of the program, we wait for all running non-daemon
+   threads to die. */
+
+static threadobject *threads_find_non_daemon_thread(threadobject *thread)
+{
+       while (thread != mainthreadobj) {
+               if (!(thread->flags & THREAD_FLAG_DAEMON))
+                       return thread;
+
+               thread = thread->prev;
        }
 
-       /* unlock and throw away this lock record */
-       freeLockRecord(lr);
-       recycleLockRecord(t, lr);
-       return true;
+       return NULL;
 }
 
-/* threads_remove_waiter *******************************************************
 
-   Remove a waiter lock record from the waiter list of the given lock record
+/* threads_join_all_threads ****************************************************
 
-   IN:
-      lr...........the lock record holding the waiter list
-         toremove.....the record to remove from the list
+   Join all non-daemon threads.
 
 *******************************************************************************/
 
-static void threads_remove_waiter(monitorLockRecord *lr,
-                                                                 monitorLockRecord *toremove)
+void threads_join_all_threads(void)
 {
-       do {
-               if (lr->waiter == toremove) {
-                       lr->waiter = toremove->waiter;
-                       break;
-               }
-               lr = lr->waiter;
-       } while (lr); /* XXX need to break cycle? */
+       threadobject *thread;
+
+       pthread_mutex_lock(&threadlistlock);
+
+       while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
+               pthread_mutex_lock(&(thread->joinmutex));
+
+               pthread_mutex_unlock(&threadlistlock);
+
+               while (thread->tid)
+                       pthread_cond_wait(&(thread->joincond), &(thread->joinmutex));
+
+               pthread_mutex_unlock(&(thread->joinmutex));
+
+               pthread_mutex_lock(&threadlistlock);
+       }
+
+       pthread_mutex_unlock(&threadlistlock);
 }
 
+
 /* threads_timespec_earlier ****************************************************
 
    Return true if timespec tv1 is earlier than timespec tv2.
@@ -1425,6 +1605,7 @@ static inline bool threads_timespec_earlier(const struct timespec *tv1,
                (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
 }
 
+
 /* threads_current_time_is_earlier_than ****************************************
 
    Check if the current time is earlier than the given timespec.
@@ -1444,11 +1625,8 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
        /* get current time */
 
-       if (gettimeofday(&tvnow, NULL) != 0) {
-               fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
-                               errno, strerror(errno));
-               abort();
-       }
+       if (gettimeofday(&tvnow, NULL) != 0)
+               vm_abort("gettimeofday failed: %s\n", strerror(errno));
 
        /* convert it to a timespec */
 
@@ -1463,7 +1641,7 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
 /* threads_wait_with_timeout ***************************************************
 
-   Wait for the given maximum amount of time on a monitor until either
+   Wait until the given point in time on a monitor until either
    we are notified, we are interrupted, or the time is up.
 
    IN:
@@ -1478,217 +1656,122 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
 *******************************************************************************/
 
-static bool threads_wait_with_timeout(threadobject *t,
+static bool threads_wait_with_timeout(threadobject *thread,
                                                                          struct timespec *wakeupTime)
 {
        bool wasinterrupted;
 
-       /* acquire the waitLock */
+       /* acquire the waitmutex */
 
-       pthread_mutex_lock(&t->waitLock);
+       pthread_mutex_lock(&thread->waitmutex);
 
        /* mark us as sleeping */
 
-       t->isSleeping = true;
+       thread->sleeping = true;
 
-       /* wait on waitCond */
+       /* wait on waitcond */
 
        if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
                /* with timeout */
-               while (!t->interrupted && !t->signaled
+               while (!thread->interrupted && !thread->signaled
                           && threads_current_time_is_earlier_than(wakeupTime))
                {
-                       pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
+                       pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
+                                                                  wakeupTime);
                }
        }
        else {
                /* no timeout */
-               while (!t->interrupted && !t->signaled)
-                       pthread_cond_wait(&t->waitCond, &t->waitLock);
+               while (!thread->interrupted && !thread->signaled)
+                       pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
        }
 
        /* check if we were interrupted */
 
-       wasinterrupted = t->interrupted;
+       wasinterrupted = thread->interrupted;
 
        /* reset all flags */
 
-       t->interrupted = false;
-       t->signaled = false;
-       t->isSleeping = false;
+       thread->interrupted = false;
+       thread->signaled    = false;
+       thread->sleeping    = false;
 
-       /* release the waitLock */
+       /* release the waitmutex */
 
-       pthread_mutex_unlock(&t->waitLock);
+       pthread_mutex_unlock(&thread->waitmutex);
 
        return wasinterrupted;
 }
 
 
-static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
-{
-       if (millis || nanos) {
-               struct timeval tv;
-               long nsec;
-               gettimeofday(&tv, NULL);
-               tv.tv_sec += millis / 1000;
-               millis %= 1000;
-               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;
-       }
-}
+/* threads_wait_with_timeout_relative ******************************************
 
-/* monitorWait *****************************************************************
-
-   Wait on an object for a given (maximum) amount of time.
+   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
-         o............the object
-         millis.......milliseconds of timeout
-         nanos........nanoseconds of timeout
+         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
 
-   PRE-CONDITION:
-      The current thread must be the owner of the object's monitor.
-   
 *******************************************************************************/
 
-void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
+bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
+                                                                               s4 nanos)
 {
-       bool wasinterrupted;
        struct timespec wakeupTime;
-       monitorLockRecord *newlr;
-       monitorLockRecord *lr;
-
-       lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return);
-
-       /* { the thread t owns the lock record lr on the object o } */
 
        /* calculate the the (latest) wakeup time */
 
-       calcAbsoluteTime(&wakeupTime, millis, nanos);
-
-       /* wake threads waiting on this record XXX why? */
-
-       if (lr->waiter)
-               threads_wake_waiters(lr->waiter);
-
-       /* mark the lock record as "waiting on object o" */
-
-       lr->waiting = o;
-       STORE_ORDER_BARRIER();
-
-       /* unlock this record */
-
-       freeLockRecord(lr);
-
-       /* wait until notified/interrupted/timed out */
-
-       wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
-
-       /* re-enter the monitor */
-
-       newlr = monitorEnter(t, o);
-
-       /* we are no longer waiting */
-
-       threads_remove_waiter(newlr, lr);
-       newlr->lockCount = lr->lockCount;
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-       /* recylce the old lock record */
+       /* wait */
 
-       lr->lockCount = 1;
-       lr->waiting = NULL;
-       lr->waiter = NULL;
-       recycleLockRecord(t, lr);
-
-       /* if we have been interrupted, throw the appropriate exception */
-
-       if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+       return threads_wait_with_timeout(thread, &wakeupTime);
 }
 
-/* notifyOneOrAll **************************************************************
 
-   Notify one thread or all threads waiting on the given object.
+/* threads_calc_absolute_time **************************************************
+
+   Calculate the absolute point in time a given number of ms and ns from now.
 
    IN:
-      t............the current thread
-         o............the object
-         one..........if true, only notify one thread
+      millis............milliseconds from now
+         nanos.............nanoseconds from now
+
+   OUT:
+      *tm...............receives the timespec of the absolute point in time
 
-   PRE-CONDITION:
-      The current thread must be the owner of the object's monitor.
-   
 *******************************************************************************/
 
-static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 {
-       monitorLockRecord *lr;
-       monitorLockRecord *wlr;
-       threadobject *wthread;
-
-       lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return);
-
-       /* { the thread t owns the lock record lr on the object o } */
-
-       /* for each waiter: */
-
-       for (wlr = lr->waiter; wlr; wlr = wlr->waiter) {
-
-               /* signal the waiting thread */
-
-               wthread = wlr->ownerThread;
-               pthread_mutex_lock(&wthread->waitLock);
-               if (wthread->isSleeping)
-                       pthread_cond_signal(&wthread->waitCond);
-               wthread->signaled = true;
-               pthread_mutex_unlock(&wthread->waitLock);
-
-               /* if we should only wake one, we are done */
-
-               if (one)
-                       break;
+       if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
+               struct timeval tv;
+               long nsec;
+               gettimeofday(&tv, NULL);
+               tv.tv_sec += millis / 1000;
+               millis %= 1000;
+               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;
        }
 }
 
-/* threadHoldsLock *************************************************************
-
-   Return true if the given thread owns the monitor of the given object.
-
-   IN:
-      t............the thread
-         o............the object
-   
-   RETURN VALUE:
-      true, if the thread is locking the object
-
-*******************************************************************************/
-
-bool threadHoldsLock(threadobject *t, java_objectheader *o)
-{
-       monitorLockRecord *lr;
-
-       lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-
-       return (lr->o == o) && (lr->ownerThread == t);
-}
 
-/* interruptThread *************************************************************
+/* threads_thread_interrupt ****************************************************
 
    Interrupt the given thread.
 
-   The thread gets the "waitCond" signal and 
+   The thread gets the "waitcond" signal and 
    its interrupted flag is set to true.
 
    IN:
@@ -1696,21 +1779,27 @@ bool threadHoldsLock(threadobject *t, java_objectheader *o)
 
 *******************************************************************************/
 
-void interruptThread(java_lang_VMThread *thread)
+void threads_thread_interrupt(threadobject *thread)
 {
-       threadobject *t = (threadobject*) thread;
+       /* Signal the thread a "waitcond" and tell it that it has been
+          interrupted. */
+
+       pthread_mutex_lock(&thread->waitmutex);
+
+       /* Interrupt blocking system call using a signal. */
+
+       pthread_kill(thread->tid, SIGHUP);
 
-       /* signal the thread a "waitCond" and tell it that it has been */
-       /* interrupted                                                 */
+       if (thread->sleeping)
+               pthread_cond_signal(&thread->waitcond);
 
-       pthread_mutex_lock(&t->waitLock);
-       if (t->isSleeping)
-               pthread_cond_signal(&t->waitCond);
-       t->interrupted = true;
-       pthread_mutex_unlock(&t->waitLock);
+       thread->interrupted = true;
+
+       pthread_mutex_unlock(&thread->waitmutex);
 }
 
-/* interruptedThread ***********************************************************
+
+/* threads_check_if_interrupted_and_reset **************************************
 
    Check if the current thread has been interrupted and reset the
    interruption flag.
@@ -1720,21 +1809,26 @@ void interruptThread(java_lang_VMThread *thread)
 
 *******************************************************************************/
 
-bool interruptedThread()
+bool threads_check_if_interrupted_and_reset(void)
 {
-       threadobject *t;
+       threadobject *thread;
        bool intr;
 
-       t = (threadobject*) THREADOBJECT;
+       thread = THREADOBJECT;
 
-       intr = t->interrupted;
+       /* get interrupted flag */
 
-       t->interrupted = false;
+       intr = thread->interrupted;
+
+       /* reset interrupted flag */
+
+       thread->interrupted = false;
 
        return intr;
 }
 
-/* isInterruptedThread *********************************************************
+
+/* threads_thread_has_been_interrupted *****************************************
 
    Check if the given thread has been interrupted
 
@@ -1746,64 +1840,44 @@ bool interruptedThread()
 
 *******************************************************************************/
 
-bool isInterruptedThread(java_lang_VMThread *thread)
+bool threads_thread_has_been_interrupted(threadobject *thread)
 {
-       threadobject *t;
-
-       t = (threadobject*) thread;
-
-       return t->interrupted;
+       return thread->interrupted;
 }
 
-/* thread_sleep ****************************************************************
+
+/* threads_sleep ***************************************************************
 
    Sleep the current thread for the specified amount of time.
 
 *******************************************************************************/
 
-void thread_sleep(s8 millis, s4 nanos)
+void threads_sleep(s8 millis, s4 nanos)
 {
-       threadobject       *t;
-       struct timespec    wakeupTime;
-       bool               wasinterrupted;
+       threadobject    *thread;
+       struct timespec  wakeupTime;
+       bool             wasinterrupted;
 
-       t = (threadobject *) THREADOBJECT;
+       thread = THREADOBJECT;
 
-       calcAbsoluteTime(&wakeupTime, millis, nanos);
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-       wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
+       wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
 
        if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+               exceptions_throw_interruptedexception();
 }
 
-void yieldThread()
-{
-       sched_yield();
-}
 
-void setPriorityThread(thread *t, s4 priority)
-{
-       nativethread *info = &((threadobject*) t->vmThread)->info;
-       threads_set_thread_priority(info->tid, priority);
-}
+/* threads_yield ***************************************************************
 
-void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
-{
-       threadobject *t = (threadobject*) THREADOBJECT;
-       monitorWait(t, o, millis, nanos);
-}
+   Yield to the scheduler.
 
-void signal_cond_for_object(java_objectheader *o)
-{
-       threadobject *t = (threadobject*) THREADOBJECT;
-       notifyOneOrAll(t, o, true);
-}
+*******************************************************************************/
 
-void broadcast_cond_for_object(java_objectheader *o)
+void threads_yield(void)
 {
-       threadobject *t = (threadobject*) THREADOBJECT;
-       notifyOneOrAll(t, o, false);
+       sched_yield();
 }
 
 
@@ -1816,58 +1890,97 @@ void broadcast_cond_for_object(java_objectheader *o)
 
 void threads_dump(void)
 {
-       threadobject       *tobj;
-       java_lang_VMThread *vmt;
-       nativethread       *nt;
-       java_lang_Thread   *t;
-       utf                *name;
+       threadobject     *thread;
+       java_lang_Thread *t;
+       utf              *name;
 
-       tobj = mainthreadobj;
+       thread = mainthreadobj;
+
+       /* XXX we should stop the world here */
 
        printf("Full thread dump CACAO "VERSION":\n");
 
        /* iterate over all started threads */
 
        do {
-               /* get thread objects */
+               /* get thread object */
 
-               vmt = &tobj->o;
-               nt  = &tobj->info;
-               t   = vmt->thread;
+               t = thread->object;
 
                /* the thread may be currently in initalization, don't print it */
 
-               if (t) {
+               if (t != NULL) {
                        /* get thread name */
 
+#if defined(ENABLE_JAVASE)
                        name = javastring_toutf(t->name, false);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+                       name = t->name;
+#endif
 
                        printf("\n\"");
-                       utf_display(name);
+                       utf_display_printable_ascii(name);
                        printf("\" ");
 
-                       if (t->daemon)
+                       if (thread->flags & THREAD_FLAG_DAEMON)
                                printf("daemon ");
 
 #if SIZEOF_VOID_P == 8
-                       printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
+                       printf("prio=%d tid=0x%016lx\n", t->priority, (ptrint) thread->tid);
 #else
-                       printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
+                       printf("prio=%d tid=0x%08lx\n", t->priority, (ptrint) thread->tid);
 #endif
 
-                       /* send SIGUSR1 to thread to print stacktrace */
+                       /* dump trace of thread */
+
+                       stacktrace_dump_trace(thread);
+               }
+
+               thread = thread->next;
+       } while ((thread != NULL) && (thread != mainthreadobj));
+}
+
+
+/* threads_table_dump *********************************************************
+
+   Dump the threads table for debugging purposes.
+
+   IN:
+      file..............stream to write to
+
+******************************************************************************/
+
+#if !defined(NDEBUG) && 0
+static void threads_table_dump(FILE *file)
+{
+       s4 i;
+       s4 size;
+       ptrint index;
+
+       pthread_mutex_lock(&threadlistlock);
 
-                       pthread_kill(nt->tid, SIGUSR1);
+       size = threads_table.size;
 
-                       /* sleep this thread a bit, so the signal can reach the thread */
+       fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
 
-                       thread_sleep(10, 0);
+       for (i=0; i<size; ++i) {
+               index = threads_table.table[i].nextfree;
+
+               fprintf(file, "%4d: ", i);
+
+               if (index < size) {
+                       fprintf(file, "free, nextfree = %d\n", (int) index);
                }
+               else {
+                       fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
+               }
+       }
 
-               tobj = tobj->info.next;
-       } while (tobj && (tobj != mainthreadobj));
-}
+       fprintf(file, "======== END OF THREADS TABLE ========\n");
 
+       pthread_mutex_unlock(&threadlistlock);
+}
+#endif
 
 /*
  * These are local overrides for various environment variables in Emacs.