* src/mm/gc-boehm.cpp: Define GC_SOLARIS_THREADS on Solaris.
[cacao.git] / src / threads / posix / thread-posix.cpp
index 6f61657031d8d2fe21495b19bee358483adeb0c9..a68cede39cf91c405bd86f2180fd3f137c519e65 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/posix/thread-posix.cpp - POSIX thread functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -27,6 +27,8 @@
 
 /* XXX cleanup these includes */
 
+#define __STDC_LIMIT_MACROS
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include "arch.h"
 
 #include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #if defined(ENABLE_GC_CACAO)
 # include "mm/cacao-gc/gc.h"
 #endif
 
-#include "native/jni.h"
 #include "native/llni.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"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_VMThread.h"
-#endif
+#include "native/native.hpp"
 
 #include "threads/condition.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
 #include "threads/mutex.hpp"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
 #include "threads/thread.hpp"
 
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
 
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/signallocal.h"
+#include "vm/globals.hpp"
+#include "vm/hook.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/signallocal.hpp"
 #include "vm/string.hpp"
 #include "vm/vm.hpp"
 
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
 #include "vm/jit/asmpart.h"
 
-#include "vmcore/globals.hpp"
-#include "vmcore/options.h"
+#if defined(__DARWIN__)
 
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
+typedef struct {
+       Mutex* mutex;
+       Condition* cond;
+       int value;
+} sem_t;
 
-#if !defined(__DARWIN__)
+#else
 # include <semaphore.h>
 #endif
 
 # define GC_IRIX_THREADS
 #elif defined(__DARWIN__)
 # define GC_DARWIN_THREADS
+#elif defined(__SOLARIS__)
+# define GC_SOLARIS_THREADS
 #endif
 
 #if defined(ENABLE_GC_BOEHM)
 # include "mm/boehm-gc/include/gc.h"
 #endif
 
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-
-// FIXME For now we export everything as C functions.
-extern "C" {
 
 #if defined(__DARWIN__)
 /* Darwin has no working semaphore implementation.  This one is taken
    from Boehm-GC. */
 
 /*
-   This is a very simple semaphore implementation for darwin. It
+   This is a very simple semaphore implementation for Darwin. It
    is implemented in terms of pthreads calls so it isn't async signal
    safe. This isn't a problem because signals aren't used to
-   suspend threads on darwin.
+   suspend threads on Darwin.
 */
    
 static int sem_init(sem_t *sem, int pshared, int value)
@@ -132,12 +125,9 @@ static int sem_init(sem_t *sem, int pshared, int value)
        if (pshared)
                assert(0);
 
-       sem->value = value;
-    
        sem->mutex = new Mutex();
-
-       if (pthread_cond_init(&sem->cond, NULL) < 0)
-               return -1;
+       sem->cond  = new Condition();
+       sem->value = value;
 
        return 0;
 }
@@ -145,14 +135,8 @@ static int sem_init(sem_t *sem, int pshared, int value)
 static int sem_post(sem_t *sem)
 {
        sem->mutex->lock();
-
        sem->value++;
-
-       if (pthread_cond_signal(&sem->cond) < 0) {
-               sem->mutex->unlock();
-               return -1;
-       }
-
+       sem->cond->signal();
        sem->mutex->unlock();
 
        return 0;
@@ -163,12 +147,10 @@ static int sem_wait(sem_t *sem)
        sem->mutex->lock();
 
        while (sem->value == 0) {
-#error We cannot call pthread_cond_wait on a Mutex-class pointer.
-               pthread_cond_wait(&sem->cond, &sem->mutex);
+               sem->cond->wait(sem->mutex);
        }
 
        sem->value--;
-
        sem->mutex->unlock();
 
        return 0;
@@ -176,9 +158,7 @@ static int sem_wait(sem_t *sem)
 
 static int sem_destroy(sem_t *sem)
 {
-       if (pthread_cond_destroy(&sem->cond) < 0)
-               return -1;
-
+       delete sem->cond;
        delete sem->mutex;
 
        return 0;
@@ -459,33 +439,6 @@ void threads_startworld(void)
 #endif
 
 
-/* threads_impl_thread_init ****************************************************
-
-   Initialize OS-level locking constructs in threadobject.
-
-   IN:
-      t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_init(threadobject *t)
-{
-       /* initialize the mutex and the condition */
-
-       t->flc_lock = new Mutex();
-       t->flc_cond = new Condition();
-
-       t->waitmutex = new Mutex();
-       t->waitcond = new Condition();
-
-       t->suspendmutex = new Mutex();
-       t->suspendcond = new Condition();
-
-#if defined(ENABLE_TLH)
-       tlh_init(&(t->tlh));
-#endif
-}
-
 /* threads_impl_thread_clear ***************************************************
 
    Clears all fields in threadobject the way an MZERO would have
@@ -536,7 +489,7 @@ void threads_impl_thread_clear(threadobject *t)
        t->es = NULL;
 #endif
 
-       MZERO(&t->dumpinfo, dumpinfo_t, 1);
+       // Simply reuse the existing dump memory.
 }
 
 /* threads_impl_thread_reuse ***************************************************
@@ -602,21 +555,21 @@ void threads_impl_thread_free(threadobject *t)
        result = pthread_cond_destroy(&(t->flc_cond));
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
 
        delete t->waitmutex;
 
        result = pthread_cond_destroy(&(t->waitcond));
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
 
        delete t->suspendmutex;
 
        result = pthread_cond_destroy(&(t->suspendcond));
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
 }
 #endif
 
@@ -632,8 +585,6 @@ void threads_impl_thread_free(threadobject *t)
 
 void threads_impl_preinit(void)
 {
-       int result;
-
        stopworldlock = new Mutex();
 
        /* initialize exit mutex and condition (on exit we join all
@@ -650,9 +601,9 @@ void threads_impl_preinit(void)
 #endif
 
 #if !defined(HAVE___THREAD)
-       result = pthread_key_create(&thread_current_key, NULL);
+       int result = pthread_key_create(&thread_current_key, NULL);
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
+               os::abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
 #endif
 }
 
@@ -726,12 +677,12 @@ void threads_impl_init(void)
        result = pthread_attr_init(&attr);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
+               os::abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
 
        result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
+               os::abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
 }
 
 
@@ -756,17 +707,12 @@ void threads_impl_init(void)
 
 static void *threads_startup_thread(void *arg)
 {
-       startupinfo        *startup;
-       threadobject       *t;
-       java_lang_Thread   *object;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       java_lang_VMThread *vmt;
-#endif
-       sem_t              *psem;
-       classinfo          *c;
-       methodinfo         *m;
-       java_handle_t      *o;
-       functionptr         function;
+       startupinfo  *startup;
+       threadobject *t;
+       sem_t        *psem;
+       classinfo    *c;
+       methodinfo   *m;
+       functionptr   function;
 
 #if defined(ENABLE_GC_BOEHM)
 # if !defined(__DARWIN__)
@@ -829,13 +775,13 @@ static void *threads_startup_thread(void *arg)
 # endif
 #endif
 
-       /* get the java.lang.Thread object for this thread */
-
-       object = (java_lang_Thread *) thread_get_object(t);
+       // Get the java.lang.Thread object for this thread.
+       java_handle_t* object = thread_get_object(t);
+       java_lang_Thread jlt(object);
 
        /* set our priority */
 
-       threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
+       threads_set_thread_priority(t->tid, jlt.get_priority());
 
        /* Thread is completely initialized. */
 
@@ -854,12 +800,8 @@ static void *threads_startup_thread(void *arg)
                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
+       // Hook point just before the threads initial method is executed.
+       Hook::thread_start(t);
 
        DEBUGTHREADS("starting", t);
 
@@ -883,45 +825,25 @@ static void *threads_startup_thread(void *arg)
                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 (_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; */
-#warning Move to C++
-
 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-               /* we need to start the run method of java.lang.VMThread */
 
-               LLNI_field_get_ref(object, vmThread, vmt);
-               o = (java_handle_t *) vmt;
+               // We need to start the run method of java.lang.VMThread.
+               java_lang_VMThread jlvmt(jlt.get_vmThread());
+               java_handle_t* h = jlvmt.get_handle();
 
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-               o = (java_handle_t *) object;
+
+               java_handle_t* h = jlt.get_handle();
+
 #else
 # error unknown classpath configuration
 #endif
 
                /* Run the thread. */
 
-               (void) vm_call_method(m, o);
+               (void) vm_call_method(m, h);
        }
        else {
-               /* set ThreadMXBean variables */
-
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
-
-/*             if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
-/*                     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
-/*                     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
-/*                             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
-#warning Move to C++
-
                /* call passed function, e.g. finalizer_thread */
 
                (function)();
@@ -929,22 +851,13 @@ static void *threads_startup_thread(void *arg)
 
        DEBUGTHREADS("stopping", t);
 
-#if defined(ENABLE_JVMTI)
-       /* fire thread end event */
-
-       if (jvmti)
-               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
-#endif
+       // Hook point just after the threads initial method returned.
+       Hook::thread_end(t);
 
        /* We ignore the return value. */
 
        (void) thread_detach_current_thread();
 
-       /* set ThreadMXBean variables */
-
-/*     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
-#warning Move to C++
-
        return NULL;
 }
 
@@ -985,33 +898,33 @@ void threads_impl_thread_start(threadobject *thread, functionptr f)
        result = pthread_attr_init(&attr);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
+               os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
 
     result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
     if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
+               os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
 
        /* initialize thread stacksize */
 
        result = pthread_attr_setstacksize(&attr, opt_stacksize);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
+               os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
 
        /* create the thread */
 
        result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
+               os::abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
 
        /* destroy the thread attributes */
 
        result = pthread_attr_destroy(&attr);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
 
        /* signal that pthread_create has returned, so thread->tid is valid */
 
@@ -1056,19 +969,7 @@ void threads_set_thread_priority(pthread_t tid, int priority)
  */
 bool thread_detach_current_thread(void)
 {
-       threadobject          *t;
-       bool                   result;
-       java_lang_Thread      *object;
-       java_handle_t         *o;
-#if defined(ENABLE_JAVASE)
-       java_lang_ThreadGroup *group;
-       java_handle_t         *e;
-       void                  *handler;
-       classinfo             *c;
-       methodinfo            *m;
-#endif
-
-       t = thread_get_current();
+       threadobject* t = thread_get_current();
 
        /* Sanity check. */
 
@@ -1077,23 +978,22 @@ bool thread_detach_current_thread(void)
     /* If the given thread has already been detached, this operation
           is a no-op. */
 
-       result = thread_is_attached(t);
-
-       if (result == false)
+       if (thread_is_attached(t) == false)
                return true;
 
        DEBUGTHREADS("detaching", t);
 
-       object = (java_lang_Thread *) thread_get_object(t);
+       java_handle_t* object = thread_get_object(t);
+       java_lang_Thread jlt(object);
 
 #if defined(ENABLE_JAVASE)
-       LLNI_field_get_ref(object, group, group);
+       java_handle_t* group = jlt.get_group();
 
     /* If there's an uncaught exception, call uncaughtException on the
        thread's exception handler, or the thread's group if this is
        unset. */
 
-       e = exceptions_get_and_clear_exception();
+       java_handle_t* e = exceptions_get_and_clear_exception();
 
     if (e != NULL) {
                /* We use the type void* for handler here, as it's not trivial
@@ -1101,30 +1001,37 @@ bool thread_detach_current_thread(void)
                   header file with cacaoh. */
 
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-               LLNI_field_get_ref(object, exceptionHandler, handler);
+
+               java_handle_t* handler = jlt.get_exceptionHandler();
+
 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-               LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
+
+               java_handle_t* handler = jlt.get_uncaughtExceptionHandler();
+
 # endif
 
+               classinfo*     c;
+               java_handle_t* h;
+
                if (handler != NULL) {
                        LLNI_class_get(handler, c);
-                       o = (java_handle_t *) handler;
+                       h = (java_handle_t *) handler;
                }
                else {
                        LLNI_class_get(group, c);
-                       o = (java_handle_t *) group;
+                       h = (java_handle_t *) group;
                }
 
-               m = class_resolveclassmethod(c,
-                                                                        utf_uncaughtException,
-                                                                        utf_java_lang_Thread_java_lang_Throwable__V,
-                                                                        NULL,
-                                                                        true);
+               methodinfo* m = class_resolveclassmethod(c,
+                                                                                                utf_uncaughtException,
+                                                                                                utf_java_lang_Thread_java_lang_Throwable__V,
+                                                                                                NULL,
+                                                                                                true);
 
                if (m == NULL)
                        return false;
 
-               (void) vm_call_method(m, o, object, e);
+               (void) vm_call_method(m, h, object, e);
 
                if (exceptions_get_exception())
                        return false;
@@ -1135,20 +1042,21 @@ bool thread_detach_current_thread(void)
        /* Remove thread from the thread group. */
 
        if (group != NULL) {
+               classinfo* c;
                LLNI_class_get(group, c);
 
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-               m = class_resolveclassmethod(c,
-                                                                        utf_removeThread,
-                                                                        utf_java_lang_Thread__V,
-                                                                        class_java_lang_ThreadGroup,
-                                                                        true);
+               methodinfo* m = class_resolveclassmethod(c,
+                                                                                                utf_removeThread,
+                                                                                                utf_java_lang_Thread__V,
+                                                                                                class_java_lang_ThreadGroup,
+                                                                                                true);
 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-               m = class_resolveclassmethod(c,
-                                                                        utf_remove,
-                                                                        utf_java_lang_Thread__V,
-                                                                        class_java_lang_ThreadGroup,
-                                                                        true);
+               methodinfo* m = class_resolveclassmethod(c,
+                                                                                                utf_remove,
+                                                                                                utf_java_lang_Thread__V,
+                                                                                                class_java_lang_ThreadGroup,
+                                                                                                true);
 # else
 #  error unknown classpath configuration
 # endif
@@ -1156,17 +1064,14 @@ bool thread_detach_current_thread(void)
                if (m == NULL)
                        return false;
 
-               o = (java_handle_t *) group;
-
-               (void) vm_call_method(m, o, object);
+               (void) vm_call_method(m, group, object);
 
                if (exceptions_get_exception())
                        return false;
 
-               /* Reset the threadgroup in the Java thread object (Mauve
-                  test: gnu/testlet/java/lang/Thread/getThreadGroup). */
-
-               LLNI_field_set_ref(object, group, NULL);
+               // Clear the ThreadGroup in the Java thread object (Mauve
+               // test: gnu/testlet/java/lang/Thread/getThreadGroup).
+               jlt.set_group(NULL);
        }
 #endif
 
@@ -1177,15 +1082,13 @@ bool thread_detach_current_thread(void)
        /* Notify all threads waiting on this thread.  These are joining
           this thread. */
 
-       o = (java_handle_t *) object;
-
        /* XXX Care about exceptions? */
-       (void) lock_monitor_enter(o);
+       (void) lock_monitor_enter(jlt.get_handle());
        
-       lock_notify_all_object(o);
+       lock_notify_all_object(jlt.get_handle());
 
        /* XXX Care about exceptions? */
-       (void) lock_monitor_exit(o);
+       (void) lock_monitor_exit(jlt.get_handle());
 
        /* Enter the join-mutex before calling thread_free, so
           threads_join_all_threads gets the correct number of non-daemon
@@ -1206,134 +1109,146 @@ bool thread_detach_current_thread(void)
 }
 
 
-/* threads_suspend_thread ******************************************************
-
-   Suspend the passed thread. Execution stops until the thread
-   is explicitly resumend again.
-
-   IN:
-     reason.....Reason for suspending this thread.
-
-*******************************************************************************/
-
-bool threads_suspend_thread(threadobject *thread, s4 reason)
+/**
+ * Internal helper function which suspends the current thread. This is
+ * the core method of the suspension mechanism actually blocking the
+ * execution until the suspension reason is cleared again. Note that
+ * the current thread needs to hold the suspension mutex while calling
+ * this function.
+ */
+static void threads_suspend_self()
 {
-       /* acquire the suspendmutex */
-       thread->suspendmutex->lock();
-
-       if (thread->suspended) {
-               thread->suspendmutex->unlock();
-               return false;
-       }
+       threadobject* thread = THREADOBJECT;
 
-       /* set the reason for the suspension */
-       thread->suspend_reason = reason;
+       DEBUGTHREADS("suspending", thread);
 
-       /* send the suspend signal to the thread */
-       assert(thread != THREADOBJECT);
-       if (pthread_kill(thread->tid, SIGUSR1) != 0)
-               vm_abort("threads_suspend_thread: pthread_kill failed: %s",
-                                strerror(errno));
+       // Mark thread as suspended.
+       assert(!thread->suspended);
+       assert(thread->suspend_reason != SUSPEND_REASON_NONE);
+       thread->suspended = true;
 
-       /* REMEMBER: do not release the suspendmutex, this is done
-          by the thread itself in threads_suspend_ack().  */
+       // Acknowledge the suspension.
+       thread->suspendcond->broadcast();
 
-       return true;
-}
+#if defined(ENABLE_GC_CACAO)
+       // If we are stopping the world, we should send a global ack.
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD)
+               threads_sem_post(&suspend_ack);
+#endif
 
+       // Release the suspension mutex and wait till we are resumed.
+       thread->suspendcond->wait(thread->suspendmutex);
 
-/* threads_suspend_ack *********************************************************
+#if defined(ENABLE_GC_CACAO)
+       // XXX This is propably not ok!
+       // If we are starting the world, we should send a global ack.
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD)
+               threads_sem_post(&suspend_ack);
+#endif
 
-   Acknowledges the suspension of the current thread.
+       // Mark thread as not suspended.
+       assert(thread->suspended);
+       assert(thread->suspend_reason == SUSPEND_REASON_NONE);
+       thread->suspended = false;
 
-   IN:
-     pc.....The PC where the thread suspended its execution.
-     sp.....The SP before the thread suspended its execution.
+       DEBUGTHREADS("resuming", thread);
+}
 
-*******************************************************************************/
 
-#if defined(ENABLE_GC_CACAO)
-void threads_suspend_ack(u1* pc, u1* sp)
+/**
+ * Suspend the passed thread. Execution of that thread stops until the thread
+ * is explicitly resumend again.
+ *
+ * @param thread The thread to be suspended.
+ * @param reason Reason for suspending the given thread.
+ * @return True of operation was successful, false otherwise.
+ */
+bool threads_suspend_thread(threadobject *thread, int32_t reason)
 {
-       threadobject *thread;
-
-       thread = THREADOBJECT;
-
-       assert(thread->suspend_reason != 0);
+       // Sanity check.
+       assert(reason != SUSPEND_REASON_NONE);
 
-       /* TODO: remember dump memory size */
+       // Guard this with the suspension mutex.
+       MutexLocker ml(*thread->suspendmutex);
 
-       /* inform the GC about the suspension */
-       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
+       // Check if thread is already suspended.
+       if (thread->suspended)
+               return false;
 
-               /* check if the GC wants to leave the thread running */
-               if (!gc_suspend(thread, pc, sp)) {
+       // Check if thread is in the process of suspending.
+       if (thread->suspend_reason != SUSPEND_REASON_NONE)
+               return false;
 
-                       /* REMEMBER: we do not unlock the suspendmutex because the thread
-                          will suspend itself again at a later time */
-                       return;
+       // Set the reason for suspending the thread.
+       thread->suspend_reason = reason;
 
-               }
+       if (thread == THREADOBJECT) {
+               // We already hold the suspension mutex and can suspend ourselves
+               // immediately without using signals at all.
+               threads_suspend_self();
        }
-
-       /* mark this thread as suspended and remember the PC */
-       thread->pc        = pc;
-       thread->suspended = true;
-
-       /* if we are stopping the world, we should send a global ack */
-       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
-               threads_sem_post(&suspend_ack);
+       else {
+               // Send the suspend signal to the other thread.
+               if (pthread_kill(thread->tid, SIGUSR1) != 0)
+                       os::abort_errno("threads_suspend_thread: pthread_kill failed");
+
+               // Wait for the thread to acknowledge the suspension.
+               // XXX A possible optimization would be to not wait here, but you
+               //     better think this through twice before trying it!
+               thread->suspendcond->wait(thread->suspendmutex);
        }
 
-       DEBUGTHREADS("suspending", thread);
+       return true;
+}
 
-       /* release the suspension mutex and wait till we are resumed */
-       thread->suspendcond->wait(thread->suspendmutex);
 
-       DEBUGTHREADS("resuming", thread);
+/**
+ * Resumes execution of the passed thread.
+ *
+ * @param thread The thread to be resumed.
+ * @param reason Reason for suspending the given thread.
+ * @return True of operation was successful, false otherwise.
+ */
+bool threads_resume_thread(threadobject *thread, int32_t reason)
+{
+       // Sanity check.
+       assert(thread != THREADOBJECT);
+       assert(reason != SUSPEND_REASON_NONE);
 
-       /* if we are stopping the world, we should send a global ack */
-       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
-               threads_sem_post(&suspend_ack);
-       }
+       // Guard this with the suspension mutex.
+       MutexLocker ml(*thread->suspendmutex);
 
-       /* TODO: free dump memory */
+       // Check if thread really is suspended.
+       if (!thread->suspended)
+               return false;
 
-       /* release the suspendmutex */
-       thread->suspendmutex->unlock();
-}
-#endif
+       // Threads can only be resumed for the same reason they were suspended.
+       if (thread->suspend_reason != reason)
+               return false;
 
+       // Clear the reason for suspending the thread.
+       thread->suspend_reason = SUSPEND_REASON_NONE;
 
-/* threads_resume_thread *******************************************************
+       // Tell everyone that the thread should resume.
+       thread->suspendcond->broadcast();
 
-   Resumes the execution of the passed thread.
+       return true;
+}
 
-*******************************************************************************/
 
-#if defined(ENABLE_GC_CACAO)
-bool threads_resume_thread(threadobject *thread)
+/**
+ * Acknowledges the suspension of the current thread.
+ */
+void threads_suspend_ack()
 {
-       /* acquire the suspendmutex */
-       thread->suspendmutex->lock();
-
-       if (!thread->suspended) {
-               thread->suspendmutex->unlock();
-               return false;
-       }
-
-       thread->suspended = false;
-
-       /* tell everyone that the thread should resume */
-       assert(thread != THREADOBJECT);
-       thread->suspendcond->broadcast();
+       threadobject* thread = THREADOBJECT;
 
-       /* release the suspendmutex */
-       thread->suspendmutex->unlock();
+       // Guard this with the suspension mutex.
+       MutexLocker ml(*thread->suspendmutex);
 
-       return true;
+       // Suspend ourselves while holding the suspension mutex.
+       threads_suspend_self();
 }
-#endif
 
 
 /* threads_join_all_threads ****************************************************
@@ -1362,7 +1277,7 @@ void threads_join_all_threads(void)
           compare against 1 because the current (main thread) is also a
           non-daemon thread. */
 
-       while (threadlist_get_non_daemons() > 1)
+       while (ThreadList::get_number_of_non_daemon_threads() > 1)
                cond_join->wait(mutex_join);
 
        /* leave join mutex */
@@ -1439,7 +1354,7 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv)
 
 *******************************************************************************/
 
-static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
+static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime, bool parking)
 {
        // Acquire the waitmutex.
        t->waitmutex->lock();
@@ -1448,10 +1363,13 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi
 
        if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
                /* with timeout */
-               while (!t->interrupted && !t->signaled
+               while (!t->interrupted && !(parking ? t->park_permit : t->signaled)
                           && threads_current_time_is_earlier_than(wakeupTime))
                {
-                       thread_set_state_timed_waiting(t);
+                       if (parking)
+                               thread_set_state_timed_parked(t);
+                       else
+                               thread_set_state_timed_waiting(t);
 
                        t->waitcond->timedwait(t->waitmutex, wakeupTime);
 
@@ -1460,8 +1378,11 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi
        }
        else {
                /* no timeout */
-               while (!t->interrupted && !t->signaled) {
-                       thread_set_state_waiting(t);
+               while (!t->interrupted && !(parking ? t->park_permit : t->signaled)) {
+                       if (parking)
+                               thread_set_state_parked(t);
+                       else
+                               thread_set_state_waiting(t);
 
                        t->waitcond->wait(t->waitmutex);
 
@@ -1469,6 +1390,9 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi
                }
        }
 
+       if (parking)
+               t->park_permit = false;
+
        // Release the waitmutex.
        t->waitmutex->unlock();
 }
@@ -1497,7 +1421,7 @@ void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
 
        /* wait */
 
-       threads_wait_with_timeout(thread, &wakeupTime);
+       threads_wait_with_timeout(thread, &wakeupTime, false);
 }
 
 
@@ -1516,20 +1440,26 @@ void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
 
 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 {
-       if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
+       // (at least with GNU classpath) we know that 0 <= nanos <= 999999
+       do {
+               if (!millis && !nanos)
+                       break;
                struct timeval tv;
-               long nsec;
                gettimeofday(&tv, NULL);
-               tv.tv_sec += millis / 1000;
+               s8 secs = tv.tv_sec + millis / 1000;
+               if (secs > INT32_MAX)   // integer overflow
+                       break;
+               tv.tv_sec = secs;
                millis %= 1000;
-               nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
+               long nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
                tm->tv_sec = tv.tv_sec + nsec / 1000000000;
+               if (tm->tv_sec < tv.tv_sec) // integer overflow
+                       break;
                tm->tv_nsec = nsec % 1000000000;
-       }
-       else {
-               tm->tv_sec = 0;
-               tm->tv_nsec = 0;
-       }
+               return;
+       } while (0);
+       tm->tv_sec = 0;
+       tm->tv_nsec = 0;
 }
 
 
@@ -1556,7 +1486,7 @@ void threads_thread_interrupt(threadobject *t)
 
        /* Interrupt blocking system call using a signal. */
 
-       pthread_kill(t->tid, Signal_THREAD_INTERRUPT);
+       pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL);
 
        t->waitcond->signal();
 
@@ -1566,12 +1496,12 @@ void threads_thread_interrupt(threadobject *t)
 }
 
 
-/* threads_sleep ***************************************************************
-
-   Sleep the current thread for the specified amount of time.
-
-*******************************************************************************/
-
+/**
+ * Sleep the current thread for the specified amount of time.
+ *
+ * @param millis Milliseconds to sleep.
+ * @param nanos  Nanoseconds to sleep.
+ */
 void threads_sleep(int64_t millis, int32_t nanos)
 {
        threadobject    *t;
@@ -1597,21 +1527,71 @@ void threads_sleep(int64_t millis, int32_t nanos)
                return;
        }
 
-       threads_calc_absolute_time(&wakeupTime, millis, nanos);
+       // (Note taken from classpath/vm/reference/java/lang/VMThread.java (sleep))
+       // Note: JDK treats a zero length sleep is like Thread.yield(),
+       // without checking the interrupted status of the thread.  It's
+       // unclear if this is a bug in the implementation or the spec.
+       // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 */
+       if (millis == 0 && nanos == 0) {
+               threads_yield();
+       }
+       else {
+               threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-       threads_wait_with_timeout(t, &wakeupTime);
+               threads_wait_with_timeout(t, &wakeupTime, false);
 
-       interrupted = thread_is_interrupted(t);
+               interrupted = thread_is_interrupted(t);
 
-       if (interrupted) {
-               thread_set_interrupted(t, false);
+               if (interrupted) {
+                       thread_set_interrupted(t, false);
+
+                       // An other exception could have been thrown
+                       // (e.g. ThreadDeathException).
+                       if (!exceptions_get_exception())
+                               exceptions_throw_interruptedexception();
+               }
+       }
+}
 
-               /* An other exception could have been thrown
-                  (e.g. ThreadDeathException). */
+/**
+ * Park the current thread for the specified amount of time or until a
+ * specified deadline.
+ *
+ * @param absolute Is the time in nanos a deadline or a duration?
+ * @param nanos    Nanoseconds to park (absolute=false)
+ *                 or deadline in milliseconds (absolute=true)
+ */
+void threads_park(bool absolute, int64_t nanos)
+{
+       threadobject    *t;
+       struct timespec  wakeupTime;
+
+       t = thread_get_current();
 
-               if (!exceptions_get_exception())
-                       exceptions_throw_interruptedexception();
+       if (absolute) {
+               wakeupTime.tv_nsec = 0;
+               wakeupTime.tv_sec = nanos / 1000; /* milliseconds */
        }
+       else
+               threads_calc_absolute_time(&wakeupTime, nanos / 1000000, nanos % 1000000);
+
+       threads_wait_with_timeout(t, &wakeupTime, true);
+}
+
+/**
+ * Unpark the specified thread.
+ *
+ * @param t The thread to unpark.
+ */
+void threads_unpark(threadobject *t)
+{
+       t->waitmutex->lock();
+
+       t->waitcond->signal();
+
+       t->park_permit = true;
+
+       t->waitmutex->unlock();
 }
 
 
@@ -1638,8 +1618,6 @@ void threads_tlh_remove_frame() {
 
 #endif
 
-} // extern "C"
-
 
 /*
  * These are local overrides for various environment variables in Emacs.