* src/threads/native/threads.c (wakeWaiters): Renamed
[cacao.git] / src / threads / native / threads.c
index 0c62c57445dc262abac7c72310ae8fb4773e7d9b..5a3f032be461be98f5c1d048c7c259e98a8eabf5 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 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
+   Contact: cacao@cacaojvm.org
 
    Authors: Stefan Ring
 
    Changes: Christian Thalinger
+                       Edwin Steiner
 
-   $Id: threads.c 2517 2005-05-23 10:33:06Z twisti $
+   $Id: threads.c 4871 2006-05-03 23:04:30Z edwin $
 
 */
 
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <time.h>
 #include <errno.h>
 
-#include "codegen.h"
-#include "config.h"
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#ifndef USE_MD_THREAD_STUFF
+#include "machine-instr.h"
+#else
+#include "threads/native/generic-primitives.h"
+#endif
+
 #include "mm/boehm.h"
 #include "mm/memory.h"
 #include "native/native.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/loader.h"
+#include "vm/options.h"
 #include "vm/stringlocal.h"
-#include "vm/tables.h"
+#include "vm/vm.h"
 #include "vm/jit/asmpart.h"
 
-#include <pthread.h>
-#include <semaphore.h>
-
 #if !defined(__DARWIN__)
 #if defined(__LINUX__)
 #define GC_LINUX_THREADS
 #include "boehm-gc/include/gc.h"
 #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;
+#endif
+
+/******************************************************************************/
+/* Recursive Mutex Implementation for Darwin                                  */
+/******************************************************************************/
+
 #ifdef MUTEXSIM
 
 /* We need this for older MacOSX (10.1.x) */
@@ -99,22 +121,24 @@ static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
 
 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
 {
-       for (;;)
+       for (;;) {
                if (!m->count)
                {
                        pthread_mutex_lock(&m->mutex);
                        m->owner = pthread_self();
                        m->count++;
                        break;
-               } else {
-                       if (m->owner != pthread_self())
+               }
+               else {
+                       if (m->owner != pthread_self()) {
                                pthread_mutex_lock(&m->mutex);
-                       else
-                       {
+                       }
+                       else {
                                m->count++;
                                break;
                        }
                }
+       }
 }
 
 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
@@ -131,7 +155,100 @@ static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
 
 #endif /* MUTEXSIM */
 
-static void setPriority(pthread_t tid, int priority)
+/* threads_sem_init ************************************************************
+   Initialize a semaphore. Checks against errors and interruptions.
+
+   IN:
+       sem..............the semaphore to initialize
+          shared...........true if this semaphore will be shared between processes
+          value............the initial value for the semaphore
+   
+*******************************************************************************/
+
+void threads_sem_init(sem_t *sem, bool shared, int value)
+{
+       int r;
+
+       assert(sem);
+
+       do {
+               r = sem_init(sem, shared, value);
+               if (r == 0)
+                       return;
+       } while (errno == EINTR);
+
+       fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
+                       errno, strerror(errno));
+       abort();
+}
+
+/* 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)
+{
+       int r;
+
+       assert(sem);
+
+       do {
+               r = sem_wait(sem);
+               if (r == 0)
+                       return;
+       } while (errno == EINTR);
+
+       fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
+                       errno, strerror(errno));
+       abort();
+}
+
+/* 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)
+{
+       int r;
+
+       assert(sem);
+
+       /* unlike sem_wait, sem_post is not interruptible */
+
+       r = sem_post(sem);
+       if (r == 0)
+               return;
+
+       fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
+                       errno, strerror(errno));
+       abort();
+}
+
+/* threads_set_thread_priority *************************************************
+
+   Set the priority of the given thread.
+
+   IN:
+      tid..........thread id
+         priority.....priority to set
+
+******************************************************************************/
+
+static void threads_set_thread_priority(pthread_t tid, int priority)
 {
        struct sched_param schedp;
        int policy;
@@ -141,10 +258,9 @@ static void setPriority(pthread_t tid, int priority)
        pthread_setschedparam(tid, policy, &schedp);
 }
 
-#include "machine-instr.h"
 
-static struct avl_table *criticaltree;
-static threadobject *mainthreadobj;
+static avl_tree *criticaltree;
+threadobject *mainthreadobj;
 
 #ifndef HAVE___THREAD
 pthread_key_t tkey_threadinfo;
@@ -153,7 +269,6 @@ __thread threadobject *threadobj;
 #endif
 
 static pthread_mutex_rec_t compiler_mutex;
-static pthread_mutex_rec_t tablelock;
 
 void compiler_lock()
 {
@@ -165,17 +280,7 @@ void compiler_unlock()
        pthread_mutex_unlock_rec(&compiler_mutex);
 }
 
-void tables_lock()
-{
-    pthread_mutex_lock_rec(&tablelock);
-}
-
-void tables_unlock()
-{
-    pthread_mutex_unlock_rec(&tablelock);
-}
-
-static int criticalcompare(const void *pa, const void *pb, void *param)
+static s4 criticalcompare(const void *pa, const void *pb)
 {
        const threadcritnode *na = pa;
        const threadcritnode *nb = pb;
@@ -187,32 +292,45 @@ static int criticalcompare(const void *pa, const void *pb, void *param)
        return 0;
 }
 
+
 static const threadcritnode *findcritical(u1 *mcodeptr)
 {
-    struct avl_node *n = criticaltree->avl_root;
-    const threadcritnode *m = NULL;
+    avl_node *n;
+    const threadcritnode *m;
+
+    n = criticaltree->root;
+       m = NULL;
+
     if (!n)
         return NULL;
-    for (;;)
-    {
-        const threadcritnode *d = n->avl_data;
+
+    for (;;) {
+        const threadcritnode *d = n->data;
+
         if (mcodeptr == d->mcodebegin)
             return d;
+
         if (mcodeptr < d->mcodebegin) {
-            if (n->avl_link[0])
-                n = n->avl_link[0];
-            else
+            if (n->childs[0]) {
+                n = n->childs[0];
+                       }
+            else {
                 return m;
-        } else {
-            if (n->avl_link[1]) {
-                m = n->avl_data;
-                n = n->avl_link[1];
-            } else
-                return n->avl_data;
+                       }
+        }
+               else {
+            if (n->childs[1]) {
+                m = n->data;
+                n = n->childs[1];
+            }
+                       else {
+                return n->data;
+                       }
         }
     }
 }
 
+
 void thread_registercritical(threadcritnode *n)
 {
        avl_insert(criticaltree, n);
@@ -226,10 +344,13 @@ u1 *thread_checkcritical(u1 *mcodeptr)
 
 static void thread_addstaticcritical()
 {
+       /* XXX TWISTI: this is just a quick hack */
+#if defined(ENABLE_JIT)
        threadcritnode *n = &asm_criticalsections;
 
        while (n->mcodebegin)
                thread_registercritical(n++);
+#endif
 }
 
 static pthread_mutex_t threadlistlock;
@@ -267,11 +388,12 @@ static int cast_sendsignals(int sig, int count)
        threadobject *tobj = mainthreadobj;
        nativethread *infoself = THREADINFO;
 
-       if (count == 0)
+       if (count == 0) {
                do {
                        count++;
                        tobj = tobj->info.next;
                } while (tobj != mainthreadobj);
+       }
 
        do {
                nativethread *info = &tobj->info;
@@ -369,7 +491,7 @@ void cast_stopworld()
 #else
        count = cast_sendsignals(GC_signum1(), 0);
        for (i=0; i<count; i++)
-               sem_wait(&suspend_ack);
+               threads_sem_wait(&suspend_ack);
 #endif
        pthread_mutex_unlock(&threadlistlock);
 }
@@ -393,18 +515,21 @@ static void 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);
 #else
-       sem_post(&suspend_ack);
+       threads_sem_post(&suspend_ack);
 
        sig = GC_signum2();
        sigfillset(&sigs);
@@ -423,7 +548,11 @@ int cacao_suspendhandler(ucontext_t *ctx)
 }
 #endif
 
+#if !defined(ENABLE_JVMTI)
 static void setthreadobject(threadobject *thread)
+#else
+void setthreadobject(threadobject *thread)
+#endif
 {
 #if !defined(HAVE___THREAD)
        pthread_setspecific(tkey_threadinfo, thread);
@@ -432,33 +561,49 @@ static void setthreadobject(threadobject *thread)
 #endif
 }
 
+
+/* thread_setself **************************************************************
+
+   Return the threadobject of the current thread.
+   
+   XXX The return value type should be changed to a typed pointer.
+
+*******************************************************************************/
+
+void *thread_getself(void)
+{
+       return THREADOBJECT;
+}
+
+/* unlocked dummy record - avoids NULL checks */
 static monitorLockRecord *dummyLR;
 
 static void initPools();
 
-/*
- * Initialize threads.
- */
-void
-initThreadsEarly()
+
+/* thread_preinit **************************************************************
+
+   Do some early initialization of stuff required.
+
+*******************************************************************************/
+
+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. */
+       /* Allocate something so the garbage collector's signal handlers
+          are installed. */
        heap_allocate(1, false, NULL);
 
        mainthreadobj = NEW(threadobject);
@@ -469,63 +614,84 @@ initThreadsEarly()
        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 */
 
-       /* 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;
+       dummyLR->waiting = NULL;
+       dummyLR->incharge = dummyLR;
+
+       /* we need a working dummyLR before initializing the critical
+          section tree */
+
+    criticaltree = avl_create(&criticalcompare);
+
+       thread_addstaticcritical();
+       threads_sem_init(&suspend_ack, 0, 0);
 }
 
+
 static pthread_attr_t threadattr;
 
 static void freeLockRecordPools(lockRecordPool *);
 
-void
-initThreads(u1 *stackbottom)
+
+/* threads_init ****************************************************************
+
+   Initializes the threads required by the JVM: main, finalizer.
+
+*******************************************************************************/
+
+bool threads_init(u1 *stackbottom)
 {
-       classinfo *threadclass;
-       java_lang_String *threadname;
-       java_lang_Thread *mainthread;
+       java_lang_String      *threadname;
+       java_lang_Thread      *mainthread;
        java_lang_ThreadGroup *threadgroup;
-       threadobject *tempthread = mainthreadobj;
-       methodinfo *method;
+       threadobject          *tempthread;
+       methodinfo            *method;
 
-       if (!load_class_bootstrap(utf_new_char("java/lang/VMThread"),&threadclass))
-               throw_exception_exit();
-       if (!threadclass)
-               throw_exception_exit();
-       if (!link_class(threadclass))
-               throw_exception_exit();
+       tempthread = mainthreadobj;
 
        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);
+       /* 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);
+
+       /* create a VMThread */
+
+       mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
 
        if (!mainthreadobj)
-               throw_exception_exit();
+               return false;
 
        FREE(tempthread, threadobject);
+
        initThread(&mainthreadobj->o);
 
        setthreadobject(mainthreadobj);
 
        initLocks();
+
        mainthreadobj->info.next = mainthreadobj;
        mainthreadobj->info.prev = mainthreadobj;
 
+#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;
+       }
+#endif
+
        threadname = javastring_new(utf_new_char("main"));
 
-       /* Allocate and init ThreadGroup */
+       /* allocate and init ThreadGroup */
 
        threadgroup = (java_lang_ThreadGroup *)
                native_new_and_init(class_java_lang_ThreadGroup);
@@ -533,34 +699,36 @@ initThreads(u1 *stackbottom)
        if (!threadgroup)
                throw_exception_exit();
 
-       /* Create a Thread */
-       if (!load_class_bootstrap(utf_new_char("java/lang/Thread"),&threadclass))
-               throw_exception_exit();
-       mainthread = (java_lang_Thread*) builtin_new(threadclass);
-       mainthreadobj->o.thread = mainthread;
+       /* create a Thread */
+
+       mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
        if (!mainthread)
                throw_exception_exit();
 
-       /* Call Thread constructor */
-       method = class_resolveclassmethod(threadclass,
+       mainthreadobj->o.thread = mainthread;
+
+       /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+
+       method = class_resolveclassmethod(class_java_lang_Thread,
                                                                          utf_init,
                                                                          utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
-                                                                         threadclass,
+                                                                         class_java_lang_Thread,
                                                                          true);
 
        if (!method)
-               throw_exception_exit();
+               return false;
+
+       (void) vm_call_method(method, (java_objectheader *) mainthread,
+                                                 mainthreadobj, threadname, 5, false);
 
-       asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
        if (*exceptionptr)
-               throw_exception_exit();
+               return false;
 
        mainthread->group = threadgroup;
-       /* XXX This is a hack because the fourth argument was omitted */
-       mainthread->daemon = false;
 
-       /* Add mainthread to ThreadGroup */
+       /* add mainthread to ThreadGroup */
+
        method = class_resolveclassmethod(class_java_lang_ThreadGroup,
                                                                          utf_new_char("addThread"),
                                                                          utf_new_char("(Ljava/lang/Thread;)V"),
@@ -568,18 +736,25 @@ initThreads(u1 *stackbottom)
                                                                          true);
 
        if (!method)
-               throw_exception_exit();
+               return false;
+
+       (void) vm_call_method(method, (java_objectheader *) threadgroup,
+                                                 mainthread);
 
-       asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
        if (*exceptionptr)
-               throw_exception_exit();
+               return false;
 
-       setPriority(pthread_self(), 5);
+       threads_set_thread_priority(pthread_self(), 5);
 
        pthread_attr_init(&threadattr);
        pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
+
+       /* everything's ok */
+
+       return true;
 }
 
+
 void initThread(java_lang_VMThread *t)
 {
        threadobject *thread = (threadobject*) t;
@@ -598,94 +773,218 @@ void initThread(java_lang_VMThread *t)
 
 static void initThreadLocks(threadobject *);
 
+
+/* startupinfo *****************************************************************
+
+   Struct used to pass info from threads_start_thread to 
+   threads_startup_thread.
+
+******************************************************************************/
+
 typedef struct {
-       threadobject *thread;
-       sem_t *psem;
+       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 void *threadstartup(void *t)
+
+/* threads_startup_thread ******************************************************
+
+   Thread startup function called by pthread_create.
+
+   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)
 {
-       startupinfo *startup = t;
-       threadobject *thread = startup->thread;
-       sem_t *psem = startup->psem;
-       nativethread *info = &thread->info;
+       startupinfo  *startup;
+       threadobject *thread;
+       sem_t        *psem;
+       nativethread *info;
        threadobject *tnext;
-       methodinfo *method;
+       methodinfo   *method;
+       functionptr   function;
+
+#if defined(ENABLE_INTRP)
+       u1 *intrp_thread_stack;
+
+       /* create interpreter stack */
+
+       if (opt_intrp) {
+               intrp_thread_stack = (u1 *) alloca(opt_stacksize);
+               MSET(intrp_thread_stack, 0, u1, opt_stacksize);
+       } else {
+               intrp_thread_stack = NULL;
+       }
+#endif
+
+       /* get passed startupinfo structure and the values in there */
+
+       startup = t;
+       t = NULL; /* make sure it's not used wrongly */
+
+       thread   = startup->thread;
+       function = startup->function;
+       psem     = startup->psem;
+
+       info = &thread->info;
+
+       /* 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. */
+       threads_sem_wait(startup->psem_first);
+
+       /* set the thread object */
 
-       t = NULL;
 #if defined(__DARWIN__)
        info->mach_thread = mach_thread_self();
 #endif
        setthreadobject(thread);
 
+       /* insert the thread into the threadlist */
+
        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);
 
+       /* init data structures of this thread */
+
        initThreadLocks(thread);
 
+       /* tell threads_startup_thread that we registered ourselves */
+       /* CAUTION: *startup becomes invalid with this!             */
+
        startup = NULL;
-       sem_post(psem);
+       threads_sem_post(psem);
 
-       setPriority(info->tid, thread->o.thread->priority);
-       sched_yield();
+       /* set our priority */
 
-       /* Find the run()V method and call it */
-       method = class_resolveclassmethod(thread->o.header.vftbl->class,
-                                                                         utf_new_char("run"),
-                                                                         utf_new_char("()V"),
-                                                                         thread->o.header.vftbl->class,
-                                                                         true);
+       threads_set_thread_priority(info->tid, thread->o.thread->priority);
 
-       /* if method != NULL, we had not exception */
-       if (method) {
-               asm_calljavafunction(method, thread, NULL, NULL, NULL);
+#if defined(ENABLE_INTRP)
+       /* set interpreter stack */
 
-       } else {
-               throw_exception();
+       if (opt_intrp)
+               THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
+#endif
+
+       /* find and run the Thread.run()V method if no other function was passed */
+
+       if (function == NULL) {
+               method = class_resolveclassmethod(thread->o.header.vftbl->class,
+                                                                                 utf_run,
+                                                                                 utf_void__void,
+                                                                                 thread->o.header.vftbl->class,
+                                                                                 true);
+
+               if (!method)
+                       throw_exception();
+
+               (void) vm_call_method(method, (java_objectheader *) thread);
+
+       }
+       else {
+               /* 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. */
+       /* 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);
 
+       /* remove thread from thread list, do this inside a lock */
+
        pthread_mutex_lock(&threadlistlock);
        info->next->info.prev = info->prev;
        info->prev->info.next = info->next;
        pthread_mutex_unlock(&threadlistlock);
 
+       /* reset thread id (lock on joinMutex? TWISTI) */
+
        pthread_mutex_lock(&info->joinMutex);
        info->tid = 0;
        pthread_mutex_unlock(&info->joinMutex);
+
+       /* tell everyone that a thread has finished */
+
        pthread_cond_broadcast(&info->joinCond);
 
        return NULL;
 }
 
-void startThread(thread *t)
+
+/* threads_start_thread ********************************************************
+
+   Start a thread in the JVM.
+
+   IN:
+      t............the java.lang.Thread object
+         function.....function to run in the new thread. NULL means that the
+                      "run" method of the object `t` should be called
+
+******************************************************************************/
+
+void threads_start_thread(thread *t, functionptr function)
 {
-       nativethread *info = &((threadobject*) t->vmThread)->info;
-       sem_t sem;
-       startupinfo startup;
+       nativethread *info;
+       sem_t         sem;
+       sem_t         sem_first;
+       startupinfo   startup;
+
+       info = &((threadobject *) t->vmThread)->info;
+
+       /* fill startupinfo structure passed by pthread_create to
+        * threads_startup_thread */
 
-       startup.thread = (threadobject*) t->vmThread;
-       startup.psem = &sem;
+       startup.thread     = (threadobject*) t->vmThread;
+       startup.function   = function;       /* maybe we don't call Thread.run()V */
+       startup.psem       = &sem;
+       startup.psem_first = &sem_first;
 
-       sem_init(&sem, 0, 0);
-       
-       if (pthread_create(&info->tid, &threadattr, threadstartup, &startup)) {
+       threads_sem_init(&sem, 0, 0);
+       threads_sem_init(&sem_first, 0, 0);
+
+       /* create the thread */
+
+       if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
+                                          &startup)) {
                log_text("pthread_create failed");
                assert(0);
        }
 
-       /* Wait here until the thread has entered itself into the thread list */
-       sem_wait(&sem);
+       /* signal that pthread_create has returned, so info->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);
 }
 
+
 /* At the end of the program, we wait for all running non-daemon threads to die
  */
 
@@ -724,23 +1023,12 @@ static void initLockRecord(monitorLockRecord *r, threadobject *t)
        r->o = NULL;
        r->waiter = NULL;
        r->incharge = (monitorLockRecord *) &dummyLR;
-       r->waiting = false;
-       sem_init(&r->queueSem, 0, 0);
+       r->waiting = NULL;
+       threads_sem_init(&r->queueSem, 0, 0);
        pthread_mutex_init(&r->resolveLock, NULL);
        pthread_cond_init(&r->resolveWait, NULL);
 }
 
-/* No lock record must ever be destroyed because there may still be references
- * to it.
-
-static void destroyLockRecord(monitorLockRecord *r)
-{
-       sem_destroy(&r->queueSem);
-       pthread_mutex_destroy(&r->resolveLock);
-       pthread_cond_destroy(&r->resolveWait);
-}
-*/
-
 void initLocks()
 {
        initThreadLocks(mainthreadobj);
@@ -769,8 +1057,8 @@ static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
 
 #define INITIALLOCKRECORDS 8
 
-static pthread_mutex_t pool_lock;
-static lockRecordPool *global_pool;
+pthread_mutex_t pool_lock;
+lockRecordPool *global_pool;
 
 static void initPools()
 {
@@ -786,9 +1074,12 @@ static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
                global_pool = pool->header.next;
                pthread_mutex_unlock(&pool_lock);
 
-               for (i=0; i < pool->header.size; i++)
+               for (i=0; i < pool->header.size; i++) {
                        pool->lr[i].ownerThread = t;
-               
+                       pool->lr[i].nextFree = &pool->lr[i+1];
+               }
+               pool->lr[i-1].nextFree = NULL;
+
                return pool;
        }
        pthread_mutex_unlock(&pool_lock);
@@ -810,7 +1101,10 @@ static void freeLockRecordPools(lockRecordPool *pool)
 
 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
 {
-       monitorLockRecord *r = t->ee.firstLR;
+       monitorLockRecord *r;
+
+       assert(t);
+       r = t->ee.firstLR;
 
        if (!r) {
                int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
@@ -820,19 +1114,36 @@ static monitorLockRecord *allocLockRecordSimple(threadobject *t)
                r = &pool->lr[0];
                t->ee.numlr += pool->header.size;
        }
-       
+
        t->ee.firstLR = r->nextFree;
+#ifndef NDEBUG
+       r->nextFree = NULL; /* in order to find invalid uses of nextFree */
+#endif
        return r;
 }
 
 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
 {
+       assert(t);
+       assert(r);
+       assert(r->ownerThread == t);
+       assert(r->nextFree == NULL);
+
        r->nextFree = t->ee.firstLR;
        t->ee.firstLR = r;
 }
 
+/* initObjectLock **************************************************************
+
+   Initialize the monitor pointer of the given object. The monitor gets
+   initialized to an unlocked state.
+
+*******************************************************************************/
+
 void initObjectLock(java_objectheader *o)
 {
+       assert(o);
+
        o->monitorPtr = dummyLR;
 }
 
@@ -855,8 +1166,10 @@ 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);
+
+       if (lr->o == o)
+               threads_sem_wait(&lr->queueSem);
+
        atomic_add(&lr->queuers, -1);
 }
 
@@ -867,66 +1180,137 @@ static void freeLockRecord(monitorLockRecord *lr)
        MEMORY_BARRIER();
        q = lr->queuers;
        while (q--)
-               sem_post(&lr->queueSem);
+               threads_sem_post(&lr->queueSem);
 }
 
-static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
+static inline void handleWaiter(monitorLockRecord *newlr,
+                                                               monitorLockRecord *curlr,
+                                                               java_objectheader *o)
 {
-       if (lr->waiting)
-               mlr->waiter = lr;
+       /* if the current lock record is used for waiting on the object */
+       /* `o`, then record it as a waiter in the new lock record       */
+
+       if (curlr->waiting == o)
+               newlr->waiter = curlr;
 }
 
+/* monitorEnter ****************************************************************
+
+   Acquire the monitor of the given object. If the current thread already
+   owns the monitor, the lock counter is simply increased.
+
+   This function blocks until it can acquire the monitor.
+
+   IN:
+      t............the current thread
+         o............the object of which to enter the monitor
+
+   RETURN VALUE:
+      the new lock record of the object when it has been entered
+
+*******************************************************************************/
+
 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
 {
        for (;;) {
                monitorLockRecord *lr = o->monitorPtr;
                if (lr->o != o) {
-                       monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
+                       /* 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) {
-                                       handleWaiter(mlr, lr);
+                                       /* the object still refers to the same lock record */
+                                       /* got it! */
+                                       handleWaiter(mlr, lr, o);
                                        return mlr;
                                }
-                       } else {
+                       } 
+                       else {
+                               /* no, it's another lock record */
+                               /* if we don't own the old record, set incharge XXX */
                                if (lr->ownerThread != t)
                                        mlr->incharge = lr;
+
+                               /* if the object still refers to lr, replace it by the new mlr */
                                MEMORY_BARRIER_BEFORE_ATOMIC();
-                               nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
+                               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) {
-                                       handleWaiter(mlr, lr);
+                                       /* 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);
-                               handleWaiter(mlr, lr);
+
+                               /* 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 {
+               } 
+               else {
+                       /* the lock record is for the object we want */
+
                        if (lr->ownerThread == t) {
+                               /* we own it already, just recurse */
                                lr->lockCount++;
                                return lr;
                        }
+
+                       /* it's locked. we wait and then try again */
                        queueOnLockRecord(lr, o);
                }
        }
 }
 
-static void wakeWaiters(monitorLockRecord *lr)
+/* threads_wake_waiters ********************************************************
+
+   For each lock record in the given waiter list, post the queueSem
+   once for each queuer of the lock record.
+
+   IN:
+      lr...........the head of the waiter list
+
+*******************************************************************************/
+
+static void threads_wake_waiters(monitorLockRecord *lr)
 {
+       monitorLockRecord *tmplr;
+       s4 q;
+
+       /* move it to a local variable (Stefan commented this especially.
+        * Might be important somehow...) */
+
+       tmplr = lr;
+
        do {
-               int q = lr->queuers;
+               q = tmplr->queuers;
+
                while (q--)
-                       sem_post(&lr->queueSem);
-               lr = lr->waiter;
-       } while (lr);
+                       threads_sem_post(&tmplr->queueSem);
+
+               tmplr = tmplr->waiter;
+       } while (tmplr != NULL && tmplr != lr); /* this breaks cycles to lr */
 }
 
 #define GRAB_LR(lr,t) \
@@ -936,82 +1320,211 @@ static void wakeWaiters(monitorLockRecord *lr)
 
 #define CHECK_MONITORSTATE(lr,t,mo,a) \
     if (lr->o != mo || lr->ownerThread != t) { \
-               *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
+               *exceptionptr = new_illegalmonitorstateexception(); \
                a; \
        }
 
+/* monitorExit *****************************************************************
+
+   Decrement the counter of a (currently owned) monitor. If the counter
+   reaches zero, release the monitor.
+
+   If the current thread is not the owner of the monitor, an 
+   IllegalMonitorState exception is thrown.
+
+   IN:
+      t............the current thread
+         o............the object of which to exit the monitor
+
+   RETURN VALUE:
+      true.........everything ok,
+         false........an exception has been thrown
+
+*******************************************************************************/
+
 bool monitorExit(threadobject *t, java_objectheader *o)
 {
-       monitorLockRecord *lr = o->monitorPtr;
+       monitorLockRecord *lr;
+
+       lr = o->monitorPtr;
        GRAB_LR(lr, t);
        CHECK_MONITORSTATE(lr, t, o, return false);
+
+       /* { the current thread `t` owns the lock record `lr` on object `o` } */
+
        if (lr->lockCount > 1) {
+               /* we had locked this one recursively. just decrement, it will */
+               /* still be locked. */
                lr->lockCount--;
                return true;
        }
+
+       /* we are going to unlock and recycle this lock record */
+
        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;
+                       nlr->waiter = wlr; /* XXX is it ok to overwrite the nlr->waiter field like that? */
                        STORE_ORDER_BARRIER();
-               } else
-                       wakeWaiters(wlr);
+               }
+               else {
+                       threads_wake_waiters(wlr);
+               }
                lr->waiter = NULL;
        }
+
+       /* unlock and throw away this lock record */
        freeLockRecord(lr);
        recycleLockRecord(t, lr);
        return true;
 }
 
-static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
+/* threads_remove_waiter *******************************************************
+
+   Remove a waiter lock record from the waiter list of the given lock record
+
+   IN:
+      lr...........the lock record holding the waiter list
+         toremove.....the record to remove from the list
+
+*******************************************************************************/
+
+static void threads_remove_waiter(monitorLockRecord *lr,
+                                                                 monitorLockRecord *toremove)
 {
        do {
-               if (lr->waiter == wlr) {
-                       lr->waiter = wlr->waiter;
+               if (lr->waiter == toremove) {
+                       lr->waiter = toremove->waiter;
                        break;
                }
                lr = lr->waiter;
-       } while (lr);
+       } while (lr); /* XXX need to break cycle? */
 }
 
-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) {
+               fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
+                               errno, strerror(errno));
+               abort();
+       }
+
+       /* 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 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
+         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 *t,
+                                                                         struct timespec *wakeupTime)
 {
        bool wasinterrupted;
 
+       /* acquire the waitLock */
+
        pthread_mutex_lock(&t->waitLock);
+
+       /* mark us as sleeping */
+
        t->isSleeping = true;
-       if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
-               while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
+
+       /* wait on waitCond */
+
+       if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
+               /* with timeout */
+               while (!t->interrupted && !t->signaled
+                          && threads_current_time_is_earlier_than(wakeupTime))
+               {
                        pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
-       else
+               }
+       }
+       else {
+               /* no timeout */
                while (!t->interrupted && !t->signaled)
                        pthread_cond_wait(&t->waitCond, &t->waitLock);
+       }
+
+       /* check if we were interrupted */
+
        wasinterrupted = t->interrupted;
+
+       /* reset all flags */
+
        t->interrupted = false;
        t->signaled = false;
        t->isSleeping = false;
+
+       /* release the waitLock */
+
        pthread_mutex_unlock(&t->waitLock);
+
        return wasinterrupted;
 }
 
+
 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
 {
        if (millis || nanos) {
@@ -1023,103 +1536,242 @@ 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;
        }
 }
 
+/* monitorWait *****************************************************************
+
+   Wait on an object for a given (maximum) amount of time.
+
+   IN:
+      t............the current thread
+         o............the object
+         millis.......milliseconds of timeout
+         nanos........nanoseconds of 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 wasinterrupted;
        struct timespec wakeupTime;
-       monitorLockRecord *mlr, *lr = o->monitorPtr;
+       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)
-               wakeWaiters(lr->waiter);
-       lr->waiting = true;
+               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);
-       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
-       mlr = monitorEnter(t, o);
-       removeFromWaiters(mlr, lr);
-       mlr->lockCount = lr->lockCount;
+
+       /* 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;
+
+       /* recylce the old lock record */
+
        lr->lockCount = 1;
-       lr->waiting = false;
+       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);
 }
 
+/* notifyOneOrAll **************************************************************
+
+   Notify one thread or all threads waiting on the given object.
+
+   IN:
+      t............the current thread
+         o............the object
+         one..........if true, only notify one thread
+
+   PRE-CONDITION:
+      The current thread must be the owner of the object's monitor.
+   
+*******************************************************************************/
+
 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
 {
-       monitorLockRecord *lr = o->monitorPtr;
+       monitorLockRecord *lr;
+       monitorLockRecord *wlr;
+       threadobject *wthread;
+
+       lr = o->monitorPtr;
        GRAB_LR(lr, t);
        CHECK_MONITORSTATE(lr, t, o, return);
-       do {
-               threadobject *wthread;
-               monitorLockRecord *wlr = lr->waiter;
-               if (!wlr)
-                       break;
+
+       /* { 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);
-               lr = wlr;
-       } while (!one);
+
+               /* if we should only wake one, we are done */
+
+               if (one)
+                       break;
+       }
 }
 
+/* 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 = o->monitorPtr;
+       monitorLockRecord *lr;
+
+       lr = o->monitorPtr;
        GRAB_LR(lr, t);
-       return lr && lr->o == o && lr->ownerThread == t;
+
+       return (lr->o == o) && (lr->ownerThread == t);
 }
 
+/* interruptThread *************************************************************
+
+   Interrupt the given thread.
+
+   The thread gets the "waitCond" signal and 
+   its interrupted flag is set to true.
+
+   IN:
+      thread............the thread to interrupt
+
+*******************************************************************************/
+
 void interruptThread(java_lang_VMThread *thread)
 {
        threadobject *t = (threadobject*) thread;
 
-       t->interrupted = true;
+       /* signal the thread a "waitCond" and tell it that it has been */
+       /* interrupted                                                 */
+
        pthread_mutex_lock(&t->waitLock);
        if (t->isSleeping)
                pthread_cond_signal(&t->waitCond);
+       t->interrupted = true;
        pthread_mutex_unlock(&t->waitLock);
 }
 
+/* interruptedThread ***********************************************************
+
+   Check if the current thread has been interrupted and reset the
+   interruption flag.
+
+   RETURN VALUE:
+      true, if the current thread had been interrupted
+
+*******************************************************************************/
+
 bool interruptedThread()
 {
-       threadobject *t = (threadobject*) THREADOBJECT;
-       bool intr = t->interrupted;
+       threadobject *t;
+       bool intr;
+
+       t = (threadobject*) THREADOBJECT;
+
+       intr = t->interrupted;
+
        t->interrupted = false;
+
        return intr;
 }
 
+/* isInterruptedThread *********************************************************
+
+   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 isInterruptedThread(java_lang_VMThread *thread)
 {
-       threadobject *t = (threadobject*) thread;
+       threadobject *t;
+
+       t = (threadobject*) thread;
+
        return t->interrupted;
 }
 
-void sleepThread(s8 millis, s4 nanos)
+/* thread_sleep ****************************************************************
+
+   Sleep the current thread for the specified amount of time.
+
+*******************************************************************************/
+
+void thread_sleep(s8 millis, s4 nanos)
 {
-       bool wasinterrupted;
-       threadobject *t = (threadobject*) THREADOBJECT;
-       monitorLockRecord *lr;
-       struct timespec wakeupTime;
+       threadobject       *t;
+       struct timespec    wakeupTime;
+       bool               wasinterrupted;
+
+       t = (threadobject *) THREADOBJECT;
+
        calcAbsoluteTime(&wakeupTime, millis, nanos);
 
-       lr = allocLockRecordSimple(t);
-       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
-       recycleLockRecord(t, lr);
+       wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
 
        if (wasinterrupted)
                *exceptionptr = new_exception(string_java_lang_InterruptedException);
@@ -1133,13 +1785,13 @@ void yieldThread()
 void setPriorityThread(thread *t, s4 priority)
 {
        nativethread *info = &((threadobject*) t->vmThread)->info;
-       setPriority(info->tid, priority);
+       threads_set_thread_priority(info->tid, priority);
 }
 
-void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
+void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
 {
        threadobject *t = (threadobject*) THREADOBJECT;
-       monitorWait(t, o, time, nanos);
+       monitorWait(t, o, millis, nanos);
 }
 
 void signal_cond_for_object(java_objectheader *o)
@@ -1155,6 +1807,68 @@ void broadcast_cond_for_object(java_objectheader *o)
 }
 
 
+/* threads_dump ****************************************************************
+
+   Dumps info for all threads running in the JVM. This function is
+   called when SIGQUIT (<ctrl>-\) is sent to CACAO.
+
+*******************************************************************************/
+
+void threads_dump(void)
+{
+       threadobject       *tobj;
+       java_lang_VMThread *vmt;
+       nativethread       *nt;
+       java_lang_Thread   *t;
+       utf                *name;
+
+       tobj = mainthreadobj;
+
+       printf("Full thread dump CACAO "VERSION":\n");
+
+       /* iterate over all started threads */
+
+       do {
+               /* get thread objects */
+
+               vmt = &tobj->o;
+               nt  = &tobj->info;
+               t   = vmt->thread;
+
+               /* the thread may be currently in initalization, don't print it */
+
+               if (t) {
+                       /* get thread name */
+
+                       name = javastring_toutf(t->name, false);
+
+                       printf("\n\"");
+                       utf_display(name);
+                       printf("\" ");
+
+                       if (t->daemon)
+                               printf("daemon ");
+
+#if SIZEOF_VOID_P == 8
+                       printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
+#else
+                       printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
+#endif
+
+                       /* send SIGUSR1 to thread to print stacktrace */
+
+                       pthread_kill(nt->tid, SIGUSR1);
+
+                       /* sleep this thread a bit, so the signal can reach the thread */
+
+                       thread_sleep(10, 0);
+               }
+
+               tobj = tobj->info.next;
+       } while (tobj && (tobj != mainthreadobj));
+}
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -1166,4 +1880,5 @@ void broadcast_cond_for_object(java_objectheader *o)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */