* Merged gc7-branch to default.
[cacao.git] / src / threads / posix / thread-posix.c
index 9fa07dc39a4ed2c759e30f8dfeb1bc00c4a3969c..cb8d82ff532461a15f46e812d62ecf834bd12d7e 100644 (file)
@@ -69,7 +69,7 @@
 # include "native/include/java_lang_ThreadGroup.h"
 #endif
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 # include "native/include/java_lang_VMThread.h"
 #endif
 
 #endif
 
 #if !defined(__DARWIN__)
+# include <semaphore.h>
+#endif
 # if defined(__LINUX__)
 #  define GC_LINUX_THREADS
 # elif defined(__IRIX__)
 #  define GC_IRIX_THREADS
+# elif defined(__DARWIN__)
+#  define GC_DARWIN_THREADS
 # endif
-# include <semaphore.h>
 # if defined(ENABLE_GC_BOEHM)
 #  include "mm/boehm-gc/include/gc.h"
 # endif
-#endif
 
 #if defined(ENABLE_JVMTI)
 #include "native/jvmti/cacaodbg.h"
@@ -128,7 +130,7 @@ static int sem_init(sem_t *sem, int pshared, int value)
 
        sem->value = value;
     
-       mutex_init(&sem->mutex, NULL)
+       mutex_init(&sem->mutex);
 
        if (pthread_cond_init(&sem->cond, NULL) < 0)
                return -1;
@@ -138,7 +140,7 @@ static int sem_init(sem_t *sem, int pshared, int value)
 
 static int sem_post(sem_t *sem)
 {
-       mutex_lock(&sem->mutex)
+       mutex_lock(&sem->mutex);
 
        sem->value++;
 
@@ -147,14 +149,14 @@ static int sem_post(sem_t *sem)
                return -1;
        }
 
-       mutex_unlock(&sem->mutex)
+       mutex_unlock(&sem->mutex);
 
        return 0;
 }
 
 static int sem_wait(sem_t *sem)
 {
-       mutex_lock(&sem->mutex)
+       mutex_lock(&sem->mutex);
 
        while (sem->value == 0) {
                pthread_cond_wait(&sem->cond, &sem->mutex);
@@ -162,7 +164,7 @@ static int sem_wait(sem_t *sem)
 
        sem->value--;
 
-       mutex_unlock(&sem->mutex)
+       mutex_unlock(&sem->mutex);
 
        return 0;
 }
@@ -172,7 +174,7 @@ static int sem_destroy(sem_t *sem)
        if (pthread_cond_destroy(&sem->cond) < 0)
                return -1;
 
-       mutex_destroy(&sem->mutex)
+       mutex_destroy(&sem->mutex);
 
        return 0;
 }
@@ -232,15 +234,12 @@ static mutex_t mutex_gc;
 static mutex_t mutex_join;
 static pthread_cond_t  cond_join;
 
-/* XXX We disable that whole bunch of code until we have the exact-GC
-   running. */
-
-#if 1
-
 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
 /* being stopped                                                              */
 static volatile int stopworldwhere;
 
+#if defined(ENABLE_GC_CACAO)
+
 /* semaphore used for acknowleding thread suspension                          */
 static sem_t suspend_ack;
 #if defined(__IRIX__)
@@ -248,7 +247,7 @@ static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
 #endif
 
-#endif /* 0 */
+#endif /* ENABLE_GC_CACAO */
 
 /* mutexes used by the fake atomic instructions                               */
 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
@@ -367,7 +366,8 @@ void unlock_stopworld(void)
 }
 
 /* XXX We disable that whole bunch of code until we have the exact-GC
-   running. */
+   running. Some of it may only be needed by the old Boehm-based
+   suspension handling. */
 
 #if 0
 
@@ -516,8 +516,6 @@ static void threads_sigsuspend_handler(ucontext_t *_uc)
 }
 #endif
 
-#endif
-
 
 /* threads_stopworld ***********************************************************
 
@@ -527,7 +525,6 @@ static void threads_sigsuspend_handler(ucontext_t *_uc)
 
 *******************************************************************************/
 
-#if !defined(DISABLE_GC)
 void threads_stopworld(void)
 {
 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
@@ -588,7 +585,6 @@ void threads_stopworld(void)
           non-signaled NEW threads can't change their state and execute
           code. */
 }
-#endif /* !defined(DISABLE_GC) */
 
 
 /* threads_startworld **********************************************************
@@ -597,7 +593,6 @@ void threads_stopworld(void)
 
 *******************************************************************************/
 
-#if !defined(DISABLE_GC)
 void threads_startworld(void)
 {
 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
@@ -657,6 +652,7 @@ void threads_startworld(void)
 
        unlock_stopworld();
 }
+
 #endif
 
 
@@ -850,9 +846,10 @@ void threads_impl_preinit(void)
                vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
 
 #if defined(ENABLE_GC_CACAO)
-       /* initialize the GC mutext */
+       /* initialize the GC mutex & suspend semaphore */
 
        mutex_init(&mutex_gc);
+       threads_sem_init(&suspend_ack, 0, 0);
 #endif
 
 #if !defined(HAVE___THREAD)
@@ -860,8 +857,6 @@ void threads_impl_preinit(void)
        if (result != 0)
                vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
 #endif
-
-       threads_sem_init(&suspend_ack, 0, 0);
 }
 
 
@@ -965,9 +960,9 @@ void threads_impl_init(void)
 static void *threads_startup_thread(void *arg)
 {
        startupinfo        *startup;
-       threadobject       *thread;
+       threadobject       *t;
        java_lang_Thread   *object;
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
        java_lang_VMThread *vmt;
 #endif
        sem_t              *psem;
@@ -993,7 +988,7 @@ static void *threads_startup_thread(void *arg)
 
        startup = arg;
 
-       thread   = startup->thread;
+       t        = startup->thread;
        function = startup->function;
        psem     = startup->psem;
 
@@ -1004,24 +999,25 @@ static void *threads_startup_thread(void *arg)
        threads_sem_wait(startup->psem_first);
 
 #if defined(__DARWIN__)
-       thread->mach_thread = mach_thread_self();
+       t->mach_thread = mach_thread_self();
 #endif
 
-       /* Store the internal thread data-structure in the TSD. */
+       /* Now that we are in the new thread, we can store the internal
+          thread data-structure in the TSD. */
 
-       thread_set_current(thread);
+       thread_set_current(t);
 
        /* get the java.lang.Thread object for this thread */
 
-       object = (java_lang_Thread *) thread_get_object(thread);
+       object = (java_lang_Thread *) thread_get_object(t);
 
        /* set our priority */
 
-       threads_set_thread_priority(thread->tid, LLNI_field_direct(object, priority));
+       threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
 
-       /* thread is completely initialized */
+       /* Thread is completely initialized. */
 
-       threads_thread_state_runnable(thread);
+       thread_set_state_runnable(t);
 
        /* tell threads_startup_thread that we registered ourselves */
        /* CAUTION: *startup becomes invalid with this!             */
@@ -1043,18 +1039,18 @@ static void *threads_startup_thread(void *arg)
                jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
 #endif
 
-       DEBUGTHREADS("starting", thread);
+       DEBUGTHREADS("starting", t);
 
        /* find and run the Thread.run()V method if no other function was passed */
 
        if (function == NULL) {
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
                /* 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_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
                LLNI_class_get(object, c);
 #else
 # error unknown classpath configuration
@@ -1075,19 +1071,19 @@ static void *threads_startup_thread(void *arg)
                        _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
                                _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
 
-#if defined(WITH_CLASSPATH_GNU)
+#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;
+               o = (java_handle_t *) vmt;
 
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
-               o   = (java_handle_t *) object;
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+               o = (java_handle_t *) object;
 #else
 # error unknown classpath configuration
 #endif
 
-               /* run the thread */
+               /* Run the thread. */
 
                (void) vm_call_method(m, o);
        }
@@ -1107,7 +1103,7 @@ static void *threads_startup_thread(void *arg)
                (function)();
        }
 
-       DEBUGTHREADS("stopping", thread);
+       DEBUGTHREADS("stopping", t);
 
 #if defined(ENABLE_JVMTI)
        /* fire thread end event */
@@ -1118,7 +1114,7 @@ static void *threads_startup_thread(void *arg)
 
        /* We ignore the return value. */
 
-       (void) threads_detach_thread(thread);
+       (void) threads_detach_thread(t);
 
        /* set ThreadMXBean variables */
 
@@ -1273,9 +1269,9 @@ bool threads_detach_thread(threadobject *t)
                   to build the java_lang_Thread_UncaughtExceptionHandler
                   header file with cacaoh. */
 
-# if defined(WITH_CLASSPATH_GNU)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
                LLNI_field_get_ref(object, exceptionHandler, handler);
-# elif defined(WITH_CLASSPATH_SUN)
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
                LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
 # endif
 
@@ -1310,13 +1306,13 @@ bool threads_detach_thread(threadobject *t)
        if (group != NULL) {
                LLNI_class_get(group, c);
 
-# if defined(WITH_CLASSPATH_GNU)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
                m = class_resolveclassmethod(c,
                                                                         utf_removeThread,
                                                                         utf_java_lang_Thread__V,
                                                                         class_java_lang_ThreadGroup,
                                                                         true);
-# elif defined(WITH_CLASSPATH_SUN)
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
                m = class_resolveclassmethod(c,
                                                                         utf_remove,
                                                                         utf_java_lang_Thread__V,
@@ -1335,12 +1331,17 @@ bool threads_detach_thread(threadobject *t)
 
                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);
        }
 #endif
 
        /* Thread has terminated. */
 
-       threads_thread_state_terminated(t);
+       thread_set_state_terminated(t);
 
        /* Notify all threads waiting on this thread.  These are joining
           this thread. */
@@ -1374,6 +1375,8 @@ bool threads_detach_thread(threadobject *t)
 }
 
 
+#if defined(ENABLE_GC_CACAO)
+
 /* threads_suspend_thread ******************************************************
 
    Suspend the passed thread. Execution stops until the thread
@@ -1430,7 +1433,6 @@ void threads_suspend_ack(u1* pc, u1* sp)
 
        /* TODO: remember dump memory size */
 
-#if defined(ENABLE_GC_CACAO)
        /* inform the GC about the suspension */
        if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
 
@@ -1443,7 +1445,6 @@ void threads_suspend_ack(u1* pc, u1* sp)
 
                }
        }
-#endif
 
        /* mark this thread as suspended and remember the PC */
        thread->pc        = pc;
@@ -1501,6 +1502,7 @@ bool threads_resume_thread(threadobject *thread)
        return true;
 }
 
+#endif
 
 /* threads_join_all_threads ****************************************************
 
@@ -1516,9 +1518,9 @@ void threads_join_all_threads(void)
 
        t = THREADOBJECT;
 
-       /* this thread is waiting for all non-daemon threads to exit */
+       /* This thread is waiting for all non-daemon threads to exit. */
 
-       threads_thread_state_waiting(t);
+       thread_set_state_waiting(t);
 
        /* enter join mutex */
 
@@ -1622,22 +1624,22 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi
                while (!t->interrupted && !t->signaled
                           && threads_current_time_is_earlier_than(wakeupTime))
                {
-                       threads_thread_state_timed_waiting(t);
+                       thread_set_state_timed_waiting(t);
 
                        pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
                                                                   wakeupTime);
 
-                       threads_thread_state_runnable(t);
+                       thread_set_state_runnable(t);
                }
        }
        else {
                /* no timeout */
                while (!t->interrupted && !t->signaled) {
-                       threads_thread_state_waiting(t);
+                       thread_set_state_waiting(t);
 
                        pthread_cond_wait(&t->waitcond, &t->waitmutex);
 
-                       threads_thread_state_runnable(t);
+                       thread_set_state_runnable(t);
                }
        }
 
@@ -1742,79 +1744,52 @@ void threads_thread_interrupt(threadobject *thread)
 }
 
 
-/* threads_check_if_interrupted_and_reset **************************************
-
-   Check if the current thread has been interrupted and reset the
-   interruption flag.
+/* threads_sleep ***************************************************************
 
-   RETURN VALUE:
-      true, if the current thread had been interrupted
+   Sleep the current thread for the specified amount of time.
 
 *******************************************************************************/
 
-bool threads_check_if_interrupted_and_reset(void)
+void threads_sleep(int64_t millis, int32_t nanos)
 {
-       threadobject *thread;
-       bool intr;
-
-       thread = THREADOBJECT;
-
-       mutex_lock(&thread->waitmutex);
-
-       /* get interrupted flag */
-
-       intr = thread->interrupted;
-
-       /* reset interrupted flag */
-
-       thread->interrupted = false;
-
-       mutex_unlock(&thread->waitmutex);
-
-       return intr;
-}
-
-
-/* threads_thread_has_been_interrupted *****************************************
-
-   Check if the given thread has been interrupted
-
-   IN:
-      t............the thread to check
-
-   RETURN VALUE:
-      true, if the given thread had been interrupted
-
-*******************************************************************************/
+       threadobject    *t;
+       struct timespec  wakeupTime;
+       bool             interrupted;
 
-bool threads_thread_has_been_interrupted(threadobject *thread)
-{
-       return thread->interrupted;
-}
+       if (millis < 0) {
+/*             exceptions_throw_illegalargumentexception("timeout value is negative"); */
+               exceptions_throw_illegalargumentexception();
+               return;
+       }
 
+       t = thread_get_current();
 
-/* threads_sleep ***************************************************************
+       if (thread_is_interrupted(t) && !exceptions_get_exception()) {
+               /* Clear interrupted flag (Mauve test:
+                  gnu/testlet/java/lang/Thread/interrupt). */
 
-   Sleep the current thread for the specified amount of time.
+               thread_set_interrupted(t, false);
 
-*******************************************************************************/
+/*             exceptions_throw_interruptedexception("sleep interrupted"); */
+               exceptions_throw_interruptedexception();
+               return;
+       }
 
-void threads_sleep(s8 millis, s4 nanos)
-{
-       threadobject    *thread;
-       struct timespec  wakeupTime;
-       bool             wasinterrupted;
+       threads_calc_absolute_time(&wakeupTime, millis, nanos);
 
-       thread = THREADOBJECT;
+       threads_wait_with_timeout(t, &wakeupTime);
 
-       threads_calc_absolute_time(&wakeupTime, millis, nanos);
+       interrupted = thread_is_interrupted(t);
 
-       threads_wait_with_timeout(thread, &wakeupTime);
+       if (interrupted) {
+               thread_set_interrupted(t, false);
 
-       wasinterrupted = threads_check_if_interrupted_and_reset();
+               /* An other exception could have been thrown
+                  (e.g. ThreadDeathException). */
 
-       if (wasinterrupted)
-               exceptions_throw_interruptedexception();
+               if (!exceptions_get_exception())
+                       exceptions_throw_interruptedexception();
+       }
 }