* src/threads/native/threads.c (threads_preinit): We always need
[cacao.git] / src / threads / native / threads.c
index a9925e60b318ec5e127d37e86726cdfa1badcf50..59f9b72d624a829049844bb765fec89b15a2c07c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/native/threads.c - native threads support
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Stefan Ring
-
-   Changes: Christian Thalinger
-                       Edwin Steiner
-
-   $Id: threads.c 5590 2006-09-30 13:51:12Z michi $
+   $Id: threads.c 7809 2007-04-25 15:14:34Z twisti $
 
 */
 
 # include "threads/native/generic-primitives.h"
 #endif
 
-#include "mm/boehm.h"
+#include "mm/gc-common.h"
 #include "mm/memory.h"
+
+#include "native/jni.h"
 #include "native/native.h"
 #include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
 #include "native/include/java_lang_Thread.h"
-#include "native/include/java_lang_ThreadGroup.h"
-#include "native/include/java_lang_VMThread.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/include/java_lang_ThreadGroup.h"
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_VMThread.h"
+#endif
+
+#include "threads/threads-common.h"
+
 #include "threads/native/threads.h"
+
 #include "toolbox/avl.h"
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
 #if !defined(__DARWIN__)
 # if defined(__LINUX__)
 #  define GC_LINUX_THREADS
@@ -87,7 +99,9 @@
 #  define GC_IRIX_THREADS
 # endif
 # include <semaphore.h>
-# include "boehm-gc/include/gc.h"
+# if defined(ENABLE_GC_BOEHM)
+#  include "mm/boehm-gc/include/gc.h"
+# endif
 #endif
 
 #if defined(ENABLE_JVMTI)
@@ -201,7 +215,7 @@ static s4 threads_table_add(threadobject *thread);
 static void threads_table_remove(threadobject *thread);
 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
 
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && 0
 static void threads_table_dump(FILE *file);
 #endif
 
@@ -212,6 +226,8 @@ static void threads_table_dump(FILE *file);
 /* the main thread                                                            */
 threadobject *mainthreadobj;
 
+static methodinfo *method_thread_init;
+
 /* the thread object of the current thread                                    */
 /* This is either a thread-local variable defined with __thread, or           */
 /* a thread-specific value stored with key threads_current_threadobject_key.  */
@@ -224,15 +240,16 @@ pthread_key_t threads_current_threadobject_key;
 /* global threads table                                                       */
 static threads_table_t threads_table;
 
-/* global compiler mutex                                                      */
-static pthread_mutex_rec_t compiler_mutex;
-
 /* global mutex for changing the thread list                                  */
 static pthread_mutex_t threadlistlock;
 
 /* global mutex for stop-the-world                                            */
 static pthread_mutex_t stopworldlock;
 
+/* global mutex and condition for joining threads on exit */
+static pthread_mutex_t mutex_join;
+static pthread_cond_t  cond_join;
+
 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
 /* being stopped                                                              */
 static volatile int stopworldwhere;
@@ -254,56 +271,6 @@ pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
 #endif
 
 
-/******************************************************************************/
-/* Recursive Mutex Implementation for Darwin                                  */
-/******************************************************************************/
-
-#if defined(MUTEXSIM)
-
-/* We need this for older MacOSX (10.1.x) */
-
-void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_init(&m->mutex, NULL);
-       m->count = 0;
-}
-
-void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
-{
-       pthread_mutex_destroy(&m->mutex);
-}
-
-void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
-{
-       for (;;) {
-               if (!m->count)
-               {
-                       pthread_mutex_lock(&m->mutex);
-                       m->owner = pthread_self();
-                       m->count++;
-                       break;
-               }
-               else {
-                       if (m->owner != pthread_self()) {
-                               pthread_mutex_lock(&m->mutex);
-                       }
-                       else {
-                               m->count++;
-                               break;
-                       }
-               }
-       }
-}
-
-void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
-{
-       if (!--m->count)
-               pthread_mutex_unlock(&m->mutex);
-}
-
-#endif /* defined(MUTEXSIM) */
-
-
 /* threads_sem_init ************************************************************
  
    Initialize a semaphore. Checks against errors and interruptions.
@@ -384,51 +351,6 @@ void threads_sem_post(sem_t *sem)
 }
 
 
-/* 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;
-
-       pthread_getschedparam(tid, &policy, &schedp);
-       schedp.sched_priority = priority;
-       pthread_setschedparam(tid, policy, &schedp);
-}
-
-
-/* compiler_lock ***************************************************************
-
-   Enter the compiler lock.
-
-******************************************************************************/
-
-void compiler_lock(void)
-{
-       pthread_mutex_lock_rec(&compiler_mutex);
-}
-
-
-/* compiler_unlock *************************************************************
-
-   Release the compiler lock.
-
-******************************************************************************/
-
-void compiler_unlock(void)
-{
-       pthread_mutex_unlock_rec(&compiler_mutex);
-}
-
-
 /* lock_stopworld **************************************************************
 
    Enter the stopworld lock, specifying why the world shall be stopped.
@@ -505,27 +427,25 @@ static void threads_cast_darwinstop(void)
                        kern_return_t r;
 
                        r = thread_suspend(thread);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_suspend failed");
-                               assert(0);
-                       }
-
-                       r = thread_get_state(thread, flavor,
-                               (natural_t*)&thread_state, &thread_state_count);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_get_state failed");
-                               assert(0);
-                       }
-
-                       thread_restartcriticalsection(&thread_state);
-
-                       r = thread_set_state(thread, flavor,
-                               (natural_t*)&thread_state, thread_state_count);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_set_state failed");
-                               assert(0);
-                       }
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_suspend failed");
+
+                       r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
+                                                                &thread_state_count);
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_get_state failed");
+
+                       thread_restartcriticalsection((ucontext_t *) &thread_state);
+
+                       r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
+                                                                thread_state_count);
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_set_state failed");
                }
+
                tobj = tobj->next;
        } while (tobj != mainthreadobj);
 }
@@ -542,11 +462,11 @@ static void threads_cast_darwinresume(void)
                        kern_return_t r;
 
                        r = thread_resume(thread);
-                       if (r != KERN_SUCCESS) {
-                               log_text("thread_resume failed");
-                               assert(0);
-                       }
+
+                       if (r != KERN_SUCCESS)
+                               vm_abort("thread_resume failed");
                }
+
                tobj = tobj->next;
        } while (tobj != mainthreadobj);
 }
@@ -562,11 +482,17 @@ static void threads_cast_irixresume(void)
 }
 #endif
 
+#if !defined(DISABLE_GC)
+
 void threads_cast_stopworld(void)
 {
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
        int count, i;
+#endif
+
        lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
        pthread_mutex_lock(&threadlistlock);
+
 #if defined(__DARWIN__)
        threads_cast_darwinstop();
 #elif defined(__CYGWIN__)
@@ -574,9 +500,10 @@ void threads_cast_stopworld(void)
        assert(0);
 #else
        count = threads_cast_sendsignals(GC_signum1(), 0);
-       for (i=0; i<count; i++)
+       for (i = 0; i < count; i++)
                threads_sem_wait(&suspend_ack);
 #endif
+
        pthread_mutex_unlock(&threadlistlock);
 }
 
@@ -597,6 +524,7 @@ void threads_cast_startworld(void)
        unlock_stopworld();
 }
 
+
 #if !defined(__DARWIN__)
 static void threads_sigsuspend_handler(ucontext_t *ctx)
 {
@@ -640,6 +568,8 @@ int cacao_suspendhandler(ucontext_t *ctx)
 }
 #endif
 
+#endif /* DISABLE_GC */
+
 /* threads_set_current_threadobject ********************************************
 
    Set the current thread object.
@@ -659,12 +589,40 @@ static void threads_set_current_threadobject(threadobject *thread)
 }
 
 
+/* threads_init_threadobject **************************************************
+
+   Initialize implementation fields of a threadobject.
+
+   IN:
+      thread............the threadobject
+
+******************************************************************************/
+
+static void threads_init_threadobject(threadobject *thread)
+{
+       /* get the pthread id */
+
+       thread->tid = pthread_self();
+
+       thread->index = 0;
+
+       /* TODO destroy all those things */
+
+       pthread_mutex_init(&(thread->waitmutex), NULL);
+       pthread_cond_init(&(thread->waitcond), NULL);
+
+       thread->interrupted = false;
+       thread->signaled    = false;
+       thread->sleeping    = false;
+}
+
+
 /* threads_get_current_threadobject ********************************************
 
    Return the threadobject of the current thread.
    
    RETURN VALUE:
-       the current threadobject * (an instance of java.lang.VMThread)
+       the current threadobject * (an instance of java.lang.Thread)
 
 *******************************************************************************/
 
@@ -678,30 +636,36 @@ threadobject *threads_get_current_threadobject(void)
 
    Do some early initialization of stuff required.
 
+   ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
+   is called AFTER this function!
+
 *******************************************************************************/
 
 void threads_preinit(void)
 {
-#ifndef MUTEXSIM
-       pthread_mutexattr_t mutexattr;
-       pthread_mutexattr_init(&mutexattr);
-       pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
-       pthread_mutex_init(&compiler_mutex, &mutexattr);
-       pthread_mutexattr_destroy(&mutexattr);
-#else
-       pthread_mutex_init_rec(&compiler_mutex);
-#endif
-
        pthread_mutex_init(&threadlistlock, NULL);
        pthread_mutex_init(&stopworldlock, NULL);
 
-       /* Allocate something so the garbage collector's signal handlers
-          are installed. */
-       heap_allocate(1, false, NULL);
+       /* initialize exit mutex and condition (on exit we join all
+          threads) */
 
+       pthread_mutex_init(&mutex_join, NULL);
+       pthread_cond_init(&cond_join, NULL);
+
+#if defined(ENABLE_GC_BOEHM)
+       mainthreadobj = GCNEW_UNCOLLECTABLE(threadobject, 1);
+#else
        mainthreadobj = NEW(threadobject);
-       mainthreadobj->tid = pthread_self();
-       mainthreadobj->index = 1;
+#endif
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_threadobject += sizeof(threadobject);
+#endif
+
+       mainthreadobj->object   = NULL;
+       mainthreadobj->tid      = pthread_self();
+       mainthreadobj->index    = 1;
        mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
        
 #if !defined(HAVE___THREAD)
@@ -731,39 +695,59 @@ void threads_preinit(void)
 
 bool threads_init(void)
 {
-       java_lang_String      *threadname;
-       java_lang_Thread      *mainthread;
+       java_objectheader     *threadname;
+       java_lang_Thread      *t;
+       java_objectheader     *o;
+
+#if defined(ENABLE_JAVASE)
        java_lang_ThreadGroup *threadgroup;
-       threadobject          *tempthread;
-       methodinfo            *method;
+       methodinfo            *m;
+#endif
 
-       tempthread = mainthreadobj;
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
 
-       /* XXX We have to find a new way to free lock records */
-       /*     with the new locking algorithm.                */
-       /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
+       /* get methods we need in this file */
 
-       /* 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. */
+#if defined(WITH_CLASSPATH_GNU)
+       method_thread_init =
+               class_resolveclassmethod(class_java_lang_Thread,
+                                                                utf_init,
+                                                                utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
+                                                                class_java_lang_Thread,
+                                                                true);
+#else
+       method_thread_init =
+               class_resolveclassmethod(class_java_lang_Thread,
+                                                                utf_init,
+                                                                utf_new_char("(Ljava/lang/String;)V"),
+                                                                class_java_lang_Thread,
+                                                                true);
+#endif
 
-       class_java_lang_VMThread->instancesize = sizeof(threadobject);
+       if (method_thread_init == NULL)
+               return false;
 
-       /* create a VMThread */
+       /* create a java.lang.Thread for the main thread */
 
-       mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       if (mainthreadobj == NULL)
+       if (t == NULL)
                return false;
 
-       FREE(tempthread, threadobject);
+       /* set the object in the internal data structure */
 
-       threads_init_threadobject(&mainthreadobj->o);
+       mainthreadobj->object = t;
 
+       threads_init_threadobject(mainthreadobj);
        threads_set_current_threadobject(mainthreadobj);
-
        lock_init_execution_env(mainthreadobj);
 
+       /* thread is running */
+
+       mainthreadobj->state = THREAD_STATE_RUNNABLE;
+
        mainthreadobj->next = mainthreadobj;
        mainthreadobj->prev = mainthreadobj;
 
@@ -778,66 +762,75 @@ bool threads_init(void)
 
        if (opt_intrp) {
                MSET(intrp_main_stack, 0, u1, opt_stacksize);
-               mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
+               mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
        }
 #endif
 
        threadname = javastring_new(utf_new_char("main"));
 
+#if defined(ENABLE_JAVASE)
        /* allocate and init ThreadGroup */
 
        threadgroup = (java_lang_ThreadGroup *)
                native_new_and_init(class_java_lang_ThreadGroup);
 
-       if (!threadgroup)
-               throw_exception_exit();
+       if (threadgroup == NULL)
+               return false;
+#endif
 
-       /* create a Thread */
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread for the main thread */
 
-       mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
-       if (mainthread == NULL)
-               throw_exception_exit();
+       if (vmt == NULL)
+               return false;
 
-       mainthreadobj->o.thread = mainthread;
+       /* set the thread */
 
-       /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+       vmt->thread = t;
+       vmt->vmdata = (java_lang_Object *) mainthreadobj;
 
-       method = class_resolveclassmethod(class_java_lang_Thread,
-                                                                         utf_init,
-                                                                         utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
-                                                                         class_java_lang_Thread,
-                                                                         true);
+       /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+       o = (java_objectheader *) t;
 
-       if (method == NULL)
-               return false;
+       (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
+                                                 false);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       /* set the thread */
+
+       t->vm_thread = (java_lang_Object *) mainthreadobj;
+
+       /* call public Thread(String name) */
+
+       o = (java_objectheader *) t;
 
-       (void) vm_call_method(method, (java_objectheader *) mainthread,
-                                                 mainthreadobj, threadname, 5, false);
+       (void) vm_call_method(method_thread_init, o, threadname);
+#endif
 
        if (*exceptionptr)
                return false;
 
-       mainthread->group = threadgroup;
+#if defined(ENABLE_JAVASE)
+       t->group = threadgroup;
 
-       /* add mainthread to ThreadGroup */
+       /* add main thread to java.lang.ThreadGroup */
 
-       method = class_resolveclassmethod(class_java_lang_ThreadGroup,
-                                                                         utf_new_char("addThread"),
-                                                                         utf_new_char("(Ljava/lang/Thread;)V"),
-                                                                         class_java_lang_ThreadGroup,
-                                                                         true);
+       m = class_resolveclassmethod(class_java_lang_ThreadGroup,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
 
-       if (method == NULL)
-               return false;
+       o = (java_objectheader *) threadgroup;
 
-       (void) vm_call_method(method, (java_objectheader *) threadgroup,
-                                                 mainthread);
+       (void) vm_call_method(m, o, t);
 
        if (*exceptionptr)
                return false;
+#endif
 
-       threads_set_thread_priority(pthread_self(), 5);
+       threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
 
        /* initialize the thread attribute object */
 
@@ -976,35 +969,6 @@ static void threads_table_remove(threadobject *thread)
 #endif
 }
 
-/* threads_init_threadobject **************************************************
-
-   Initialize implementation fields of a java.lang.VMThread.
-
-   IN:
-      t............the java.lang.VMThread
-
-******************************************************************************/
-
-void threads_init_threadobject(java_lang_VMThread *t)
-{
-       threadobject *thread = (threadobject*) t;
-
-       thread->tid = pthread_self();
-
-       thread->index = 0;
-
-       /* TODO destroy all those things */
-       pthread_mutex_init(&(thread->joinmutex), NULL);
-       pthread_cond_init(&(thread->joincond), NULL);
-
-       pthread_mutex_init(&(thread->waitmutex), NULL);
-       pthread_cond_init(&(thread->waitcond), NULL);
-
-       thread->interrupted = false;
-       thread->signaled = false;
-       thread->sleeping = false;
-}
-
 
 /* threads_startup_thread ******************************************************
 
@@ -1027,12 +991,17 @@ void threads_init_threadobject(java_lang_VMThread *t)
 
 static void *threads_startup_thread(void *t)
 {
-       startupinfo  *startup;
-       threadobject *thread;
-       sem_t        *psem;
-       threadobject *tnext;
-       methodinfo   *method;
-       functionptr   function;
+       startupinfo        *startup;
+       threadobject       *thread;
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread *vmt;
+#endif
+       sem_t              *psem;
+       threadobject       *tnext;
+       classinfo          *c;
+       methodinfo         *m;
+       java_objectheader  *o;
+       functionptr         function;
 
 #if defined(ENABLE_INTRP)
        u1 *intrp_thread_stack;
@@ -1068,6 +1037,10 @@ static void *threads_startup_thread(void *t)
 #endif
        threads_set_current_threadobject(thread);
 
+       /* thread is running */
+
+       thread->state = THREAD_STATE_RUNNABLE;
+
        /* insert the thread into the threadlist and the threads table */
 
        pthread_mutex_lock(&threadlistlock);
@@ -1093,22 +1066,21 @@ static void *threads_startup_thread(void *t)
 
        /* set our priority */
 
-       threads_set_thread_priority(thread->tid, thread->o.thread->priority);
+       threads_set_thread_priority(thread->tid, thread->object->priority);
 
 #if defined(ENABLE_INTRP)
        /* set interpreter stack */
 
        if (opt_intrp)
-               thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
 #endif
 
-
-
 #if defined(ENABLE_JVMTI)
        /* fire thread start event */
-       if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
-#endif
 
+       if (jvmti) 
+               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
+#endif
 
        /* find and run the Thread.run()V method if no other function was passed */
 
@@ -1117,29 +1089,59 @@ static void *threads_startup_thread(void *t)
 
                thread->flags |= THREAD_FLAG_JAVA;
 
-               method = class_resolveclassmethod(thread->o.header.vftbl->class,
-                                                                                 utf_run,
-                                                                                 utf_void__void,
-                                                                                 thread->o.header.vftbl->class,
-                                                                                 true);
+#if defined(WITH_CLASSPATH_GNU)
+               /* We need to start the run method of
+                  java.lang.VMThread. Since this is a final class, we can use
+                  the class object directly. */
+
+               c   = class_java_lang_VMThread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+               c   = thread->object->header.vftbl->class;
+#endif
+
+               m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
+
+               if (m == NULL)
+                       vm_abort("threads_startup_thread: run() method not found in class");
+
+               /* set ThreadMXBean variables */
+
+               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+               _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
 
-               if (method == NULL)
-                       throw_exception();
+               if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+                               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
 
-               /* increase total started thread count */
+#if defined(WITH_CLASSPATH_GNU)
+               /* we need to start the run method of java.lang.VMThread */
+
+               vmt = (java_lang_VMThread *) thread->object->vmThread;
+               o   = (java_objectheader *) vmt;
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+               o   = (java_objectheader *) thread->object;
+#endif
 
-               _Jv_jvm->total_started_thread_count++;
+               /* run the thread */
 
-               (void) vm_call_method(method, (java_objectheader *) thread);
+               (void) vm_call_method(m, o);
        }
        else {
                /* this is an internal thread */
 
                thread->flags |= THREAD_FLAG_INTERNAL;
 
-               /* increase total started thread count */
+               /* set ThreadMXBean variables */
 
-               _Jv_jvm->total_started_thread_count++;
+               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+               _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+               if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+                       _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+                               _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
 
                /* call passed function, e.g. finalizer_thread */
 
@@ -1148,37 +1150,17 @@ static void *threads_startup_thread(void *t)
 
 #if defined(ENABLE_JVMTI)
        /* fire thread end event */
-       if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
-#endif
 
+       if (jvmti)
+               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
 
-       /* Allow lock record pools to be used by other threads. They
-          cannot be deleted so we'd better not waste them. */
-
-       /* XXX We have to find a new way to free lock records */
-       /*     with the new locking algorithm.                */
-       /* lock_record_free_pools(thread->ee.lockrecordpools); */
-
-       /* remove thread from thread list and threads table, do this inside a lock */
-
-       pthread_mutex_lock(&threadlistlock);
-
-       thread->next->prev = thread->prev;
-       thread->prev->next = thread->next;
-
-       threads_table_remove(thread);
-
-       pthread_mutex_unlock(&threadlistlock);
-
-       /* reset thread id (lock on joinmutex? TWISTI) */
-
-       pthread_mutex_lock(&thread->joinmutex);
-       thread->tid = 0;
-       pthread_mutex_unlock(&thread->joinmutex);
+       if (!threads_detach_thread(thread))
+               vm_abort("threads_startup_thread: threads_detach_thread failed");
 
-       /* tell everyone that a thread has finished */
+       /* set ThreadMXBean variables */
 
-       pthread_cond_broadcast(&thread->joincond);
+       _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
 
        return NULL;
 }
@@ -1186,24 +1168,21 @@ static void *threads_startup_thread(void *t)
 
 /* threads_start_thread ********************************************************
 
-   Start a thread in the JVM.
+   Start a thread in the JVM. Both (vm internal and java) thread objects exist.
 
    IN:
-      t............the java.lang.Thread object
+      thread.......the thread object
          function.....function to run in the new thread. NULL means that the
                       "run" method of the object `t` should be called
 
 ******************************************************************************/
 
-void threads_start_thread(java_lang_Thread *t, functionptr function)
+void threads_start_thread(threadobject *thread, functionptr function)
 {
        sem_t          sem;
        sem_t          sem_first;
        pthread_attr_t attr;
        startupinfo    startup;
-       threadobject  *thread;
-
-       thread = (threadobject *) t->vmThread;
 
        /* fill startupinfo structure passed by pthread_create to
         * threads_startup_thread */
@@ -1228,7 +1207,7 @@ void threads_start_thread(java_lang_Thread *t, functionptr function)
 
        /* create the thread */
 
-       if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
+       if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
                vm_abort("pthread_create failed: %s", strerror(errno));
 
        /* signal that pthread_create has returned, so thread->tid is valid */
@@ -1246,6 +1225,277 @@ void threads_start_thread(java_lang_Thread *t, functionptr function)
 }
 
 
+/* threads_set_thread_priority *************************************************
+
+   Set the priority of the given thread.
+
+   IN:
+      tid..........thread id
+         priority.....priority to set
+
+******************************************************************************/
+
+void threads_set_thread_priority(pthread_t tid, int priority)
+{
+       struct sched_param schedp;
+       int policy;
+
+       pthread_getschedparam(tid, &policy, &schedp);
+       schedp.sched_priority = priority;
+       pthread_setschedparam(tid, policy, &schedp);
+}
+
+
+/* threads_attach_current_thread ***********************************************
+
+   Attaches the current thread to the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+       threadobject          *thread;
+       utf                   *u;
+       java_objectheader     *s;
+       java_objectheader     *o;
+       java_lang_Thread      *t;
+
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
+
+       /* create a vm internal thread object */
+
+#if defined(ENABLE_GC_BOEHM)
+       thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
+#else
+       thread = NEW(threadobject);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_threadobject += sizeof(threadobject);
+#endif
+
+       if (thread == NULL)
+               return false;
+
+       /* create a java.lang.Thread object */
+
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       if (t == NULL)
+               return false;
+
+       thread->object = t;
+
+       threads_init_threadobject(thread);
+       threads_set_current_threadobject(thread);
+       lock_init_execution_env(thread);
+
+       /* thread is running */
+
+       thread->state = THREAD_STATE_RUNNABLE;
+
+       /* insert the thread into the threadlist and the threads table */
+
+       pthread_mutex_lock(&threadlistlock);
+
+       thread->prev        = mainthreadobj;
+       thread->next        = mainthreadobj->next;
+       mainthreadobj->next = thread;
+       thread->next->prev  = thread;
+
+       threads_table_add(thread);
+
+       pthread_mutex_unlock(&threadlistlock);
+
+       /* mark thread as Java thread */
+
+       thread->flags = THREAD_FLAG_JAVA;
+
+       if (isdaemon)
+               thread->flags |= THREAD_FLAG_DAEMON;
+
+#if defined(ENABLE_INTRP)
+       /* create interpreter stack */
+
+       if (opt_intrp) {
+               MSET(intrp_main_stack, 0, u1, opt_stacksize);
+               thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
+       }
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       /* create a java.lang.VMThread object */
+
+       vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+
+       if (vmt == NULL)
+               return false;
+
+       /* set the thread */
+
+       vmt->thread = t;
+       vmt->vmdata = (java_lang_Object *) thread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       t->vm_thread = (java_lang_Object *) thread;
+#endif
+
+       if (vm_aargs != NULL) {
+               u     = utf_new_char(vm_aargs->name);
+#if defined(ENABLE_JAVASE)
+               group = (java_lang_ThreadGroup *) vm_aargs->group;
+#endif
+       }
+       else {
+               u     = utf_null;
+#if defined(ENABLE_JAVASE)
+               group = mainthreadobj->object->group;
+#endif
+       }
+
+       /* the the thread name */
+
+       s = javastring_new(u);
+
+       /* for convenience */
+
+       o = (java_objectheader *) thread->object;
+
+#if defined(WITH_CLASSPATH_GNU)
+       (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
+                                                 isdaemon);
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       (void) vm_call_method(method_thread_init, o, s);
+#endif
+
+       if (*exceptionptr)
+               return false;
+
+#if defined(ENABLE_JAVASE)
+       /* store the thread group in the object */
+
+       thread->object->group = group;
+
+       /* add thread to given thread-group */
+
+       m = class_resolveclassmethod(group->header.vftbl->class,
+                                                                utf_addThread,
+                                                                utf_java_lang_Thread__V,
+                                                                class_java_lang_ThreadGroup,
+                                                                true);
+
+       o = (java_objectheader *) group;
+
+       (void) vm_call_method(m, o, t);
+
+       if (*exceptionptr)
+               return false;
+#endif
+
+       return true;
+}
+
+
+/* threads_detach_thread *******************************************************
+
+   Detaches the passed thread from the VM.  Used in JNI.
+
+*******************************************************************************/
+
+bool threads_detach_thread(threadobject *thread)
+{
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+       java_objectheader     *o;
+       java_lang_Thread      *t;
+#endif
+
+       /* Allow lock record pools to be used by other threads. They
+          cannot be deleted so we'd better not waste them. */
+
+       /* XXX We have to find a new way to free lock records */
+       /*     with the new locking algorithm.                */
+       /* lock_record_free_pools(thread->ee.lockrecordpools); */
+
+       /* XXX implement uncaught exception stuff (like JamVM does) */
+
+#if defined(ENABLE_JAVASE)
+       /* remove thread from the thread group */
+
+       group = thread->object->group;
+
+       /* XXX TWISTI: should all threads be in a ThreadGroup? */
+
+       if (group != NULL) {
+               m = class_resolveclassmethod(group->header.vftbl->class,
+                                                                        utf_removeThread,
+                                                                        utf_java_lang_Thread__V,
+                                                                        class_java_lang_ThreadGroup,
+                                                                        true);
+
+               if (m == NULL)
+                       return false;
+
+               o = (java_objectheader *) group;
+               t = thread->object;
+
+               (void) vm_call_method(m, o, t);
+
+               if (*exceptionptr)
+                       return false;
+       }
+#endif
+
+       /* thread is terminated */
+
+       thread->state = THREAD_STATE_TERMINATED;
+
+       /* lock thread list */
+
+       pthread_mutex_lock(&threadlistlock);
+
+       /* remove thread from thread list and threads table */
+
+       thread->next->prev = thread->prev;
+       thread->prev->next = thread->next;
+
+       threads_table_remove(thread);
+
+       /* unlock thread list */
+
+       pthread_mutex_unlock(&threadlistlock);
+
+       /* signal that this thread has finished */
+
+       pthread_mutex_lock(&mutex_join);
+       pthread_cond_signal(&cond_join);
+       pthread_mutex_unlock(&mutex_join);
+
+       /* free the vm internal thread object */
+
+#if defined(ENABLE_GC_BOEHM)
+       GCFREE(thread);
+#else
+       FREE(thread, threadobject);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_threadobject -= sizeof(threadobject);
+#endif
+
+       return true;
+}
+
+
 /* threads_find_non_daemon_thread **********************************************
 
    Helper function used by threads_join_all_threads for finding
@@ -1253,17 +1503,34 @@ void threads_start_thread(java_lang_Thread *t, functionptr function)
 
 *******************************************************************************/
 
-/* At the end of the program, we wait for all running non-daemon
-   threads to die. */
-
-static threadobject *threads_find_non_daemon_thread(threadobject *thread)
+static threadobject *threads_find_non_daemon_thread(void)
 {
+       threadobject *thread;
+
+       /* lock the thread list */
+
+       pthread_mutex_lock(&threadlistlock);
+
+       /* iterate over all threads */
+
+       thread = mainthreadobj->next;
+
        while (thread != mainthreadobj) {
-               if (!thread->o.thread->daemon)
+               if (!(thread->flags & THREAD_FLAG_DAEMON)) {
+                       /* unlock thread list */
+
+                       pthread_mutex_unlock(&threadlistlock);
+
                        return thread;
-               thread = thread->prev;
+               }
+
+               thread = thread->next;
        }
 
+       /* unlock thread list */
+
+       pthread_mutex_unlock(&threadlistlock);
+
        return NULL;
 }
 
@@ -1278,23 +1545,26 @@ void threads_join_all_threads(void)
 {
        threadobject *thread;
 
-       pthread_mutex_lock(&threadlistlock);
+       /* get current thread */
 
-       while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
+       thread = THREADOBJECT;
 
-               pthread_mutex_lock(&thread->joinmutex);
+       /* this thread is waiting for all non-daemon threads to exit */
 
-               pthread_mutex_unlock(&threadlistlock);
+       thread->state = THREAD_STATE_WAITING;
 
-               while (thread->tid)
-                       pthread_cond_wait(&thread->joincond, &thread->joinmutex);
+       /* enter join mutex */
 
-               pthread_mutex_unlock(&thread->joinmutex);
+       pthread_mutex_lock(&mutex_join);
 
-               pthread_mutex_lock(&threadlistlock);
-       }
+       /* wait for condition as long as we have non-daemon threads */
 
-       pthread_mutex_unlock(&threadlistlock);
+       while (threads_find_non_daemon_thread() != NULL)
+               pthread_cond_wait(&cond_join, &mutex_join);
+
+       /* leave join mutex */
+
+       pthread_mutex_unlock(&mutex_join);
 }
 
 
@@ -1370,48 +1640,58 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
 *******************************************************************************/
 
-static bool threads_wait_with_timeout(threadobject *t,
+static bool threads_wait_with_timeout(threadobject *thread,
                                                                          struct timespec *wakeupTime)
 {
        bool wasinterrupted;
 
        /* acquire the waitmutex */
 
-       pthread_mutex_lock(&t->waitmutex);
+       pthread_mutex_lock(&thread->waitmutex);
 
        /* mark us as sleeping */
 
-       t->sleeping = true;
+       thread->sleeping = true;
 
        /* wait on waitcond */
 
        if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
                /* with timeout */
-               while (!t->interrupted && !t->signaled
+               while (!thread->interrupted && !thread->signaled
                           && threads_current_time_is_earlier_than(wakeupTime))
                {
-                       pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
+                       thread->state = THREAD_STATE_TIMED_WAITING;
+
+                       pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
+                                                                  wakeupTime);
+
+                       thread->state = THREAD_STATE_RUNNABLE;
                }
        }
        else {
                /* no timeout */
-               while (!t->interrupted && !t->signaled)
-                       pthread_cond_wait(&t->waitcond, &t->waitmutex);
+               while (!thread->interrupted && !thread->signaled) {
+                       thread->state = THREAD_STATE_WAITING;
+
+                       pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
+
+                       thread->state = THREAD_STATE_RUNNABLE;
+               }
        }
 
        /* check if we were interrupted */
 
-       wasinterrupted = t->interrupted;
+       wasinterrupted = thread->interrupted;
 
        /* reset all flags */
 
-       t->interrupted = false;
-       t->signaled = false;
-       t->sleeping = false;
+       thread->interrupted = false;
+       thread->signaled    = false;
+       thread->sleeping    = false;
 
        /* release the waitmutex */
 
-       pthread_mutex_unlock(&t->waitmutex);
+       pthread_mutex_unlock(&thread->waitmutex);
 
        return wasinterrupted;
 }
@@ -1433,8 +1713,7 @@ static bool threads_wait_with_timeout(threadobject *t,
 
 *******************************************************************************/
 
-bool threads_wait_with_timeout_relative(threadobject *t,
-                                                                               s8 millis,
+bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
                                                                                s4 nanos)
 {
        struct timespec wakeupTime;
@@ -1445,7 +1724,7 @@ bool threads_wait_with_timeout_relative(threadobject *t,
 
        /* wait */
 
-       return threads_wait_with_timeout(t, &wakeupTime);
+       return threads_wait_with_timeout(thread, &wakeupTime);
 }
 
 
@@ -1481,7 +1760,7 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 }
 
 
-/* threads_interrupt_thread ****************************************************
+/* threads_thread_interrupt ****************************************************
 
    Interrupt the given thread.
 
@@ -1493,18 +1772,23 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 
 *******************************************************************************/
 
-void threads_interrupt_thread(java_lang_VMThread *thread)
+void threads_thread_interrupt(threadobject *thread)
 {
-       threadobject *t = (threadobject*) thread;
+       /* Signal the thread a "waitcond" and tell it that it has been
+          interrupted. */
+
+       pthread_mutex_lock(&thread->waitmutex);
+
+       /* Interrupt blocking system call using a signal. */
+
+       pthread_kill(thread->tid, SIGHUP);
 
-       /* signal the thread a "waitcond" and tell it that it has been */
-       /* interrupted                                                 */
+       if (thread->sleeping)
+               pthread_cond_signal(&thread->waitcond);
 
-       pthread_mutex_lock(&t->waitmutex);
-       if (t->sleeping)
-               pthread_cond_signal(&t->waitcond);
-       t->interrupted = true;
-       pthread_mutex_unlock(&t->waitmutex);
+       thread->interrupted = true;
+
+       pthread_mutex_unlock(&thread->waitmutex);
 }
 
 
@@ -1520,20 +1804,24 @@ void threads_interrupt_thread(java_lang_VMThread *thread)
 
 bool threads_check_if_interrupted_and_reset(void)
 {
-       threadobject *t;
+       threadobject *thread;
        bool intr;
 
-       t = (threadobject*) THREADOBJECT;
+       thread = THREADOBJECT;
+
+       /* get interrupted flag */
 
-       intr = t->interrupted;
+       intr = thread->interrupted;
 
-       t->interrupted = false;
+       /* reset interrupted flag */
+
+       thread->interrupted = false;
 
        return intr;
 }
 
 
-/* threads_thread_has_been_interrupted *********************************************************
+/* threads_thread_has_been_interrupted *****************************************
 
    Check if the given thread has been interrupted
 
@@ -1545,13 +1833,9 @@ bool threads_check_if_interrupted_and_reset(void)
 
 *******************************************************************************/
 
-bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
+bool threads_thread_has_been_interrupted(threadobject *thread)
 {
-       threadobject *t;
-
-       t = (threadobject*) thread;
-
-       return t->interrupted;
+       return thread->interrupted;
 }
 
 
@@ -1563,22 +1847,22 @@ bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
 
 void threads_sleep(s8 millis, s4 nanos)
 {
-       threadobject       *t;
-       struct timespec    wakeupTime;
-       bool               wasinterrupted;
+       threadobject    *thread;
+       struct timespec  wakeupTime;
+       bool             wasinterrupted;
 
-       t = (threadobject *) THREADOBJECT;
+       thread = THREADOBJECT;
 
        threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-       wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
+       wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
 
        if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+               exceptions_throw_interruptedexception();
 }
 
 
-/* threads_yield *****************************************************************
+/* threads_yield ***************************************************************
 
    Yield to the scheduler.
 
@@ -1590,86 +1874,6 @@ void threads_yield(void)
 }
 
 
-/* threads_java_lang_Thread_set_priority ***********************************************************
-
-   Set the priority for the given java.lang.Thread.
-
-   IN:
-      t............the java.lang.Thread
-         priority.....the priority
-
-*******************************************************************************/
-
-void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
-{
-       threadobject *thread;
-
-       thread = (threadobject*) t->vmThread;
-
-       threads_set_thread_priority(thread->tid, priority);
-}
-
-
-/* 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;
-       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;
-               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_printable_ascii(name);
-                       printf("\" ");
-
-                       if (t->daemon)
-                               printf("daemon ");
-
-#if SIZEOF_VOID_P == 8
-                       printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
-#else
-                       printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
-#endif
-
-                       /* send SIGUSR1 to thread to print stacktrace */
-
-                       pthread_kill(tobj->tid, SIGUSR1);
-
-                       /* sleep this thread a bit, so the signal can reach the thread */
-
-                       threads_sleep(10, 0);
-               }
-
-               tobj = tobj->next;
-       } while (tobj && (tobj != mainthreadobj));
-}
-
-
 /* threads_table_dump *********************************************************
 
    Dump the threads table for debugging purposes.
@@ -1679,7 +1883,7 @@ void threads_dump(void)
 
 ******************************************************************************/
 
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && 0
 static void threads_table_dump(FILE *file)
 {
        s4 i;
@@ -1698,7 +1902,7 @@ static void threads_table_dump(FILE *file)
                fprintf(file, "%4d: ", i);
 
                if (index < size) {
-                       fprintf(file, "free, nextfree = %d\n", index);
+                       fprintf(file, "free, nextfree = %d\n", (int) index);
                }
                else {
                        fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);