* src/vm/vm.cpp (vm_abort_errnum, vm_abort_errno): Removed obsolete functions.
[cacao.git] / src / threads / posix / thread-posix.cpp
index 84603487e29c50a023979176c840f7909dcc5853..b91e50f1d6725fb3149f1a49ff4fb6d9922417da 100644 (file)
@@ -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/llni.h"
-#include "native/native.h"
+#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/jit/builtin.hpp"
 #include "vm/exceptions.hpp"
@@ -66,7 +68,8 @@
 #include "vm/globals.hpp"
 #include "vm/javaobjects.hpp"
 #include "vm/options.h"
-#include "vm/signallocal.h"
+#include "vm/os.hpp"
+#include "vm/signallocal.hpp"
 #include "vm/string.hpp"
 #include "vm/vm.hpp"
 
@@ -545,21 +548,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
 
@@ -595,7 +598,7 @@ void threads_impl_preinit(void)
 #if !defined(HAVE___THREAD)
        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
 }
 
@@ -669,12 +672,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");
 }
 
 
@@ -925,33 +928,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 */
 
@@ -1292,7 +1295,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 */
@@ -1369,7 +1372,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();
@@ -1378,10 +1381,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);
 
@@ -1390,8 +1396,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);
 
@@ -1399,6 +1408,9 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi
                }
        }
 
+       if (parking)
+               t->park_permit = false;
+
        // Release the waitmutex.
        t->waitmutex->unlock();
 }
@@ -1427,7 +1439,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);
 }
 
 
@@ -1446,20 +1458,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;
 }
 
 
@@ -1538,7 +1556,7 @@ void threads_sleep(int64_t millis, int32_t nanos)
        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);
 
@@ -1553,6 +1571,47 @@ void threads_sleep(int64_t millis, int32_t nanos)
        }
 }
 
+/**
+ * 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 (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();
+}
+
 
 /* threads_yield ***************************************************************