* src/threads/thread.cpp (thread_set_state_*): Don't take the ThreadList
[cacao.git] / src / threads / thread.cpp
index 1579fd4e1ed42269625109f877913ef3f1a9e67e..7fd0205e2a0efc69aea69e789d8109bc9a745bbe 100644 (file)
@@ -80,7 +80,7 @@ bool threads_pthreads_implementation_nptl;
 
 static void          thread_create_initial_threadgroups(void);
 static void          thread_create_initial_thread(void);
-static threadobject *thread_new(void);
+static threadobject *thread_new(int32_t flags);
 
 
 /* threads_preinit *************************************************************
@@ -138,7 +138,7 @@ void threads_preinit(void)
 
        /* Create internal thread data-structure for the main thread. */
 
-       mainthread = thread_new();
+       mainthread = thread_new(THREAD_FLAG_JAVA);
 
        /* The main thread should always have index 1. */
 
@@ -146,9 +146,8 @@ void threads_preinit(void)
                vm_abort("threads_preinit: main thread index not 1: %d != 1",
                                 mainthread->index);
 
-       /* thread is a Java thread and running */
+       /* Thread is already running. */
 
-       mainthread->flags |= THREAD_FLAG_JAVA;
        mainthread->state = THREAD_STATE_RUNNABLE;
 
        /* Store the internal thread data-structure in the TSD. */
@@ -440,7 +439,7 @@ static void thread_create_initial_thread(void)
 
 *******************************************************************************/
 
-static threadobject *thread_new(void)
+static threadobject *thread_new(int32_t flags)
 {
        int32_t       index;
        threadobject *t;
@@ -509,7 +508,7 @@ static threadobject *thread_new(void)
 
        t->index     = index;
        t->thinlock  = Lockword::pre_compute_thinlock(t->index);
-       t->flags     = 0;
+       t->flags     = flags;
        t->state     = THREAD_STATE_NEW;
 
 #if defined(ENABLE_GC_CACAO)
@@ -578,9 +577,7 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
        /* Create internal thread data-structure. */
 
-       t = thread_new();
-
-       t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+       t = thread_new(THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON);
 
        /* The thread is flagged as (non-)daemon thread, we can leave the
           mutex. */
@@ -624,11 +621,7 @@ void threads_thread_start(java_handle_t *object)
 
        /* Create internal thread data-structure. */
 
-       threadobject* t = thread_new();
-
-       /* this is a normal Java thread */
-
-       t->flags |= THREAD_FLAG_JAVA;
+       threadobject* t = thread_new(THREAD_FLAG_JAVA);
 
 #if defined(ENABLE_JAVASE)
        /* Is this a daemon thread? */
@@ -654,7 +647,9 @@ void threads_thread_start(java_handle_t *object)
        assert(jlvmt.get_handle() != NULL);
        assert(jlvmt.get_vmdata() == NULL);
 
+       ThreadList::lock();
        jlvmt.set_vmdata(t);
+       ThreadList::unlock();
 
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
@@ -708,11 +703,7 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
        /* Create internal thread data structure. */
 
-       t = thread_new();
-
-       /* Thread is a Java thread and running. */
-
-       t->flags = THREAD_FLAG_JAVA;
+       t = thread_new(THREAD_FLAG_JAVA);
 
        if (isdaemon)
                t->flags |= THREAD_FLAG_DAEMON;
@@ -1018,17 +1009,11 @@ static inline void thread_set_state(threadobject *t, int state)
 
 void thread_set_state_runnable(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       ThreadList::lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
                thread_set_state(t, THREAD_STATE_RUNNABLE);
 
                DEBUGTHREADS("is RUNNABLE", t);
        }
-
-       ThreadList::unlock();
 }
 
 
@@ -1043,17 +1028,11 @@ void thread_set_state_runnable(threadobject *t)
 
 void thread_set_state_waiting(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       ThreadList::lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
                thread_set_state(t, THREAD_STATE_WAITING);
 
                DEBUGTHREADS("is WAITING", t);
        }
-
-       ThreadList::unlock();
 }
 
 
@@ -1069,17 +1048,11 @@ void thread_set_state_waiting(threadobject *t)
 
 void thread_set_state_timed_waiting(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       ThreadList::lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
                thread_set_state(t, THREAD_STATE_TIMED_WAITING);
 
                DEBUGTHREADS("is TIMED_WAITING", t);
        }
-
-       ThreadList::unlock();
 }
 
 
@@ -1094,17 +1067,11 @@ void thread_set_state_timed_waiting(threadobject *t)
 
 void thread_set_state_parked(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       ThreadList::lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
                thread_set_state(t, THREAD_STATE_PARKED);
 
                DEBUGTHREADS("is PARKED", t);
        }
-
-       ThreadList::unlock();
 }
 
 
@@ -1119,17 +1086,11 @@ void thread_set_state_parked(threadobject *t)
 
 void thread_set_state_timed_parked(threadobject *t)
 {
-       /* Set the state inside a lock. */
-
-       ThreadList::lock();
-
        if (t->state != THREAD_STATE_TERMINATED) {
                thread_set_state(t, THREAD_STATE_TIMED_PARKED);
 
                DEBUGTHREADS("is TIMED_PARKED", t);
        }
-
-       ThreadList::unlock();
 }
 
 
@@ -1164,6 +1125,10 @@ void thread_set_state_terminated(threadobject *t)
    RETURN VALUE:
        the thread object
 
+   NOTE:
+       Usage of this function without the thread list lock held is
+       almost certainly a bug.
+
 *******************************************************************************/
 
 threadobject *thread_get_thread(java_handle_t *h)
@@ -1225,6 +1190,118 @@ bool threads_thread_is_alive(threadobject *t)
        return false;
 }
 
+/* thread_is_interrupted *******************************************************
+
+   Check if the given thread has been interrupted.
+
+   ARGUMENTS:
+       t ... the thread to check
+
+   RETURN VALUE:
+      true, if the given thread had been interrupted
+
+*******************************************************************************/
+
+bool thread_is_interrupted(threadobject *t)
+{
+       /* We need the mutex because classpath will call this function when
+          a blocking system call is interrupted. The mutex ensures that it will
+          see the correct value for the interrupted flag. */
+
+       t->waitmutex->lock();
+       bool interrupted = t->interrupted;
+       t->waitmutex->unlock();
+
+       return interrupted;
+}
+
+
+/* thread_set_interrupted ******************************************************
+
+   Set the interrupted flag to the given value.
+
+   ARGUMENTS:
+       interrupted ... value to set
+
+*******************************************************************************/
+
+void thread_set_interrupted(threadobject *t, bool interrupted)
+{
+       t->waitmutex->lock();
+       t->interrupted = interrupted;
+       t->waitmutex->unlock();
+}
+
+/* thread_handle_set_priority **************************************************
+
+   Calls threads_set_thread_priority for the threadobject associated
+   with the thread indicated by handle th, while holding the thread
+   list lock.
+
+*******************************************************************************/
+
+void thread_handle_set_priority(java_handle_t *th, int priority)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       /* For GNU classpath, this should not happen, because both
+          setPriority() and start() are synchronized. */
+       assert(t != 0);
+       threads_set_thread_priority(t->tid, priority);
+}
+
+/* thread_handle_is_interrupted ************************************************
+
+   Calls thread_is_interrupted for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+bool thread_handle_is_interrupted(java_handle_t *th)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       return t ? thread_is_interrupted(t) : false;
+}
+
+/* thread_handle_interrupt *****************************************************
+
+   Calls threads_thread_interrupt for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+void thread_handle_interrupt(java_handle_t *th)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       /* For GNU classpath, this should not happen, because both
+          interrupt() and start() are synchronized. */
+       assert(t != 0);
+       threads_thread_interrupt(t);
+}
+
+/* thread_handle_get_state *****************************************************
+
+   Calls cacaothread_get_state for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+int thread_handle_get_state(java_handle_t *th)
+{
+       ThreadListLocker l;
+
+       threadobject *t = thread_get_thread(th);
+       return t ? cacaothread_get_state(t) : THREAD_STATE_NEW;
+}
+
 
 /*
  * These are local overrides for various environment variables in Emacs.