* src/threads/native/threads.c (threads_init) [!ENABLE_GC_CACAO]: Fixed bug for
[cacao.git] / src / threads / native / threads.c
index 3678dc65c673c0b4463e5795d0de1ff863f8c7c3..c159e9ccc017000b3496a312568b9c5a0dcea816 100644 (file)
@@ -1,9 +1,9 @@
 /* src/threads/native/threads.c - native threads support
 
-   Copyright (C) 1996-2005 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
+   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
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   $Id: threads.c 7478 2007-03-08 02:59:31Z michi $
 
-   Authors: Stefan Ring
-
-   Changes: Christian Thalinger
+*/
 
-   $Id: threads.c 2899 2005-07-04 20:41:28Z twisti $
 
-*/
+#include "config.h"
 
+/* XXX cleanup these includes */
 
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <errno.h>
 
-#include "codegen.h"
-#include "config.h"
-#include "mm/boehm.h"
+#include <pthread.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
+# include "machine-instr.h"
+#else
+# include "threads/native/generic-primitives.h"
+#endif
+
+#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/stringlocal.h"
-#include "vm/tables.h"
+#include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
-#include <pthread.h>
-#include <semaphore.h>
+#include "vmcore/options.h"
 
 #if !defined(__DARWIN__)
-#if defined(__LINUX__)
-#define GC_LINUX_THREADS
-#elif defined(__MIPS__)
-#define GC_IRIX_THREADS
+# 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
-#include "boehm-gc/include/gc.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
 #endif
 
-#ifdef MUTEXSIM
+#if defined(__DARWIN__)
+/* Darwin has no working semaphore implementation.  This one is taken
+   from Boehm-GC. */
 
-/* We need this for older MacOSX (10.1.x) */
+/*
+   This is a very simple semaphore implementation for darwin. It
+   is implemented in terms of pthreads calls so it isn't async signal
+   safe. This isn't a problem because signals aren't used to
+   suspend threads on darwin.
+*/
+   
+static int sem_init(sem_t *sem, int pshared, int value)
+{
+       if (pshared)
+               assert(0);
 
-typedef struct {
-       pthread_mutex_t mutex;
-       pthread_t owner;
-       int count;
-} pthread_mutex_rec_t;
+       sem->value = value;
+    
+       if (pthread_mutex_init(&sem->mutex, NULL) < 0)
+               return -1;
 
-static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_init(&m->mutex, NULL);
-       m->count = 0;
+       if (pthread_cond_init(&sem->cond, NULL) < 0)
+               return -1;
+
+       return 0;
 }
 
-static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
+static int sem_post(sem_t *sem)
 {
-       pthread_mutex_destroy(&m->mutex);
+       if (pthread_mutex_lock(&sem->mutex) < 0)
+               return -1;
+
+       sem->value++;
+
+       if (pthread_cond_signal(&sem->cond) < 0) {
+               pthread_mutex_unlock(&sem->mutex);
+               return -1;
+       }
+
+       if (pthread_mutex_unlock(&sem->mutex) < 0)
+               return -1;
+
+       return 0;
 }
 
-static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
+static int sem_wait(sem_t *sem)
 {
-       for (;;)
-               if (!m->count)
-               {
-                       pthread_mutex_lock(&m->mutex);
-                       m->owner = pthread_self();
-                       m->count++;
-                       break;
-               } else {
-                       if (m->owner != pthread_self())
-                               pthread_mutex_lock(&m->mutex);
-                       else
-                       {
-                               m->count++;
-                               break;
-                       }
-               }
+       if (pthread_mutex_lock(&sem->mutex) < 0)
+               return -1;
+
+       while (sem->value == 0) {
+               pthread_cond_wait(&sem->cond, &sem->mutex);
+       }
+
+       sem->value--;
+
+       if (pthread_mutex_unlock(&sem->mutex) < 0)
+               return -1;    
+
+       return 0;
 }
 
-static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
+static int sem_destroy(sem_t *sem)
 {
-       if (!--m->count)
-               pthread_mutex_unlock(&m->mutex);
+       if (pthread_cond_destroy(&sem->cond) < 0)
+               return -1;
+
+       if (pthread_mutex_destroy(&sem->mutex) < 0)
+               return -1;
+
+       return 0;
 }
+#endif /* defined(__DARWIN__) */
 
-#else /* MUTEXSIM */
 
-#define pthread_mutex_lock_rec pthread_mutex_lock
-#define pthread_mutex_unlock_rec pthread_mutex_unlock
-#define pthread_mutex_rec_t pthread_mutex_t
+/* internally used constants **************************************************/
 
-#endif /* MUTEXSIM */
+/* CAUTION: Do not change these values. Boehm GC code depends on them.        */
+#define STOPWORLD_FROM_GC               1
+#define STOPWORLD_FROM_CLASS_NUMBERING  2
 
-static void setPriority(pthread_t tid, int priority)
-{
-       struct sched_param schedp;
-       int policy;
+#define THREADS_INITIAL_TABLE_SIZE      8
 
-       pthread_getschedparam(tid, &policy, &schedp);
-       schedp.sched_priority = priority;
-       pthread_setschedparam(tid, policy, &schedp);
-}
 
-#include "machine-instr.h"
+/* startupinfo *****************************************************************
+
+   Struct used to pass info from threads_start_thread to 
+   threads_startup_thread.
+
+******************************************************************************/
+
+typedef struct {
+       threadobject *thread;      /* threadobject for this thread             */
+       functionptr   function;    /* function to run in the new thread        */
+       sem_t        *psem;        /* signals when thread has been entered     */
+                                  /* in the thread list                       */
+       sem_t        *psem_first;  /* signals when pthread_create has returned */
+} startupinfo;
+
 
-static struct avl_table *criticaltree;
-static threadobject *mainthreadobj;
+/* prototypes *****************************************************************/
 
-#ifndef HAVE___THREAD
-pthread_key_t tkey_threadinfo;
+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
-__thread threadobject *threadobj;
+pthread_key_t threads_current_threadobject_key;
 #endif
 
-static pthread_mutex_rec_t compiler_mutex;
-static pthread_mutex_rec_t tablelock;
+/* global threads table                                                       */
+static threads_table_t threads_table;
 
-void compiler_lock()
-{
-       pthread_mutex_lock_rec(&compiler_mutex);
-}
+/* global compiler mutex                                                      */
+static pthread_mutex_t compiler_mutex;
 
-void compiler_unlock()
-{
-       pthread_mutex_unlock_rec(&compiler_mutex);
-}
+/* global mutex for changing the thread list                                  */
+static pthread_mutex_t threadlistlock;
 
-void tables_lock()
-{
-    pthread_mutex_lock_rec(&tablelock);
-}
+/* global mutex for stop-the-world                                            */
+static pthread_mutex_t stopworldlock;
+
+/* 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
+
+
+/* threads_sem_init ************************************************************
+   Initialize a semaphore. Checks against errors and interruptions.
+
+   IN:
+       sem..............the semaphore to initialize
+          shared...........true if this semaphore will be shared between processes
+          value............the initial value for the semaphore
+   
+*******************************************************************************/
 
-void tables_unlock()
+void threads_sem_init(sem_t *sem, bool shared, int value)
 {
-    pthread_mutex_unlock_rec(&tablelock);
+       int r;
+
+       assert(sem);
+
+       do {
+               r = sem_init(sem, shared, value);
+               if (r == 0)
+                       return;
+       } while (errno == EINTR);
+
+       vm_abort("sem_init failed: %s", strerror(errno));
 }
 
-static int criticalcompare(const void *pa, const void *pb, void *param)
+
+/* threads_sem_wait ************************************************************
+   Wait for a semaphore, non-interruptible.
+
+   IMPORTANT: Always use this function instead of `sem_wait` directly, as
+              `sem_wait` may be interrupted by signals!
+  
+   IN:
+       sem..............the semaphore to wait on
+   
+*******************************************************************************/
+
+void threads_sem_wait(sem_t *sem)
 {
-       const threadcritnode *na = pa;
-       const threadcritnode *nb = pb;
+       int r;
 
-       if (na->mcodebegin < nb->mcodebegin)
-               return -1;
-       if (na->mcodebegin > nb->mcodebegin)
-               return 1;
-       return 0;
+       assert(sem);
+
+       do {
+               r = sem_wait(sem);
+               if (r == 0)
+                       return;
+       } while (errno == EINTR);
+
+       vm_abort("sem_wait failed: %s", strerror(errno));
 }
 
-static const threadcritnode *findcritical(u1 *mcodeptr)
+
+/* threads_sem_post ************************************************************
+   Increase the count of a semaphore. Checks for errors.
+
+   IN:
+       sem..............the semaphore to increase the count of
+   
+*******************************************************************************/
+
+void threads_sem_post(sem_t *sem)
 {
-    struct avl_node *n = criticaltree->avl_root;
-    const threadcritnode *m = NULL;
-    if (!n)
-        return NULL;
-    for (;;)
-    {
-        const threadcritnode *d = n->avl_data;
-        if (mcodeptr == d->mcodebegin)
-            return d;
-        if (mcodeptr < d->mcodebegin) {
-            if (n->avl_link[0])
-                n = n->avl_link[0];
-            else
-                return m;
-        } else {
-            if (n->avl_link[1]) {
-                m = n->avl_data;
-                n = n->avl_link[1];
-            } else
-                return n->avl_data;
-        }
-    }
+       int r;
+
+       assert(sem);
+
+       /* unlike sem_wait, sem_post is not interruptible */
+
+       r = sem_post(sem);
+       if (r == 0)
+               return;
+
+       vm_abort("sem_post failed: %s", strerror(errno));
 }
 
-void thread_registercritical(threadcritnode *n)
+
+/* compiler_lock ***************************************************************
+
+   Enter the compiler lock.
+
+******************************************************************************/
+
+void compiler_lock(void)
 {
-       avl_insert(criticaltree, n);
+       pthread_mutex_lock(&compiler_mutex);
 }
 
-u1 *thread_checkcritical(u1 *mcodeptr)
+
+/* compiler_unlock *************************************************************
+
+   Release the compiler lock.
+
+******************************************************************************/
+
+void compiler_unlock(void)
 {
-       const threadcritnode *n = findcritical(mcodeptr);
-       return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
+       pthread_mutex_unlock(&compiler_mutex);
 }
 
-static void thread_addstaticcritical()
-{
-       threadcritnode *n = &asm_criticalsections;
 
-       while (n->mcodebegin)
-               thread_registercritical(n++);
-}
+/* lock_stopworld **************************************************************
 
-static pthread_mutex_t threadlistlock;
+   Enter the stopworld lock, specifying why the world shall be stopped.
 
-static pthread_mutex_t stopworldlock;
-volatile int stopworldwhere;
+   IN:
+      where........ STOPWORLD_FROM_GC              (1) from within GC
+                    STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
 
-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
+******************************************************************************/
 
-/*
- * where - 1 from within GC
-           2 class numbering
- */
 void lock_stopworld(int where)
 {
        pthread_mutex_lock(&stopworldlock);
        stopworldwhere = where;
 }
 
-void unlock_stopworld()
+
+/* unlock_stopworld ************************************************************
+
+   Release the stopworld lock.
+
+******************************************************************************/
+
+void unlock_stopworld(void)
 {
        stopworldwhere = 0;
        pthread_mutex_unlock(&stopworldlock);
@@ -261,97 +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)
+       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);
@@ -359,52 +501,72 @@ 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++)
-               sem_wait(&suspend_ack);
+       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;
-       
+
+       /* XXX TWISTI: this is just a quick hack */
+#if defined(ENABLE_JIT)
        thread_restartcriticalsection(ctx);
+#endif
 
        /* Do as Boehm does. On IRIX a condition variable is used for wake-up
           (not POSIX async-safe). */
 #if defined(__IRIX__)
        pthread_mutex_lock(&suspend_ack_lock);
-       sem_post(&suspend_ack);
+       threads_sem_post(&suspend_ack);
        pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
        pthread_mutex_unlock(&suspend_ack_lock);
+#elif defined(__CYGWIN__)
+       /* TODO */
+       assert(0);
 #else
-       sem_post(&suspend_ack);
+       threads_sem_post(&suspend_ack);
 
        sig = GC_signum2();
        sigfillset(&sigs);
@@ -413,633 +575,1182 @@ 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
 
-static void setthreadobject(threadobject *thread)
+#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 ********************************************
 
-   XXX
+   Return the threadobject of the current thread.
+   
+   RETURN VALUE:
+       the current threadobject * (an instance of java.lang.Thread)
 
 *******************************************************************************/
 
-void *thread_getself(void)
+threadobject *threads_get_current_threadobject(void)
 {
-       return pthread_getspecific(tkey_threadinfo);
+       return THREADOBJECT;
 }
 
 
-static monitorLockRecord *dummyLR;
+/* threads_preinit *************************************************************
 
-static void initPools();
+   Do some early initialization of stuff required.
 
-/*
- * Initialize threads.
- */
-void
-initThreadsEarly()
+   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_mutex_init(&tablelock, &mutexattr);
        pthread_mutexattr_destroy(&mutexattr);
-#else
-       pthread_mutex_init_rec(&compiler_mutex);
-       pthread_mutex_init_rec(&tablelock);
-#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();
-
-    criticaltree = avl_create(criticalcompare, NULL, NULL);
-       thread_addstaticcritical();
-       sem_init(&suspend_ack, 0, 0);
-
-       /* Every newly created object's monitorPtr points here so we save a check
-        * against NULL */
-       dummyLR = NEW(monitorLockRecord);
-       dummyLR->o = NULL;
-       dummyLR->ownerThread = NULL;
-       dummyLR->waiting = false;
-}
+       threads_set_current_threadobject(mainthreadobj);
 
-static pthread_attr_t threadattr;
+       threads_sem_init(&suspend_ack, 0, 0);
 
-static void freeLockRecordPools(lockRecordPool *);
+       /* initialize the threads table */
 
-void
-initThreads(u1 *stackbottom)
-{
-       classinfo *threadclass;
-       java_lang_String *threadname;
-       java_lang_Thread *mainthread;
-       java_lang_ThreadGroup *threadgroup;
-       threadobject *tempthread = mainthreadobj;
-       methodinfo *method;
+       threads_table_init();
 
-       if (!(threadclass = load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
-               throw_exception_exit();
+       /* initialize subsystems */
 
-       if (!threadclass)
-               throw_exception_exit();
+       lock_init();
 
-       if (!link_class(threadclass))
-               throw_exception_exit();
+       critical_init();
+}
 
-       freeLockRecordPools(mainthreadobj->ee.lrpool);
-       /* 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 */
-       threadclass->instancesize = sizeof(threadobject);
 
-       /* Create a VMThread */
-       mainthreadobj = (threadobject *) builtin_new(threadclass);
+/* threads_init ****************************************************************
 
-       if (!mainthreadobj)
-               throw_exception_exit();
+   Initializes the threads required by the JVM: main, finalizer.
 
-       FREE(tempthread, threadobject);
-       initThread(&mainthreadobj->o);
+*******************************************************************************/
 
-       setthreadobject(mainthreadobj);
+bool threads_init(void)
+{
+       java_lang_String      *threadname;
+       threadobject          *tempthread;
+       java_objectheader     *o;
 
-       initLocks();
-       mainthreadobj->info.next = mainthreadobj;
-       mainthreadobj->info.prev = mainthreadobj;
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *threadgroup;
+       methodinfo            *m;
+       java_lang_Thread      *t;
+#endif
 
-       threadname = javastring_new(utf_new_char("main"));
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
 
-       /* Allocate and init ThreadGroup */
+       tempthread = mainthreadobj;
 
-       threadgroup = (java_lang_ThreadGroup *)
-               native_new_and_init(class_java_lang_ThreadGroup);
+       /* 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 (!threadgroup)
-               throw_exception_exit();
+#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. */
 
-       /* Create a Thread */
+       class_java_lang_Thread->instancesize = sizeof(threadobject);
+#endif
 
-       if (!(threadclass = load_class_bootstrap(utf_new_char("java/lang/Thread"))))
-               throw_exception_exit();
+       /* get methods we need in this file */
 
-       mainthread = (java_lang_Thread*) builtin_new(threadclass);
-       mainthreadobj->o.thread = mainthread;
+#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 (!mainthread)
-               throw_exception_exit();
+       if (method_thread_init == NULL)
+               return false;
 
-       /* Call Thread constructor */
-       method = class_resolveclassmethod(threadclass,
-                                                                         utf_init,
-                                                                         utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
-                                                                         threadclass,
-                                                                         true);
+       /* 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 (!method)
-               throw_exception_exit();
+#if defined(ENABLE_GC_CACAO)
+       mainthreadobj = NEW(threadobject);
+#else
+       mainthreadobj = GCNEW(threadobject);
+#endif
 
-       asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
-       if (*exceptionptr)
-               throw_exception_exit();
+       if (mainthreadobj == NULL)
+               return false;
 
-       mainthread->group = threadgroup;
-       /* XXX This is a hack because the fourth argument was omitted */
-       mainthread->daemon = false;
+       /* create a java.lang.Thread for the main thread */
 
-       /* Add mainthread to ThreadGroup */
-       method = class_resolveclassmethod(class_java_lang_ThreadGroup,
-                                                                         utf_new_char("addThread"),
-                                                                         utf_new_char("(Ljava/lang/Thread;)V"),
-                                                                         class_java_lang_ThreadGroup,
-                                                                         true);
+       mainthreadobj->object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       if (!method)
-               throw_exception_exit();
+       if (mainthreadobj->object == NULL)
+               return false;
 
-       asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
-       if (*exceptionptr)
-               throw_exception_exit();
+       FREE(tempthread, threadobject);
 
-       setPriority(pthread_self(), 5);
+       threads_init_threadobject(mainthreadobj);
 
-       pthread_attr_init(&threadattr);
-       pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
-}
+       threads_set_current_threadobject(mainthreadobj);
 
-void initThread(java_lang_VMThread *t)
-{
-       threadobject *thread = (threadobject*) t;
-       nativethread *info = &thread->info;
-       info->tid = pthread_self();
-       /* TODO destroy all those things */
-       pthread_mutex_init(&info->joinMutex, NULL);
-       pthread_cond_init(&info->joinCond, NULL);
+       lock_init_execution_env(mainthreadobj);
 
-       pthread_mutex_init(&thread->waitLock, NULL);
-       pthread_cond_init(&thread->waitCond, NULL);
-       thread->interrupted = false;
-       thread->signaled = false;
-       thread->isSleeping = false;
-}
+       mainthreadobj->next = mainthreadobj;
+       mainthreadobj->prev = mainthreadobj;
 
-static void initThreadLocks(threadobject *);
+       threads_table_add(mainthreadobj);
 
-typedef struct {
-       threadobject *thread;
-       sem_t *psem;
-       sem_t *psem_first;
-} startupinfo;
+       /* mark main thread as Java thread */
 
-static void *threadstartup(void *t)
-{
-       startupinfo *startup = t;
-       threadobject *thread = startup->thread;
-       sem_t *psem = startup->psem;
-       nativethread *info = &thread->info;
-       threadobject *tnext;
-       methodinfo *method;
-
-       /* Seems like we've encountered a situation where info->tid was not set by
-        * pthread_create. We alleviate this problem by waiting for pthread_create
-        * to return. */
-       sem_wait(startup->psem_first);
+       mainthreadobj->flags = THREAD_FLAG_JAVA;
 
-       t = NULL;
-#if defined(__DARWIN__)
-       info->mach_thread = mach_thread_self();
+#if defined(ENABLE_INTRP)
+       /* create interpreter stack */
+
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
+       }
 #endif
-       setthreadobject(thread);
 
-       pthread_mutex_lock(&threadlistlock);
-       info->prev = mainthreadobj;
-       info->next = tnext = mainthreadobj->info.next;
-       mainthreadobj->info.next = thread;
-       tnext->info.prev = thread;
-       pthread_mutex_unlock(&threadlistlock);
+       threadname = javastring_new(utf_new_char("main"));
 
-       initThreadLocks(thread);
+#if defined(ENABLE_JAVASE)
+       /* allocate and init ThreadGroup */
 
-       startup = NULL;
-       sem_post(psem);
+       threadgroup = (java_lang_ThreadGroup *)
+               native_new_and_init(class_java_lang_ThreadGroup);
 
-       setPriority(info->tid, thread->o.thread->priority);
+       if (threadgroup == NULL)
+               throw_exception_exit();
+#endif
 
-       /* Find the run()V method and call it */
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread for the main thread */
 
-       method = class_resolveclassmethod(thread->o.header.vftbl->class,
-                                                                         utf_run,
-                                                                         utf_void__void,
-                                                                         thread->o.header.vftbl->class,
-                                                                         true);
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
-       if (!method)
-               throw_exception();
+       if (vmt == NULL)
+               throw_exception_exit();
 
-       asm_calljavafunction(method, thread, NULL, NULL, NULL);
+       /* set the thread */
 
-       /* Allow lock record pools to be used by other threads. They cannot be
-        * deleted so we'd better not waste them. */
-       freeLockRecordPools(thread->ee.lrpool);
+       vmt->thread = mainthreadobj->object;
+       vmt->vmdata = (java_lang_Object *) mainthreadobj;
 
-       pthread_mutex_lock(&threadlistlock);
-       info->next->info.prev = info->prev;
-       info->prev->info.next = info->next;
-       pthread_mutex_unlock(&threadlistlock);
+       /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+       o = (java_objectheader *) mainthreadobj->object;
 
-       pthread_mutex_lock(&info->joinMutex);
-       info->tid = 0;
-       pthread_mutex_unlock(&info->joinMutex);
-       pthread_cond_broadcast(&info->joinCond);
+       (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
+                                                 false);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       /* set the thread */
 
-       return NULL;
-}
+       mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
 
-void startThread(thread *t)
-{
-       nativethread *info = &((threadobject*) t->vmThread)->info;
-       sem_t sem;
-       sem_t sem_first;
-       startupinfo startup;
+       /* call public Thread(String name) */
 
-       startup.thread = (threadobject*) t->vmThread;
-       startup.psem = &sem;
-       startup.psem_first = &sem_first;
+       o = (java_objectheader *) mainthreadobj->object;
 
-       sem_init(&sem, 0, 0);
-       sem_init(&sem_first, 0, 0);
-       
-       if (pthread_create(&info->tid, &threadattr, threadstartup, &startup)) {
-               log_text("pthread_create failed");
-               assert(0);
+       (void) vm_call_method(method_thread_init, o, threadname);
+#endif
+
+       if (*exceptionptr)
+               return false;
+
+#if defined(ENABLE_JAVASE)
+       mainthreadobj->object->group = threadgroup;
+
+       /* add main thread to java.lang.ThreadGroup */
+
+       m = class_resolveclassmethod(class_java_lang_ThreadGroup,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
+
+       o = (java_objectheader *) threadgroup;
+       t = mainthreadobj->object;
+
+       (void) vm_call_method(m, o, t);
+
+       if (*exceptionptr)
+               return false;
+
+#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;
        }
-       sem_post(&sem_first);
 
-       /* Wait here until the thread has entered itself into the thread list */
-       sem_wait(&sem);
-       sem_destroy(&sem);
-       sem_destroy(&sem_first);
+       pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
+
+       /* everything's ok */
+
+       return true;
 }
 
-/* At the end of the program, we wait for all running non-daemon threads to die
- */
 
-static threadobject *findNonDaemon(threadobject *thread)
+/* threads_table_init *********************************************************
+
+   Initialize the global threads table.
+
+******************************************************************************/
+
+static void threads_table_init(void)
 {
-       while (thread != mainthreadobj) {
-               if (!thread->o.thread->daemon)
-                       return thread;
-               thread = thread->info.prev;
+       s4 size;
+       s4 i;
+
+       size = THREADS_INITIAL_TABLE_SIZE;
+
+       threads_table.size = size;
+       threads_table.table = MNEW(threads_table_entry_t, size);
+
+       /* link the entries in a freelist */
+
+       for (i=0; i<size; ++i) {
+               threads_table.table[i].nextfree = i+1;
        }
 
-       return NULL;
+       /* terminate the freelist */
+
+       threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
 }
 
-void joinAllThreads()
+
+/* threads_table_add **********************************************************
+
+   Add a thread to the global threads table. The index is entered in the
+   threadobject. The thinlock value for the thread is pre-computed.
+
+   IN:
+      thread............the thread to add
+
+   RETURN VALUE:
+      The table index for the newly added thread. This value has also been
+         entered in the threadobject.
+
+   PRE-CONDITION:
+      The caller must hold the threadlistlock!
+
+******************************************************************************/
+
+static s4 threads_table_add(threadobject *thread)
 {
-       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);
+       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;
        }
-       pthread_mutex_unlock(&threadlistlock);
-}
 
-static void initLockRecord(monitorLockRecord *r, threadobject *t)
-{
-       r->lockCount = 1;
-       r->ownerThread = t;
-       r->queuers = 0;
-       r->o = NULL;
-       r->waiter = NULL;
-       r->incharge = (monitorLockRecord *) &dummyLR;
-       r->waiting = false;
-       sem_init(&r->queueSem, 0, 0);
-       pthread_mutex_init(&r->resolveLock, NULL);
-       pthread_cond_init(&r->resolveWait, NULL);
-}
+       /* we must grow the table */
 
-/* No lock record must ever be destroyed because there may still be references
- * to it.
+       oldsize = threads_table.size;
+       newsize = oldsize * 2;
 
-static void destroyLockRecord(monitorLockRecord *r)
-{
-       sem_destroy(&r->queueSem);
-       pthread_mutex_destroy(&r->resolveLock);
-       pthread_cond_destroy(&r->resolveWait);
-}
-*/
+       threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
+                                                                  oldsize, newsize);
+       threads_table.size = newsize;
 
-void initLocks()
-{
-       initThreadLocks(mainthreadobj);
+       /* 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;
 }
 
-static void initThreadLocks(threadobject *thread)
+
+/* 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)
 {
-       thread->ee.firstLR = NULL;
-       thread->ee.lrpool = NULL;
-       thread->ee.numlr = 0;
+       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
 }
 
-static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
+
+/* threads_startup_thread ******************************************************
+
+   Thread startup function called by pthread_create.
+
+   Thread which have a startup.function != NULL are marked as internal
+   threads. All other threads are threated as normal Java threads.
+
+   NOTE: This function is not called directly by pthread_create. The Boehm GC
+         inserts its own GC_start_routine in between, which then calls
+                threads_startup.
+
+   IN:
+      t............the argument passed to pthread_create, ie. a pointer to
+                      a startupinfo struct. CAUTION: When the `psem` semaphore
+                                  is posted, the startupinfo struct becomes invalid! (It
+                                  is allocated on the stack of threads_start_thread.)
+
+******************************************************************************/
+
+static void *threads_startup_thread(void *t)
 {
-       lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
-       int i;
+       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;
+
+       /* create interpreter stack */
 
-       p->header.size = size;
-       for (i=0; i<size; i++) {
-               initLockRecord(&p->lr[i], thread);
-               p->lr[i].nextFree = &p->lr[i+1];
+       if (opt_intrp) {
+               intrp_thread_stack = GCMNEW(u1, opt_stacksize);
+               MSET(intrp_thread_stack, 0, u1, opt_stacksize);
        }
-       p->lr[i-1].nextFree = NULL;
-       return p;
-}
+       else
+               intrp_thread_stack = NULL;
+#endif
 
-#define INITIALLOCKRECORDS 8
+       /* get passed startupinfo structure and the values in there */
 
-static pthread_mutex_t pool_lock;
-static lockRecordPool *global_pool;
+       startup = t;
+       t = NULL; /* make sure it's not used wrongly */
 
-static void initPools()
-{
-       pthread_mutex_init(&pool_lock, NULL);
-}
+       thread   = startup->thread;
+       function = startup->function;
+       psem     = startup->psem;
 
-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;
-               
-               return pool;
+       /* 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);
+
+       /* set the thread object */
+
+#if defined(__DARWIN__)
+       thread->mach_thread = mach_thread_self();
+#endif
+       threads_set_current_threadobject(thread);
+
+       /* insert the thread into the threadlist and the threads table */
+
+       pthread_mutex_lock(&threadlistlock);
+
+       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 */
+
+       lock_init_execution_env(thread);
+
+       /* tell threads_startup_thread that we registered ourselves */
+       /* CAUTION: *startup becomes invalid with this!             */
+
+       startup = NULL;
+       threads_sem_post(psem);
+
+       /* set our priority */
+
+       threads_set_thread_priority(thread->tid, thread->object->priority);
+
+#if defined(ENABLE_INTRP)
+       /* set interpreter stack */
+
+       if (opt_intrp)
+               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) {
+               /* this is a normal Java thread */
+
+               thread->flags |= THREAD_FLAG_JAVA;
+
+#if defined(WITH_CLASSPATH_GNU)
+               /* We need to start the run method of
+                  java.lang.VMThread. Since this is a final class, we can use
+                  the class object directly. */
+
+               c   = class_java_lang_VMThread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+               c   = thread->object->header.vftbl->class;
+#endif
+
+               m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
+
+               if (m == NULL)
+                       throw_exception();
+
+               /* 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);
        }
-       pthread_mutex_unlock(&pool_lock);
+       else {
+               /* this is an internal thread */
 
-       return allocNewLockRecordPool(t, size);
-}
+               thread->flags |= THREAD_FLAG_INTERNAL;
 
-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);
-}
+               /* set ThreadMXBean variables */
 
-static monitorLockRecord *allocLockRecordSimple(threadobject *t)
-{
-       monitorLockRecord *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;
+               _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)();
        }
-       
-       t->ee.firstLR = r->nextFree;
-       return r;
-}
 
-static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
-{
-       r->nextFree = t->ee.firstLR;
-       t->ee.firstLR = r;
-}
+#if defined(ENABLE_JVMTI)
+       /* fire thread end event */
 
-void initObjectLock(java_objectheader *o)
-{
-       o->monitorPtr = dummyLR;
+       if (jvmti)
+               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
+
+       threads_detach_thread(thread);
+
+       /* set ThreadMXBean variables */
+
+       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
+
+       return NULL;
 }
 
 
-/* get_dummyLR *****************************************************************
+/* threads_start_javathread ***************************************************
 
-   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.
+   Start a thread in the JVM. Only the java thread object exists so far.
 
-*******************************************************************************/
+   IN:
+      object.....the java thread object java.lang.Thread
 
-monitorLockRecord *get_dummyLR(void)
+******************************************************************************/
+
+void threads_start_javathread(java_lang_Thread *object)
 {
-       return dummyLR;
-}
+       threadobject *thread;
 
+       /* create the vm internal threadobject */
 
-static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
-{
-       atomic_add(&lr->queuers, 1);
-       MEMORY_BARRIER_AFTER_ATOMIC();
-       while (lr->o == o)
-               sem_wait(&lr->queueSem);
-       atomic_add(&lr->queuers, -1);
+       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);
 }
 
-static void freeLockRecord(monitorLockRecord *lr)
+
+/* threads_start_thread ********************************************************
+
+   Start a thread in the JVM. Both (vm internal and java) thread objects exist.
+
+   IN:
+      thread.......the thread object
+         function.....function to run in the new thread. NULL means that the
+                      "run" method of the object `t` should be called
+
+******************************************************************************/
+
+void threads_start_thread(threadobject *thread, functionptr function)
 {
-       int q;
-       lr->o = NULL;
-       MEMORY_BARRIER();
-       q = lr->queuers;
-       while (q--)
-               sem_post(&lr->queueSem);
+       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     = thread;
+       startup.function   = function;       /* maybe we don't call Thread.run()V */
+       startup.psem       = &sem;
+       startup.psem_first = &sem_first;
+
+       threads_sem_init(&sem, 0, 0);
+       threads_sem_init(&sem_first, 0, 0);
+
+       /* initialize thread attribute object */
+
+       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(&(thread->tid), &attr, threads_startup_thread, &startup))
+               vm_abort("pthread_create failed: %s", strerror(errno));
+
+       /* signal that pthread_create has returned, so thread->tid is valid */
+
+       threads_sem_post(&sem_first);
+
+       /* wait here until the thread has entered itself into the thread list */
+
+       threads_sem_wait(&sem);
+
+       /* cleanup */
+
+       sem_destroy(&sem);
+       sem_destroy(&sem_first);
 }
 
-static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
+
+/* threads_set_thread_priority *************************************************
+
+   Set the priority of the given thread.
+
+   IN:
+      tid..........thread id
+         priority.....priority to set
+
+******************************************************************************/
+
+void threads_set_thread_priority(pthread_t tid, int priority)
 {
-       if (lr->waiting)
-               mlr->waiter = lr;
+       struct sched_param schedp;
+       int policy;
+
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
 }
 
-monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
+
+/* threads_attach_current_thread ***********************************************
+
+   Attaches the current thread to the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 {
-       for (;;) {
-               monitorLockRecord *lr = o->monitorPtr;
-               if (lr->o != o) {
-                       monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
-                       mlr->o = o;
-                       if (mlr == lr) {
-                               MEMORY_BARRIER();
-                               nlr = o->monitorPtr;
-                               if (nlr == lr) {
-                                       handleWaiter(mlr, lr);
-                                       return mlr;
-                               }
-                       } else {
-                               if (lr->ownerThread != t)
-                                       mlr->incharge = lr;
-                               MEMORY_BARRIER_BEFORE_ATOMIC();
-                               nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
-                       }
-                       if (nlr == lr) {
-                               if (mlr == lr || lr->o != o) {
-                                       handleWaiter(mlr, lr);
-                                       return mlr;
-                               }
-                               while (lr->o == o)
-                                       queueOnLockRecord(lr, o);
-                               handleWaiter(mlr, lr);
-                               return mlr;
-                       }
-                       freeLockRecord(mlr);
-                       recycleLockRecord(t, mlr);
-                       queueOnLockRecord(nlr, o);
-               } else {
-                       if (lr->ownerThread == t) {
-                               lr->lockCount++;
-                               return lr;
-                       }
-                       queueOnLockRecord(lr, o);
-               }
+       threadobject          *thread;
+       utf                   *u;
+       java_lang_String      *s;
+       java_objectheader     *o;
+       java_lang_Thread      *t;
+
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
+
+       /* create a vm internal thread object */
+
+       thread = NEW(threadobject);
+
+       if (thread == NULL)
+               return false;
+
+       /* create a java.lang.Thread object */
+
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       if (t == NULL)
+               return false;
+
+       thread->object = t;
+
+       threads_init_threadobject(thread);
+       threads_set_current_threadobject(thread);
+       lock_init_execution_env(thread);
+
+       /* insert the thread into the threadlist and the threads table */
+
+       pthread_mutex_lock(&threadlistlock);
+
+       thread->prev        = mainthreadobj;
+       thread->next        = mainthreadobj->next;
+       mainthreadobj->next = thread;
+       thread->next->prev  = thread;
+
+       threads_table_add(thread);
+
+       pthread_mutex_unlock(&threadlistlock);
+
+       /* mark thread as Java thread */
+
+       thread->flags = THREAD_FLAG_JAVA;
+
+       if (isdaemon)
+               thread->flags |= THREAD_FLAG_DAEMON;
+
+#if defined(ENABLE_INTRP)
+       /* create interpreter stack */
+
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
        }
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread object */
+
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+
+       if (vmt == NULL)
+               return false;
+
+       /* set the thread */
+
+       vmt->thread = t;
+       vmt->vmdata = (java_lang_Object *) thread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       t->vm_thread = (java_lang_Object *) thread;
+#endif
+
+       if (vm_aargs != NULL) {
+               u     = utf_new_char(vm_aargs->name);
+#if defined(ENABLE_JAVASE)
+               group = (java_lang_ThreadGroup *) vm_aargs->group;
+#endif
+       }
+       else {
+               u     = utf_null;
+#if defined(ENABLE_JAVASE)
+               group = mainthreadobj->object->group;
+#endif
+       }
+
+       s = javastring_new(u);
+
+       o = (java_objectheader *) thread->object;
+
+#if defined(WITH_CLASSPATH_GNU)
+       (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
+                                                 isdaemon);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       (void) vm_call_method(method_thread_init, o, s);
+#endif
+
+       if (*exceptionptr)
+               return false;
+
+#if defined(ENABLE_JAVASE)
+       /* store the thread group in the object */
+
+       thread->object->group = group;
+
+       /* add thread to given thread-group */
+
+       m = class_resolveclassmethod(group->header.vftbl->class,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
+
+       o = (java_objectheader *) group;
+
+       (void) vm_call_method(m, o, t);
+
+       if (*exceptionptr)
+               return false;
+#endif
+
+       return true;
 }
 
-static void wakeWaiters(monitorLockRecord *lr)
+
+/* threads_detach_thread *******************************************************
+
+   Detaches the passed thread from the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_detach_thread(threadobject *thread)
 {
-       do {
-               int q = lr->queuers;
-               while (q--)
-                       sem_post(&lr->queueSem);
-               lr = lr->waiter;
-       } while (lr);
-}
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+       java_objectheader     *o;
+       java_lang_Thread      *t;
+#endif
 
-#define GRAB_LR(lr,t) \
-    if (lr->ownerThread != t) { \
-               lr = lr->incharge; \
-       }
+       /* Allow lock record pools to be used by other threads. They
+          cannot be deleted so we'd better not waste them. */
+
+       /* XXX We have to find a new way to free lock records */
+       /*     with the new locking algorithm.                */
+       /* lock_record_free_pools(thread->ee.lockrecordpools); */
+
+       /* XXX implement uncaught exception stuff (like JamVM does) */
+
+#if defined(ENABLE_JAVASE)
+       /* remove thread from the thread group */
+
+       group = thread->object->group;
 
-#define CHECK_MONITORSTATE(lr,t,mo,a) \
-    if (lr->o != mo || lr->ownerThread != t) { \
-               *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
-               a; \
+       /* 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;
+
+               o = (java_objectheader *) group;
+               t = thread->object;
+
+               (void) vm_call_method(m, o, t);
+
+               if (*exceptionptr)
+                       return false;
        }
+#endif
+
+       /* remove thread from thread list and threads table, do this
+          inside a lock */
+
+       pthread_mutex_lock(&threadlistlock);
+
+       thread->next->prev = thread->prev;
+       thread->prev->next = thread->next;
+
+       threads_table_remove(thread);
+
+       pthread_mutex_unlock(&threadlistlock);
+
+       /* reset thread id (lock on joinmutex? TWISTI) */
+
+       pthread_mutex_lock(&(thread->joinmutex));
+       thread->tid = 0;
+       pthread_mutex_unlock(&(thread->joinmutex));
 
-bool monitorExit(threadobject *t, java_objectheader *o)
+       /* tell everyone that a thread has finished */
+
+       pthread_cond_broadcast(&(thread->joincond));
+
+       /* free the vm internal thread object */
+
+       FREE(thread, threadobject);
+
+       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)
 {
-       monitorLockRecord *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return false);
-       if (lr->lockCount > 1) {
-               lr->lockCount--;
-               return true;
-       }
-       if (lr->waiter) {
-               monitorLockRecord *wlr = lr->waiter;
-               if (o->monitorPtr != lr ||
-                       (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
-               {
-                       monitorLockRecord *nlr = o->monitorPtr;
-                       nlr->waiter = wlr;
-                       STORE_ORDER_BARRIER();
-               } else
-                       wakeWaiters(wlr);
-               lr->waiter = NULL;
+       while (thread != mainthreadobj) {
+               if (!(thread->flags & THREAD_FLAG_DAEMON))
+                       return thread;
+
+               thread = thread->prev;
        }
-       freeLockRecord(lr);
-       recycleLockRecord(t, lr);
-       return true;
+
+       return NULL;
 }
 
-static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
+
+/* threads_join_all_threads ****************************************************
+
+   Join all non-daemon threads.
+
+*******************************************************************************/
+
+void threads_join_all_threads(void)
 {
-       do {
-               if (lr->waiter == wlr) {
-                       lr->waiter = wlr->waiter;
-                       break;
-               }
-               lr = lr->waiter;
-       } while (lr);
+       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);
 }
 
-static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
+
+/* threads_timespec_earlier ****************************************************
+
+   Return true if timespec tv1 is earlier than timespec tv2.
+
+   IN:
+      tv1..........first timespec
+         tv2..........second timespec
+
+   RETURN VALUE:
+      true, if the first timespec is earlier
+
+*******************************************************************************/
+
+static inline bool threads_timespec_earlier(const struct timespec *tv1,
+                                                                                       const struct timespec *tv2)
 {
-       return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
+       return (tv1->tv_sec < tv2->tv_sec)
+                               ||
+               (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
 }
 
-static bool timeIsEarlier(const struct timespec *tv)
+
+/* threads_current_time_is_earlier_than ****************************************
+
+   Check if the current time is earlier than the given timespec.
+
+   IN:
+      tv...........the timespec to compare against
+
+   RETURN VALUE:
+      true, if the current time is earlier
+
+*******************************************************************************/
+
+static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 {
        struct timeval tvnow;
        struct timespec tsnow;
-       gettimeofday(&tvnow, NULL);
+
+       /* get current time */
+
+       if (gettimeofday(&tvnow, NULL) != 0)
+               vm_abort("gettimeofday failed: %s\n", strerror(errno));
+
+       /* convert it to a timespec */
+
        tsnow.tv_sec = tvnow.tv_sec;
        tsnow.tv_nsec = tvnow.tv_usec * 1000;
-       return timespec_less(&tsnow, tv);
+
+       /* compare current time with the given timespec */
+
+       return threads_timespec_earlier(&tsnow, tv);
 }
 
-bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
+
+/* threads_wait_with_timeout ***************************************************
+
+   Wait until the given point in time on a monitor until either
+   we are notified, we are interrupted, or the time is up.
+
+   IN:
+      t............the current thread
+         wakeupTime...absolute (latest) wakeup time
+                          If both tv_sec and tv_nsec are zero, this function
+                                          waits for an unlimited amount of time.
+
+   RETURN VALUE:
+      true.........if the wait has been interrupted,
+         false........if the wait was ended by notification or timeout
+
+*******************************************************************************/
+
+static bool threads_wait_with_timeout(threadobject *thread,
+                                                                         struct timespec *wakeupTime)
 {
        bool wasinterrupted;
 
-       pthread_mutex_lock(&t->waitLock);
-       t->isSleeping = true;
-       if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
-               while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
-                       pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
-       else
-               while (!t->interrupted && !t->signaled)
-                       pthread_cond_wait(&t->waitCond, &t->waitLock);
-       wasinterrupted = t->interrupted;
-       t->interrupted = false;
-       t->signaled = false;
-       t->isSleeping = false;
-       pthread_mutex_unlock(&t->waitLock);
+       /* acquire the waitmutex */
+
+       pthread_mutex_lock(&thread->waitmutex);
+
+       /* mark us as sleeping */
+
+       thread->sleeping = true;
+
+       /* wait on waitcond */
+
+       if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
+               /* with timeout */
+               while (!thread->interrupted && !thread->signaled
+                          && threads_current_time_is_earlier_than(wakeupTime))
+               {
+                       pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
+                                                                  wakeupTime);
+               }
+       }
+       else {
+               /* no timeout */
+               while (!thread->interrupted && !thread->signaled)
+                       pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
+       }
+
+       /* check if we were interrupted */
+
+       wasinterrupted = thread->interrupted;
+
+       /* reset all flags */
+
+       thread->interrupted = false;
+       thread->signaled    = false;
+       thread->sleeping    = false;
+
+       /* release the waitmutex */
+
+       pthread_mutex_unlock(&thread->waitmutex);
+
        return wasinterrupted;
 }
 
-static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
+
+/* threads_wait_with_timeout_relative ******************************************
+
+   Wait for the given maximum amount of time on a monitor until either
+   we are notified, we are interrupted, or the time is up.
+
+   IN:
+      t............the current thread
+         millis.......milliseconds to wait
+         nanos........nanoseconds to wait
+
+   RETURN VALUE:
+      true.........if the wait has been interrupted,
+         false........if the wait was ended by notification or timeout
+
+*******************************************************************************/
+
+bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
+                                                                               s4 nanos)
 {
-       if (millis || nanos) {
+       struct timespec wakeupTime;
+
+       /* calculate the the (latest) wakeup time */
+
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+       /* wait */
+
+       return threads_wait_with_timeout(thread, &wakeupTime);
+}
+
+
+/* threads_calc_absolute_time **************************************************
+
+   Calculate the absolute point in time a given number of ms and ns from now.
+
+   IN:
+      millis............milliseconds from now
+         nanos.............nanoseconds from now
+
+   OUT:
+      *tm...............receives the timespec of the absolute point in time
+
+*******************************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
+{
+       if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
                struct timeval tv;
                long nsec;
                gettimeofday(&tv, NULL);
@@ -1048,192 +1759,228 @@ static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
                nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
                tm->tv_sec = tv.tv_sec + nsec / 1000000000;
                tm->tv_nsec = nsec % 1000000000;
-       } else {
+       }
+       else {
                tm->tv_sec = 0;
                tm->tv_nsec = 0;
        }
 }
 
-void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
-{
-       bool wasinterrupted;
-       struct timespec wakeupTime;
-       monitorLockRecord *mlr, *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return);
 
-       calcAbsoluteTime(&wakeupTime, millis, nanos);
-       
-       if (lr->waiter)
-               wakeWaiters(lr->waiter);
-       lr->waiting = true;
-       STORE_ORDER_BARRIER();
-       freeLockRecord(lr);
-       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
-       mlr = monitorEnter(t, o);
-       removeFromWaiters(mlr, lr);
-       mlr->lockCount = lr->lockCount;
-       lr->lockCount = 1;
-       lr->waiting = false;
-       lr->waiter = NULL;
-       recycleLockRecord(t, lr);
+/* threads_thread_interrupt ****************************************************
 
-       if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
-}
+   Interrupt the given thread.
 
-static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
-{
-       monitorLockRecord *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       CHECK_MONITORSTATE(lr, t, o, return);
-       do {
-               threadobject *wthread;
-               monitorLockRecord *wlr = lr->waiter;
-               if (!wlr)
-                       break;
-               wthread = wlr->ownerThread;
-               pthread_mutex_lock(&wthread->waitLock);
-               if (wthread->isSleeping)
-                       pthread_cond_signal(&wthread->waitCond);
-               wthread->signaled = true;
-               pthread_mutex_unlock(&wthread->waitLock);
-               lr = wlr;
-       } while (!one);
-}
+   The thread gets the "waitcond" signal and 
+   its interrupted flag is set to true.
 
-bool threadHoldsLock(threadobject *t, java_objectheader *o)
-{
-       monitorLockRecord *lr = o->monitorPtr;
-       GRAB_LR(lr, t);
-       /* The reason why we have to check against NULL is that
-        * dummyLR->incharge == NULL */
-       return lr && lr->o == o && lr->ownerThread == t;
-}
+   IN:
+      thread............the thread to interrupt
+
+*******************************************************************************/
 
-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. */
 
-       t->interrupted = true;
-       pthread_mutex_lock(&t->waitLock);
-       if (t->isSleeping)
-               pthread_cond_signal(&t->waitCond);
-       pthread_mutex_unlock(&t->waitLock);
+       pthread_mutex_lock(&thread->waitmutex);
+
+       /* Interrupt blocking system call using a signal. */
+
+       pthread_kill(thread->tid, SIGHUP);
+
+       if (thread->sleeping)
+               pthread_cond_signal(&thread->waitcond);
+
+       thread->interrupted = true;
+
+       pthread_mutex_unlock(&thread->waitmutex);
 }
 
-bool interruptedThread()
+
+/* threads_check_if_interrupted_and_reset **************************************
+
+   Check if the current thread has been interrupted and reset the
+   interruption flag.
+
+   RETURN VALUE:
+      true, if the current thread had been interrupted
+
+*******************************************************************************/
+
+bool threads_check_if_interrupted_and_reset(void)
 {
-       threadobject *t = (threadobject*) THREADOBJECT;
-       bool intr = t->interrupted;
-       t->interrupted = false;
+       threadobject *thread;
+       bool intr;
+
+       thread = THREADOBJECT;
+
+       /* get interrupted flag */
+
+       intr = thread->interrupted;
+
+       /* reset interrupted flag */
+
+       thread->interrupted = false;
+
        return intr;
 }
 
-bool isInterruptedThread(java_lang_VMThread *thread)
+
+/* threads_thread_has_been_interrupted *****************************************
+
+   Check if the given thread has been interrupted
+
+   IN:
+      t............the thread to check
+
+   RETURN VALUE:
+      true, if the given thread had been interrupted
+
+*******************************************************************************/
+
+bool threads_thread_has_been_interrupted(threadobject *thread)
 {
-       threadobject *t = (threadobject*) thread;
-       return t->interrupted;
+       return thread->interrupted;
 }
 
-void sleepThread(s8 millis, s4 nanos)
+
+/* threads_sleep ***************************************************************
+
+   Sleep the current thread for the specified amount of time.
+
+*******************************************************************************/
+
+void threads_sleep(s8 millis, s4 nanos)
 {
-       bool wasinterrupted;
-       threadobject *t = (threadobject*) THREADOBJECT;
-       monitorLockRecord *lr;
-       struct timespec wakeupTime;
-       calcAbsoluteTime(&wakeupTime, millis, nanos);
+       threadobject    *thread;
+       struct timespec  wakeupTime;
+       bool             wasinterrupted;
+
+       thread = THREADOBJECT;
 
-       lr = allocLockRecordSimple(t);
-       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
-       recycleLockRecord(t, lr);
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+       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;
-       setPriority(info->tid, priority);
-}
+/* threads_yield ***************************************************************
 
-void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
-{
-       threadobject *t = (threadobject*) THREADOBJECT;
-       monitorWait(t, o, time, 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();
 }
 
 
-/* thread_dump *****************************************************************
+/* threads_dump ****************************************************************
 
    Dumps info for all threads running in the JVM. This function is
    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
 
 *******************************************************************************/
 
-void thread_dump(void)
+void threads_dump(void)
 {
-       threadobject       *tobj;
-       nativethread       *nt;
-       java_lang_VMThread *vmt;
-       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 */
+
+               t = thread->object;
 
-               nt  = &tobj->info;
-               vmt = &tobj->o;
-               t   = vmt->thread;
+               /* the thread may be currently in initalization, don't print it */
 
-               /* get thread name */
+               if (t != NULL) {
+                       /* get thread name */
 
-               name = javastring_toutf(t->name, false);
+#if defined(ENABLE_JAVASE)
+                       name = javastring_toutf(t->name, false);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+                       name = t->name;
+#endif
+
+                       printf("\n\"");
+                       utf_display_printable_ascii(name);
+                       printf("\" ");
+
+                       if (thread->flags & THREAD_FLAG_DAEMON)
+                               printf("daemon ");
 
-               printf("\n\"");
-               utf_display(name);
 #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 */
 
-               pthread_kill(nt->tid, SIGUSR1);
+                       stacktrace_dump_trace(thread);
+               }
 
-               /* sleep this thread a bit, so the signal can reach the thread */
+               thread = thread->next;
+       } while ((thread != NULL) && (thread != mainthreadobj));
+}
 
-               sleepThread(10, 0);
 
-               tobj = tobj->info.next;
-       } while (tobj != mainthreadobj);
-}
+/* threads_table_dump *********************************************************
+
+   Dump the threads table for debugging purposes.
+
+   IN:
+      file..............stream to write to
+
+******************************************************************************/
+
+#if !defined(NDEBUG) && 0
+static void threads_table_dump(FILE *file)
+{
+       s4 i;
+       s4 size;
+       ptrint index;
+
+       pthread_mutex_lock(&threadlistlock);
+
+       size = threads_table.size;
 
+       fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
+
+       for (i=0; i<size; ++i) {
+               index = threads_table.table[i].nextfree;
+
+               fprintf(file, "%4d: ", i);
+
+               if (index < size) {
+                       fprintf(file, "free, nextfree = %d\n", (int) index);
+               }
+               else {
+                       fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
+               }
+       }
+
+       fprintf(file, "======== END OF THREADS TABLE ========\n");
+
+       pthread_mutex_unlock(&threadlistlock);
+}
+#endif
 
 /*
  * These are local overrides for various environment variables in Emacs.
@@ -1246,4 +1993,5 @@ void thread_dump(void)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */