* src/vm/signallocal.h (Signal_THREAD_INTERRUPT): Renamed to
[cacao.git] / src / threads / posix / thread-posix.cpp
index 7afa711edc7a9fd2899bcf7f13b81aaabf8102e9..cd1b19a26f7e752139cc075e556258c9376823ff 100644 (file)
@@ -32,7 +32,6 @@
 #include <assert.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <signal.h>
 #include <sys/time.h>
 #include <time.h>
 #include <errno.h>
@@ -78,7 +77,8 @@
 #include "vm/builtin.h"
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/stringlocal.h"
+#include "vm/signallocal.h"
+#include "vm/string.hpp"
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
@@ -121,10 +121,10 @@ extern "C" {
    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 +132,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 +142,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 +154,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 +165,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;
@@ -1547,12 +1534,6 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 
 void threads_thread_interrupt(threadobject *t)
 {
-#if defined(__LINUX__) && defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       /* See openjdk/jdk/src/solaris/native/java/net/linux_close.c, "sigWakeup" */
-       int sig = (__SIGRTMAX - 2);
-#else
-       int sig = SIGHUP;
-#endif
        /* Signal the thread a "waitcond" and tell it that it has been
           interrupted. */
 
@@ -1562,7 +1543,7 @@ void threads_thread_interrupt(threadobject *t)
 
        /* Interrupt blocking system call using a signal. */
 
-       pthread_kill(t->tid, sig);
+       pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL);
 
        t->waitcond->signal();
 
@@ -1572,12 +1553,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;
@@ -1603,20 +1584,29 @@ void threads_sleep(int64_t millis, int32_t nanos)
                return;
        }
 
-       threads_calc_absolute_time(&wakeupTime, millis, nanos);
-
-       threads_wait_with_timeout(t, &wakeupTime);
+       // (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);
 
-       interrupted = thread_is_interrupted(t);
+               threads_wait_with_timeout(t, &wakeupTime);
 
-       if (interrupted) {
-               thread_set_interrupted(t, false);
+               interrupted = thread_is_interrupted(t);
 
-               /* An other exception could have been thrown
-                  (e.g. ThreadDeathException). */
+               if (interrupted) {
+                       thread_set_interrupted(t, false);
 
-               if (!exceptions_get_exception())
-                       exceptions_throw_interruptedexception();
+                       // An other exception could have been thrown
+                       // (e.g. ThreadDeathException).
+                       if (!exceptions_get_exception())
+                               exceptions_throw_interruptedexception();
+               }
        }
 }