X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fthreads%2Fthread.cpp;h=7fd0205e2a0efc69aea69e789d8109bc9a745bbe;hb=642883f832867bf2fcb70aa702a68ba825c7118d;hp=0cf22e757f0518046279f00842ff6e49b8f4a924;hpb=205f73330e05a066af8701c40766323fa59b98ba;p=cacao.git diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp index 0cf22e757..7fd0205e2 100644 --- a/src/threads/thread.cpp +++ b/src/threads/thread.cpp @@ -31,7 +31,7 @@ #include "vm/types.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #if defined(ENABLE_GC_BOEHM) /* We need to include Boehm's gc.h here for GC_register_my_thread and @@ -51,7 +51,7 @@ #include "vm/exceptions.hpp" #include "vm/globals.hpp" #include "vm/javaobjects.hpp" -#include "vm/method.h" +#include "vm/method.hpp" #include "vm/options.h" #include "vm/string.hpp" #include "vm/utf8.h" @@ -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; @@ -987,6 +978,26 @@ intptr_t threads_get_current_tid(void) } +/** + * Set the current state of the given thread. This method should only + * be called while holding the threadlist-lock and after checking that + * the new state is valid. It is best to not call this method directly + * but call the specific setter methods below. + */ +static inline void thread_set_state(threadobject *t, int state) +{ + // Set the state of our internal threadobject. + t->state = state; + +#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + // Set the state of the java.lang.Thread object. + java_lang_Thread thread(thread_get_object(t)); + assert(thread.is_non_null()); + thread.set_threadStatus(state); +#endif +} + + /* thread_set_state_runnable *************************************************** Set the current state of the given thread to THREAD_STATE_RUNNABLE. @@ -998,17 +1009,11 @@ intptr_t threads_get_current_tid(void) void thread_set_state_runnable(threadobject *t) { - /* Set the state inside a lock. */ - - ThreadList::lock(); - if (t->state != THREAD_STATE_TERMINATED) { - t->state = THREAD_STATE_RUNNABLE; + thread_set_state(t, THREAD_STATE_RUNNABLE); DEBUGTHREADS("is RUNNABLE", t); } - - ThreadList::unlock(); } @@ -1023,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) { - t->state = THREAD_STATE_WAITING; + thread_set_state(t, THREAD_STATE_WAITING); DEBUGTHREADS("is WAITING", t); } - - ThreadList::unlock(); } @@ -1049,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) { - t->state = THREAD_STATE_TIMED_WAITING; + thread_set_state(t, THREAD_STATE_TIMED_WAITING); DEBUGTHREADS("is TIMED_WAITING", t); } - - ThreadList::unlock(); } @@ -1074,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) { - t->state = THREAD_STATE_PARKED; + thread_set_state(t, THREAD_STATE_PARKED); DEBUGTHREADS("is PARKED", t); } - - ThreadList::unlock(); } @@ -1099,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) { - t->state = THREAD_STATE_TIMED_PARKED; + thread_set_state(t, THREAD_STATE_TIMED_PARKED); DEBUGTHREADS("is TIMED_PARKED", t); } - - ThreadList::unlock(); } @@ -1126,7 +1107,7 @@ void thread_set_state_terminated(threadobject *t) ThreadList::lock(); - t->state = THREAD_STATE_TERMINATED; + thread_set_state(t, THREAD_STATE_TERMINATED); DEBUGTHREADS("is TERMINATED", t); @@ -1144,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) @@ -1192,6 +1177,8 @@ bool threads_thread_is_alive(threadobject *t) case THREAD_STATE_BLOCKED: case THREAD_STATE_WAITING: case THREAD_STATE_TIMED_WAITING: + case THREAD_STATE_PARKED: + case THREAD_STATE_TIMED_PARKED: return true; default: @@ -1203,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.