X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fthreads%2Fthread.cpp;h=7fd0205e2a0efc69aea69e789d8109bc9a745bbe;hb=642883f832867bf2fcb70aa702a68ba825c7118d;hp=f41502504764bc6e82f3a5d027f93269c13cbe89;hpb=0ce178c56bb73f85555e1693ed2019387838b362;p=cacao.git diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp index f41502504..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 @@ -40,18 +40,18 @@ #endif #include "native/llni.h" -#include "native/native.h" +#include "native/native.hpp" -#include "threads/lock-common.h" -#include "threads/threadlist.h" +#include "threads/lock.hpp" +#include "threads/threadlist.hpp" #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/class.h" +#include "vm/class.hpp" #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. */ @@ -405,7 +404,7 @@ static void thread_create_initial_thread(void) /* Get the main-thread (NOTE: The main thread is always the first thread in the list). */ - t = threadlist_first(); + t = ThreadList::get_main_thread(); /* The thread name. */ @@ -440,28 +439,24 @@ static void thread_create_initial_thread(void) *******************************************************************************/ -static threadobject *thread_new(void) +static threadobject *thread_new(int32_t flags) { int32_t index; threadobject *t; /* Lock the thread lists */ - threadlist_lock(); + ThreadList::lock(); - index = threadlist_get_free_index(); + index = ThreadList::get_free_thread_index(); /* Allocate a thread data structure. */ /* First, try to get one from the free-list. */ - t = threadlist_free_first(); + t = ThreadList::get_free_thread(); if (t != NULL) { - /* Remove from free list. */ - - threadlist_free_remove(t); - /* Equivalent of MZERO on the else path */ threads_impl_thread_clear(t); @@ -512,8 +507,8 @@ static threadobject *thread_new(void) assert(index != 0); t->index = index; - t->thinlock = lock_pre_compute_thinlock(t->index); - t->flags = 0; + t->thinlock = Lockword::pre_compute_thinlock(t->index); + t->flags = flags; t->state = THREAD_STATE_NEW; #if defined(ENABLE_GC_CACAO) @@ -526,11 +521,11 @@ static threadobject *thread_new(void) /* Add the thread to the thread list. */ - threadlist_add(t); + ThreadList::add_to_active_thread_list(t); /* Unlock the thread lists. */ - threadlist_unlock(); + ThreadList::unlock(); return t; } @@ -549,29 +544,13 @@ static threadobject *thread_new(void) void thread_free(threadobject *t) { - /* Lock the thread lists. */ - - threadlist_lock(); - - /* Remove the thread from the thread-list. */ - - threadlist_remove(t); - - /* Add the thread index to the free list. */ - - threadlist_index_add(t->index); - /* Set the reference to the Java object to NULL. */ thread_set_object(t, NULL); - /* Add the thread data structure to the free list. */ - - threadlist_free_add(t); - - /* Unlock the thread lists. */ + /* Release the thread. */ - threadlist_unlock(); + ThreadList::release_thread(t); } @@ -598,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. */ @@ -644,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? */ @@ -674,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) @@ -728,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; @@ -895,7 +866,7 @@ void thread_fprint_name(threadobject *t, FILE *stream) #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1) /* FIXME: In OpenJDK and CLDC the name is a char[]. */ - java_chararray_t *name; + //java_chararray_t *name; /* FIXME This prints to stdout. */ utf_display_printable_ascii(utf_null); @@ -968,6 +939,12 @@ void thread_print_info(threadobject *t) case THREAD_STATE_TIMED_WAITING: printf(" waiting on condition"); break; + case THREAD_STATE_PARKED: + printf(" parked"); + break; + case THREAD_STATE_TIMED_PARKED: + printf(" timed parked"); + break; case THREAD_STATE_TERMINATED: printf(" terminated"); break; @@ -1001,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. @@ -1012,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(); } @@ -1037,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(); } @@ -1063,17 +1048,49 @@ void thread_set_state_waiting(threadobject *t) void thread_set_state_timed_waiting(threadobject *t) { - /* Set the state inside a lock. */ + if (t->state != THREAD_STATE_TERMINATED) { + thread_set_state(t, THREAD_STATE_TIMED_WAITING); + + DEBUGTHREADS("is TIMED_WAITING", t); + } +} + - threadlist_lock(); +/* thread_set_state_parked ***************************************************** + Set the current state of the given thread to THREAD_STATE_PARKED. + + NOTE: If the thread has already terminated, don't set the state. + This is important for threads_detach_thread. + +*******************************************************************************/ + +void thread_set_state_parked(threadobject *t) +{ if (t->state != THREAD_STATE_TERMINATED) { - t->state = THREAD_STATE_TIMED_WAITING; + thread_set_state(t, THREAD_STATE_PARKED); - DEBUGTHREADS("is TIMED_WAITING", t); + DEBUGTHREADS("is PARKED", t); } +} + - threadlist_unlock(); +/* thread_set_state_timed_parked *********************************************** + + Set the current state of the given thread to THREAD_STATE_TIMED_PARKED. + + NOTE: If the thread has already terminated, don't set the state. + This is important for threads_detach_thread. + +*******************************************************************************/ + +void thread_set_state_timed_parked(threadobject *t) +{ + if (t->state != THREAD_STATE_TERMINATED) { + thread_set_state(t, THREAD_STATE_TIMED_PARKED); + + DEBUGTHREADS("is TIMED_PARKED", t); + } } @@ -1088,13 +1105,13 @@ void thread_set_state_terminated(threadobject *t) { /* Set the state inside a lock. */ - threadlist_lock(); + ThreadList::lock(); - t->state = THREAD_STATE_TERMINATED; + thread_set_state(t, THREAD_STATE_TERMINATED); DEBUGTHREADS("is TERMINATED", t); - threadlist_unlock(); + ThreadList::unlock(); } @@ -1108,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) @@ -1120,23 +1141,11 @@ threadobject *thread_get_thread(java_handle_t *h) #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) /* XXX This is just a quick hack. */ - threadobject* t; - bool equal; - - threadlist_lock(); - - for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) { - LLNI_equals(t->object, h, equal); - - if (equal == true) - break; - } - - threadlist_unlock(); + threadobject* t = ThreadList::get_thread_from_java_object(h); #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1) - log_println("threads_get_thread: IMPLEMENT ME!"); + log_println("thread_get_thread: IMPLEMENT ME!"); threadobject* t = NULL; #else @@ -1168,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: @@ -1179,62 +1190,116 @@ bool threads_thread_is_alive(threadobject *t) return false; } +/* thread_is_interrupted ******************************************************* + + Check if the given thread has been interrupted. -/* threads_dump **************************************************************** + ARGUMENTS: + t ... the thread to check - Dumps info for all threads running in the JVM. This function is - called when SIGQUIT (-\) is sent to CACAO. + RETURN VALUE: + true, if the given thread had been interrupted *******************************************************************************/ -void threads_dump(void) +bool thread_is_interrupted(threadobject *t) { - 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. */ - /* XXX we should stop the world here */ + t->waitmutex->lock(); + bool interrupted = t->interrupted; + t->waitmutex->unlock(); - /* Lock the thread lists. */ + return interrupted; +} - threadlist_lock(); - printf("Full thread dump CACAO "VERSION":\n"); +/* thread_set_interrupted ****************************************************** - /* iterate over all started threads */ + Set the interrupted flag to the given value. - for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) { - /* ignore threads which are in state NEW */ - if (t->state == THREAD_STATE_NEW) - continue; + ARGUMENTS: + interrupted ... value to set -#if defined(ENABLE_GC_CACAO) - /* Suspend the thread. */ - /* XXX Is the suspend reason correct? */ +*******************************************************************************/ - if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false) - vm_abort("threads_dump: threads_suspend_thread failed"); -#endif +void thread_set_interrupted(threadobject *t, bool interrupted) +{ + t->waitmutex->lock(); + t->interrupted = interrupted; + t->waitmutex->unlock(); +} + +/* thread_handle_set_priority ************************************************** - /* Print thread info. */ + Calls threads_set_thread_priority for the threadobject associated + with the thread indicated by handle th, while holding the thread + list lock. - printf("\n"); - thread_print_info(t); - printf("\n"); +*******************************************************************************/ - /* Print trace of thread. */ +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); +} - stacktrace_print_of_thread(t); +/* thread_handle_is_interrupted ************************************************ -#if defined(ENABLE_GC_CACAO) - /* Resume the thread. */ + Calls thread_is_interrupted for the threadobject associated with + the thread indicated by handle th, while holding the thread list + lock. - if (threads_resume_thread(t) == false) - vm_abort("threads_dump: threads_resume_thread failed"); -#endif - } +*******************************************************************************/ - /* Unlock the thread lists. */ +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; - threadlist_unlock(); + threadobject *t = thread_get_thread(th); + return t ? cacaothread_get_state(t) : THREAD_STATE_NEW; }