almost all required function implemented - first integration with jdwp - nothing...
[cacao.git] / src / threads / native / threads.c
index 4c780d43016460e5e91c57c6e65ecad124f12422..08a0c420fc4626dacf53f4a3803a93ceb6ea783f 100644 (file)
@@ -1,6 +1,37 @@
-#include "global.h"
+/* 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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   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.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Stefan Ring
+
+   Changes: Christian Thalinger
+
+   $Id: threads.c 3570 2005-11-04 16:58:36Z motse $
+
+*/
 
-#if defined(NATIVE_THREADS)
 
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <errno.h>
 
+#include <pthread.h>
+#include <semaphore.h>
+
 #include "config.h"
-#include "thread.h"
-#include "codegen.h"
-#include "locks.h"
-#include "tables.h"
-#include "native.h"
-#include "loader.h"
-#include "builtin.h"
-#include "asmpart.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "toolbox/avl.h"
-#include "mm/boehm.h"
+#include "vm/types.h"
 
-#include "nat/java_lang_Object.h"
-#include "nat/java_lang_Throwable.h"
-#include "nat/java_lang_Thread.h"
-#include "nat/java_lang_ThreadGroup.h"
+#ifndef USE_MD_THREAD_STUFF
+#include "machine-instr.h"
+#else
+#include "threads/native/generic-primitives.h"
+#endif
 
-#include <pthread.h>
-#include <semaphore.h>
+#include "cacao/cacao.h"
+#include "mm/boehm.h"
+#include "mm/memory.h"
+#include "native/native.h"
+#include "native/include/java_lang_Object.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"
+#include "threads/native/threads.h"
+#include "toolbox/avl.h"
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
 
+#if !defined(__DARWIN__)
 #if defined(__LINUX__)
 #define GC_LINUX_THREADS
-#include "../mm/boehm-gc/include/gc.h"
+#elif defined(__MIPS__)
+#define GC_IRIX_THREADS
+#endif
+#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
 
 #ifdef MUTEXSIM
 
+/* We need this for older MacOSX (10.1.x) */
+
 typedef struct {
        pthread_mutex_t mutex;
        pthread_t owner;
@@ -92,10 +146,19 @@ static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
 
 #endif /* MUTEXSIM */
 
-#include "machine-instr.h"
+static void setPriority(pthread_t tid, int priority)
+{
+       struct sched_param schedp;
+       int policy;
+
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
+}
+
 
 static struct avl_table *criticaltree;
-static threadobject *mainthreadobj;
+threadobject *mainthreadobj;
 
 #ifndef HAVE___THREAD
 pthread_key_t tkey_threadinfo;
@@ -189,6 +252,10 @@ static pthread_mutex_t stopworldlock;
 volatile int stopworldwhere;
 
 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
@@ -248,20 +315,26 @@ static void cast_darwinstop()
                        kern_return_t r;
 
                        r = thread_suspend(thread);
-                       if (r != KERN_SUCCESS)
-                               panic("thread_suspend failed");
+                       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)
-                               panic("thread_get_state failed");
+                       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)
-                               panic("thread_set_state failed");
+                       if (r != KERN_SUCCESS) {
+                               log_text("thread_set_state failed");
+                               assert(0);
+                       }
                }
                tobj = tobj->info.next;
        } while (tobj != mainthreadobj);
@@ -276,9 +349,14 @@ static void cast_darwinresume()
                nativethread *info = &tobj->info;
                if (info != infoself)
                {
+                       mach_port_t thread = info->mach_thread;
+                       kern_return_t r;
+
                        r = thread_resume(thread);
-                       if (r != KERN_SUCCESS)
-                               panic("thread_resume failed");
+                       if (r != KERN_SUCCESS) {
+                               log_text("thread_resume failed");
+                               assert(0);
+                       }
                }
                tobj = tobj->info.next;
        } while (tobj != mainthreadobj);
@@ -286,6 +364,15 @@ static void cast_darwinresume()
 
 #endif
 
+#if defined(__MIPS__)
+static void cast_irixresume()
+{
+       pthread_mutex_lock(&suspend_ack_lock);
+       pthread_cond_broadcast(&suspend_cond);
+       pthread_mutex_unlock(&suspend_ack_lock);
+}
+#endif
+
 void cast_stopworld()
 {
        int count, i;
@@ -306,6 +393,8 @@ void cast_startworld()
        pthread_mutex_lock(&threadlistlock);
 #if defined(__DARWIN__)
        cast_darwinresume();
+#elif defined(__MIPS__)
+       cast_irixresume();
 #else
        cast_sendsignals(GC_signum2(), -1);
 #endif
@@ -321,12 +410,21 @@ static void sigsuspend_handler(ucontext_t *ctx)
        
        thread_restartcriticalsection(ctx);
 
+       /* 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);
+       pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
+       pthread_mutex_unlock(&suspend_ack_lock);
+#else
        sem_post(&suspend_ack);
 
        sig = GC_signum2();
        sigfillset(&sigs);
        sigdelset(&sigs, sig);
        sigsuspend(&sigs);
+#endif
 }
 
 int cacao_suspendhandler(ucontext_t *ctx)
@@ -348,11 +446,31 @@ static void setthreadobject(threadobject *thread)
 #endif
 }
 
-/*
- * Initialize threads.
- */
-void
-initThreadsEarly()
+
+/* thread_setself **************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+void *thread_getself(void)
+{
+       return pthread_getspecific(tkey_threadinfo);
+}
+
+
+static monitorLockRecord *dummyLR;
+
+static void initPools();
+
+
+/* thread_preinit **************************************************************
+
+   Do some early initialization of stuff required.
+
+*******************************************************************************/
+
+void threads_preinit(void)
 {
 #ifndef MUTEXSIM
        pthread_mutexattr_t mutexattr;
@@ -369,95 +487,219 @@ initThreadsEarly()
        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);
-       memset(mainthreadobj, 0, sizeof(threadobject));
+       mainthreadobj->info.tid = pthread_self();
 #if !defined(HAVE___THREAD)
        pthread_key_create(&tkey_threadinfo, 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;
 }
 
 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;
-        classinfo *threadgroupclass;
-       java_lang_Thread *mainthread;
-       threadobject *tempthread = mainthreadobj;
+       java_lang_String      *threadname;
+       java_lang_Thread      *mainthread;
+       java_lang_ThreadGroup *threadgroup;
+       threadobject          *tempthread;
+       methodinfo            *method;
 
-       threadclass = class_new(utf_new_char("java/lang/Thread"));
-       class_load(threadclass);
-       class_link(threadclass);
+       tempthread = mainthreadobj;
 
-       assert(threadclass);
        freeLockRecordPools(mainthreadobj->ee.lrpool);
-       threadclass->instancesize = sizeof(threadobject);
 
-       mainthreadobj = (threadobject *) builtin_new(threadclass);
-       assert(mainthreadobj);
+       /* 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)
+               return false;
 
        FREE(tempthread, threadobject);
+
        initThread(&mainthreadobj->o);
 
-#if !defined(HAVE___THREAD)
-       pthread_setspecific(tkey_threadinfo, mainthreadobj);
-#else
-       threadobj = mainthreadobj;
-#endif
+       setthreadobject(mainthreadobj);
 
-       mainthread = &mainthreadobj->o;
        initLocks();
+
        mainthreadobj->info.next = mainthreadobj;
        mainthreadobj->info.prev = mainthreadobj;
 
-       mainthread->name=javastring_new(utf_new_char("main"));
+#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 */
+
+       threadgroup = (java_lang_ThreadGroup *)
+               native_new_and_init(class_java_lang_ThreadGroup);
+
+       if (!threadgroup)
+               throw_exception_exit();
+
+       /* create a Thread */
 
-       /* Allocate and init ThreadGroup */
-       threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
-       class_load(threadgroupclass);
-       class_link(threadgroupclass);
+       mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       mainthread->group =
-               (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
-       assert(mainthread->group != 0);
+       if (!mainthread)
+               throw_exception_exit();
+
+       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"),
+                                                                         class_java_lang_Thread,
+                                                                         true);
+
+       if (!method)
+               return false;
+
+       asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
+       if (*exceptionptr)
+               return false;
+
+       mainthread->group = threadgroup;
+       /* XXX This is a hack because the fourth argument was omitted */
+       mainthread->daemon = false;
+
+       /* 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);
+
+       if (!method)
+               return false;
+
+       asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
+
+       if (*exceptionptr)
+               return false;
+
+       setPriority(pthread_self(), 5);
 
        pthread_attr_init(&threadattr);
        pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
+
+       /* everything's ok */
+
+       return true;
 }
 
-void initThread(java_lang_Thread *t)
+
+void initThread(java_lang_VMThread *t)
 {
-       nativethread *info = &((threadobject*) t)->info;
+       threadobject *thread = (threadobject*) t;
+       nativethread *info = &thread->info;
+       info->tid = pthread_self();
+       /* TODO destroy all those things */
        pthread_mutex_init(&info->joinMutex, NULL);
        pthread_cond_init(&info->joinCond, NULL);
+
+       pthread_mutex_init(&thread->waitLock, NULL);
+       pthread_cond_init(&thread->waitCond, NULL);
+       thread->interrupted = false;
+       thread->signaled = false;
+       thread->isSleeping = false;
 }
 
 static void initThreadLocks(threadobject *);
 
+
 typedef struct {
        threadobject *thread;
-       sem_t *psem;
+       functionptr   function;
+       sem_t        *psem;
+       sem_t        *psem_first;
 } startupinfo;
 
-static void *threadstartup(void *t)
+
+/* threads_startup *************************************************************
+
+   Thread startup function called by pthread_create.
+
+******************************************************************************/
+
+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);
+       }
+#endif
+
+       /* get passed startupinfo structure and the values in there */
+
+       startup = t;
+
+       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. */
+       sem_wait(startup->psem_first);
 
        t = NULL;
 #if defined(__DARWIN__)
@@ -465,11 +707,15 @@ static void *threadstartup(void *t)
 #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);
 
        initThreadLocks(thread);
@@ -477,61 +723,123 @@ static void *threadstartup(void *t)
        startup = NULL;
        sem_post(psem);
 
-       /* Find the run()V method and call it */
-       method = class_findmethod(thread->o.header.vftbl->class,
-                                                         utf_new_char("run"), utf_new_char("()V"));
-       if (!method)
-               panic("Cannot find method \'void run ()\'");
+       setPriority(info->tid, thread->o.thread->priority);
 
-       asm_calljavafunction(method, thread, NULL, NULL, NULL);
+#if defined(ENABLE_INTRP)
+       /* set interpreter stack */
 
-    if (info->_exceptionptr) {
-        utf_display_classname((info->_exceptionptr)->vftbl->class->name);
-        printf("\n");
-    }
+       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();
+
+               asm_calljavafunction(method, thread, NULL, NULL, NULL);
+
+       } 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. */
 
        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);
+
        pthread_cond_broadcast(&info->joinCond);
 
        return NULL;
 }
 
-void startThread(threadobject *t)
+
+/* threads_start_thread ********************************************************
+
+   Start a thread in the JVM.
+
+******************************************************************************/
+
+void threads_start_thread(thread *t, functionptr function)
 {
-       nativethread *info = &t->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 XXX */
 
-       startup.thread = t;
-       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);
+       sem_init(&sem_first, 0, 0);
        
-       if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
-               panic("pthread_create failed");
+       if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
+                                          &startup)) {
+               log_text("pthread_create failed");
+               assert(0);
+       }
+
+       sem_post(&sem_first);
+
+       /* wait here until the thread has entered itself into the thread list */
 
-       /* Wait here until thread has entered itself into the thread list */
        sem_wait(&sem);
        sem_destroy(&sem);
+       sem_destroy(&sem_first);
+}
+
+
+/* At the end of the program, we wait for all running non-daemon threads to die
+ */
+
+static threadobject *findNonDaemon(threadobject *thread)
+{
+       while (thread != mainthreadobj) {
+               if (!thread->o.thread->daemon)
+                       return thread;
+               thread = thread->info.prev;
+       }
+
+       return NULL;
 }
 
 void joinAllThreads()
 {
+       threadobject *thread;
        pthread_mutex_lock(&threadlistlock);
-       while (mainthreadobj->info.prev != mainthreadobj) {
-               nativethread *info = &mainthreadobj->info.prev->info;
+       while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
+               nativethread *info = &thread->info;
                pthread_mutex_lock(&info->joinMutex);
                pthread_mutex_unlock(&threadlistlock);
-               if (info->tid)
+               while (info->tid)
                        pthread_cond_wait(&info->joinCond, &info->joinMutex);
                pthread_mutex_unlock(&info->joinMutex);
                pthread_mutex_lock(&threadlistlock);
@@ -539,54 +847,30 @@ void joinAllThreads()
        pthread_mutex_unlock(&threadlistlock);
 }
 
-bool aliveThread(java_lang_Thread *t)
-{
-       return ((threadobject*) t)->info.tid != 0;
-}
-
-void sleepThread(s8 millis)
-{
-       struct timespec tv;
-       tv.tv_sec = millis / 1000;
-       tv.tv_nsec = millis % 1000 * 1000000;
-       do { } while (nanosleep(&tv, &tv) == EINTR);
-}
-
-void yieldThread()
-{
-       sched_yield();
-}
-
-static void timedCondWait(pthread_cond_t *cond, pthread_mutex_t *mutex, s8 millis)
+static void initLockRecord(monitorLockRecord *r, threadobject *t)
 {
-       struct timeval now;
-       struct timespec desttime;
-       gettimeofday(&now, NULL);
-       desttime.tv_sec = millis / 1000;
-       desttime.tv_nsec = millis % 1000 * 1000000;
-       pthread_cond_timedwait(cond, mutex, &desttime);
+       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);
 }
 
+/* No lock record must ever be destroyed because there may still be references
+ * to it.
 
-#define NEUTRAL 0
-#define LOCKED 1
-#define WAITERS 2
-#define BUSY 3
-
-static void initExecutionEnvironment(ExecEnvironment *ee)
+static void destroyLockRecord(monitorLockRecord *r)
 {
-       pthread_mutex_init(&ee->metaLockMutex, NULL);
-       pthread_cond_init(&ee->metaLockCond, NULL);
-       pthread_mutex_init(&ee->monitorLockMutex, NULL);
-       pthread_cond_init(&ee->monitorLockCond, NULL);
-}
-
-static void initLockRecord(monitorLockRecord *r, threadobject *t)
-{
-       r->owner = t;
-       r->lockCount = 1;
-       r->queue = NULL;
+       sem_destroy(&r->queueSem);
+       pthread_mutex_destroy(&r->resolveLock);
+       pthread_cond_destroy(&r->resolveWait);
 }
+*/
 
 void initLocks()
 {
@@ -595,34 +879,12 @@ void initLocks()
 
 static void initThreadLocks(threadobject *thread)
 {
-       int i;
-
-       initExecutionEnvironment(&thread->ee);
-       for (i=0; i<INITIALLOCKRECORDS; i++) {
-               monitorLockRecord *r = &thread->ee.lr[i];
-               initLockRecord(r, thread);
-               r->nextFree = &thread->ee.lr[i+1];
-       }
-       thread->ee.lr[i-1].nextFree = NULL;
-       thread->ee.firstLR = &thread->ee.lr[0];
-}
-
-static inline int lockState(long r)
-{
-       return (int) r & 3;
+       thread->ee.firstLR = NULL;
+       thread->ee.lrpool = NULL;
+       thread->ee.numlr = 0;
 }
 
-static inline void *lockRecord(long r)
-{
-       return (void*) (r & ~3L);
-}
-
-static inline long makeLockBits(void *r, long l)
-{
-       return ((long) r) | l;
-}
-
-static lockRecordPool *allocLockRecordPool(threadobject *thread, int size)
+static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
 {
        lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
        int i;
@@ -636,268 +898,406 @@ static lockRecordPool *allocLockRecordPool(threadobject *thread, int size)
        return p;
 }
 
-static void freeLockRecordPools(lockRecordPool *pool)
+#define INITIALLOCKRECORDS 8
+
+pthread_mutex_t pool_lock;
+lockRecordPool *global_pool;
+
+static void initPools()
 {
-       while (pool) {
-               lockRecordPool *n = pool->header.next;
-               mem_free(pool, sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * pool->header.size);
-               pool = n;
+       pthread_mutex_init(&pool_lock, NULL);
+}
+
+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;
        }
+       pthread_mutex_unlock(&pool_lock);
+
+       return allocNewLockRecordPool(t, size);
+}
+
+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);
 }
 
-static monitorLockRecord *allocLockRecord(threadobject *t)
+static monitorLockRecord *allocLockRecordSimple(threadobject *t)
 {
        monitorLockRecord *r = t->ee.firstLR;
 
        if (!r) {
-               int poolsize = t->ee.lrpool ? t->ee.lrpool->header.size * 2 : INITIALLOCKRECORDS * 2;
+               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;
        }
        
        t->ee.firstLR = r->nextFree;
        return r;
 }
 
-static void recycleLockRecord(threadobject *t, monitorLockRecord *r)
+static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
 {
        r->nextFree = t->ee.firstLR;
        t->ee.firstLR = r;
 }
 
-static monitorLockRecord *appendToQueue(monitorLockRecord *queue, monitorLockRecord *lr)
+void initObjectLock(java_objectheader *o)
 {
-       monitorLockRecord *queuestart = queue;
-       if (!queue)
-               return lr;
-       while (queue->queue)
-               queue = queue->queue;
-       queue->queue = lr;
-       return queuestart;
+       o->monitorPtr = dummyLR;
 }
 
-static monitorLockRecord *moveMyLRToFront(threadobject *t, monitorLockRecord *lr)
+
+/* get_dummyLR *****************************************************************
+
+   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.
+
+*******************************************************************************/
+
+monitorLockRecord *get_dummyLR(void)
 {
-       monitorLockRecord *pred = NULL;
-       monitorLockRecord *firstLR = lr;
-       while (lr->owner != t) {
-               pred = lr;
-               lr = lr->queue;
-       }
-       if (!pred)
-               return lr;
-       pred->queue = lr->queue;
-       lr->queue = firstLR;
-       lr->storedBits = firstLR->storedBits;
-       return lr;
+       return dummyLR;
 }
 
-static long getMetaLockSlow(threadobject *t, long predBits);
-static void releaseMetaLockSlow(threadobject *t, long releaseBits);
 
-static long getMetaLock(threadobject *t, java_objectheader *o)
+static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
 {
-       long busyBits = makeLockBits(t, BUSY);
-       long lockBits = atomic_swap(&o->monitorBits, busyBits);
-       return lockState(lockBits) != BUSY ? lockBits : getMetaLockSlow(t, lockBits);
+       atomic_add(&lr->queuers, 1);
+
+       MEMORY_BARRIER_AFTER_ATOMIC();
+
+       while (lr->o == o)
+               sem_wait(&lr->queueSem);
+
+       atomic_add(&lr->queuers, -1);
 }
 
-static long getMetaLockSlow(threadobject *t, long predBits)
+static void freeLockRecord(monitorLockRecord *lr)
 {
-       long bits;
-       threadobject *pred = lockRecord(predBits);
-       pthread_mutex_lock(&pred->ee.metaLockMutex);
-       if (!pred->ee.bitsForGrab) {
-               pred->ee.succ = t;
-               do {
-                       pthread_cond_wait(&pred->ee.metaLockCond, &pred->ee.metaLockMutex);
-               } while (!t->ee.gotMetaLockSlow);
-               t->ee.gotMetaLockSlow = false;
-               bits = t->ee.metaLockBits;
-       } else {
-               bits = pred->ee.metaLockBits;
-               pred->ee.bitsForGrab = false;
-               pthread_cond_signal(&pred->ee.metaLockCond);
-       }
-       pthread_mutex_unlock(&pred->ee.metaLockMutex);
-       return bits;
+       int q;
+       lr->o = NULL;
+       MEMORY_BARRIER();
+       q = lr->queuers;
+       while (q--)
+               sem_post(&lr->queueSem);
 }
 
-static void releaseMetaLock(threadobject *t, java_objectheader *o, long releaseBits)
+static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
 {
-       long busyBits = makeLockBits(t, BUSY);
-       int locked = compare_and_swap(&o->monitorBits, busyBits, releaseBits) != 0;
-       
-       if (!locked)
-               releaseMetaLockSlow(t, releaseBits);
+       if (lr->waiting)
+               mlr->waiter = lr;
 }
 
-static void releaseMetaLockSlow(threadobject *t, long releaseBits)
+monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
 {
-       pthread_mutex_lock(&t->ee.metaLockMutex);
-       if (t->ee.succ) {
-               assert(!t->ee.succ->ee.bitsForGrab);
-               assert(!t->ee.bitsForGrab);
-               assert(!t->ee.succ->ee.gotMetaLockSlow);
-               t->ee.succ->ee.metaLockBits = releaseBits;
-               t->ee.succ->ee.gotMetaLockSlow = true;
-               t->ee.succ = NULL;
-               pthread_cond_signal(&t->ee.metaLockCond);
-       } else {
-               t->ee.metaLockBits = releaseBits;
-               t->ee.bitsForGrab = true;
-               do {
-                       pthread_cond_wait(&t->ee.metaLockCond, &t->ee.metaLockMutex);
-               } while (t->ee.bitsForGrab);
+       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);
+               }
        }
-       pthread_mutex_unlock(&t->ee.metaLockMutex);
 }
 
-static void monitorEnterSlow(threadobject *t, java_objectheader *o, long r);
-
-void monitorEnter(threadobject *t, java_objectheader *o)
+static void wakeWaiters(monitorLockRecord *lr)
 {
-       long r = getMetaLock(t, o);
-       int state = lockState(r);
+       monitorLockRecord *tmplr;
+       s4 q;
 
-       if (state == NEUTRAL) {
-               monitorLockRecord *lr = allocLockRecord(t);
-               lr->storedBits = r;
-               releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
-       } else if (state == LOCKED) {
-               monitorLockRecord *ownerLR = lockRecord(r);
-               if (ownerLR->owner == t) {
-                       ownerLR->lockCount++;
-                       releaseMetaLock(t, o, r);
-               } else {
-                       monitorLockRecord *lr = allocLockRecord(t);
-                       ownerLR->queue = appendToQueue(ownerLR->queue, lr);
-                       monitorEnterSlow(t, o, r);
-               }
-       } else if (state == WAITERS) {
-               monitorLockRecord *lr = allocLockRecord(t);
-               monitorLockRecord *firstWaiterLR = lockRecord(r);
-               lr->queue = firstWaiterLR;
-               lr->storedBits = firstWaiterLR->storedBits;
-               releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
-       }
+       /* assign lock record to a temporary variable */
+
+       tmplr = lr;
+
+       do {
+               q = tmplr->queuers;
+
+               while (q--)
+                       sem_post(&tmplr->queueSem);
+
+               tmplr = tmplr->waiter;
+       } while (tmplr != NULL && tmplr != lr);
 }
 
-static void monitorEnterSlow(threadobject *t, java_objectheader *o, long r)
+#define GRAB_LR(lr,t) \
+    if (lr->ownerThread != t) { \
+               lr = lr->incharge; \
+       }
+
+#define CHECK_MONITORSTATE(lr,t,mo,a) \
+    if (lr == NULL || lr->o != mo || lr->ownerThread != t) { \
+               *exceptionptr = new_illegalmonitorstateexception(); \
+               a; \
+       }
+
+bool monitorExit(threadobject *t, java_objectheader *o)
 {
-       monitorLockRecord *lr;
-       while (lockState(r) == LOCKED) {
-               pthread_mutex_lock(&t->ee.monitorLockMutex);
-               releaseMetaLock(t, o, r);
-               pthread_cond_wait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex);
-               pthread_mutex_unlock(&t->ee.monitorLockMutex);
-               r = getMetaLock(t, o);
+       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;
        }
-       assert(lockState(r) == WAITERS);
-       lr = moveMyLRToFront(t, lockRecord(r));
-       releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
+       freeLockRecord(lr);
+       recycleLockRecord(t, lr);
+       return true;
 }
 
-static void monitorExitSlow(threadobject *t, java_objectheader *o, monitorLockRecord *lr);
-
-void monitorExit(threadobject *t, java_objectheader *o)
+static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
 {
-       long r = getMetaLock(t, o);
-       monitorLockRecord *ownerLR = lockRecord(r);
-       int state = lockState(r);
-       if (state == LOCKED && ownerLR->owner == t) {
-               assert(ownerLR->lockCount >= 1);
-               if (ownerLR->lockCount == 1) {
-                       if (ownerLR->queue == NULL) {
-                               assert(lockState(ownerLR->storedBits) == NEUTRAL);
-                               releaseMetaLock(t, o, ownerLR->storedBits);
-                       } else {
-                               ownerLR->queue->storedBits = ownerLR->storedBits;
-                               monitorExitSlow(t, o, ownerLR->queue);
-                               ownerLR->queue = NULL;
-                       }
-                       recycleLockRecord(t, ownerLR);
-               } else {
-                       ownerLR->lockCount--;
-                       releaseMetaLock(t, o, r);
+       do {
+               if (lr->waiter == wlr) {
+                       lr->waiter = wlr->waiter;
+                       break;
                }
-       } else {
-               releaseMetaLock(t, o, r);
-               panic("Illegal monitor exception");
-       }
+               lr = lr->waiter;
+       } while (lr);
 }
 
-static threadobject *wakeupEE(monitorLockRecord *lr)
+static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
 {
-       while (lr->queue && lr->queue->owner->ee.isWaitingForNotify)
-               lr = lr->queue;
-       return lr->owner;
+       return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
 }
 
-static void monitorExitSlow(threadobject *t, java_objectheader *o, monitorLockRecord *lr)
+static bool timeIsEarlier(const struct timespec *tv)
 {
-       threadobject *wakeEE = wakeupEE(lr);
-       if (wakeEE) {
-               pthread_mutex_lock(&wakeEE->ee.monitorLockMutex);
-               releaseMetaLock(t, o, makeLockBits(lr, WAITERS));
-               pthread_cond_signal(&wakeEE->ee.monitorLockCond);
-               pthread_mutex_unlock(&wakeEE->ee.monitorLockMutex);
-       } else {
-               releaseMetaLock(t, o, makeLockBits(lr, WAITERS));
-       }
+       struct timeval tvnow;
+       struct timespec tsnow;
+       gettimeofday(&tvnow, NULL);
+       tsnow.tv_sec = tvnow.tv_sec;
+       tsnow.tv_nsec = tvnow.tv_usec * 1000;
+       return timespec_less(&tsnow, tv);
 }
 
-void monitorWait(threadobject *t, java_objectheader *o, s8 millis)
-{
-       long r = getMetaLock(t, o);
-       monitorLockRecord *ownerLR = lockRecord(r);
-       int state = lockState(r);
-       if (state == LOCKED && ownerLR->owner == t) {
-               pthread_mutex_lock(&t->ee.monitorLockMutex);
-               t->ee.isWaitingForNotify = true;
-               monitorExitSlow(t, o, ownerLR);
-               if (millis == -1)
-                       pthread_cond_wait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex);
-               else
-                       timedCondWait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex, millis);
-               t->ee.isWaitingForNotify = false;
-               pthread_mutex_unlock(&t->ee.monitorLockMutex);
-               r = getMetaLock(t, o);
-               monitorEnterSlow(t, o, r);
+
+/* waitWithTimeout *************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+static bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, 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);
+
+       return wasinterrupted;
+}
+
+
+static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
+{
+       if (millis || nanos) {
+               struct timeval tv;
+               long nsec;
+               gettimeofday(&tv, NULL);
+               tv.tv_sec += millis / 1000;
+               millis %= 1000;
+               nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
+               tm->tv_sec = tv.tv_sec + nsec / 1000000000;
+               tm->tv_nsec = nsec % 1000000000;
        } else {
-               releaseMetaLock(t, o, r);
-               panic("Illegal monitor exception");
+               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);
+
+       if (wasinterrupted)
+               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+}
+
 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
 {
-       long r = getMetaLock(t, o);
-       monitorLockRecord *ownerLR = lockRecord(r);
-       int state = lockState(r);
-       if (state == LOCKED && ownerLR->owner == t) {
-               monitorLockRecord *q = ownerLR->queue;
-               while (q) {
-                       if (q->owner->ee.isWaitingForNotify) {
-                               q->owner->ee.isWaitingForNotify = false;
-                               if (one)
-                                       break;
-                       }
-                       q = q->queue;
-               }
-               releaseMetaLock(t, o, r);
-       } else {
-               releaseMetaLock(t, o, r);
-               panic("Illegal monitor exception");
-       }
+       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);
+}
+
+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;
+}
+
+void interruptThread(java_lang_VMThread *thread)
+{
+       threadobject *t = (threadobject*) thread;
+
+       t->interrupted = true;
+       pthread_mutex_lock(&t->waitLock);
+       if (t->isSleeping)
+               pthread_cond_signal(&t->waitCond);
+       pthread_mutex_unlock(&t->waitLock);
+}
+
+bool interruptedThread()
+{
+       threadobject *t = (threadobject*) THREADOBJECT;
+       bool intr = t->interrupted;
+       t->interrupted = false;
+       return intr;
+}
+
+bool isInterruptedThread(java_lang_VMThread *thread)
+{
+       threadobject *t = (threadobject*) thread;
+       return t->interrupted;
 }
 
-void wait_cond_for_object(java_objectheader *o, s8 time)
+void sleepThread(s8 millis, s4 nanos)
 {
+       bool wasinterrupted;
        threadobject *t = (threadobject*) THREADOBJECT;
-       monitorWait(t, o, time);
+       monitorLockRecord *lr;
+       struct timespec wakeupTime;
+       calcAbsoluteTime(&wakeupTime, millis, nanos);
+
+       lr = allocLockRecordSimple(t);
+       wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
+       recycleLockRecord(t, lr);
+
+       if (wasinterrupted)
+               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+}
+
+void yieldThread()
+{
+       sched_yield();
+}
+
+void setPriorityThread(thread *t, s4 priority)
+{
+       nativethread *info = &((threadobject*) t->vmThread)->info;
+       setPriority(info->tid, priority);
+}
+
+void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
+{
+       threadobject *t = (threadobject*) THREADOBJECT;
+       monitorWait(t, o, time, nanos);
 }
 
 void signal_cond_for_object(java_objectheader *o)
@@ -912,8 +1312,70 @@ void broadcast_cond_for_object(java_objectheader *o)
        notifyOneOrAll(t, o, false);
 }
 
+
+/* 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;
+       ExecEnvironment    *ee;
+       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;
+               ee  = &tobj->ee;
+               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 */
+
+                       sleepThread(10, 0);
+               }
+
+               tobj = tobj->info.next;
+       } while (tobj && (tobj != mainthreadobj));
+}
+
 
 /*
  * These are local overrides for various environment variables in Emacs.