From: Stefan Ring Date: Fri, 22 Apr 2011 19:10:41 +0000 (+0200) Subject: merged threadlist & threadobject improvements X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=2d0318e8ef5490edb37dd0727e0b58f2feb2c3bf;hp=99748a8b518bdd870dddd69a85a49bf654da4156 merged threadlist & threadobject improvements --- diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index 6a98636ff..0d365146f 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -1,6 +1,6 @@ /* src/native/vm/openjdk/jvm.cpp - HotSpot VM interface functions - Copyright (C) 2007, 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2009 Theobroma Systems Ltd. @@ -3250,7 +3250,7 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) for (List::iterator it = active_threads.begin(); it != active_threads.end(); it++) { threadobject* t = *it; - java_handle_t* h = thread_get_object(t); + java_handle_t* h = LLNI_WRAP(t->object); assert(h != NULL); oa.set_element(index, h); diff --git a/src/threads/posix/thread-posix.cpp b/src/threads/posix/thread-posix.cpp index 1d9b3881e..ce03f8016 100644 --- a/src/threads/posix/thread-posix.cpp +++ b/src/threads/posix/thread-posix.cpp @@ -209,7 +209,6 @@ static Mutex* mutex_gc; #endif /* global mutex and condition for joining threads on exit */ -static Mutex* mutex_join; static Condition* cond_join; #if defined(ENABLE_GC_CACAO) @@ -459,6 +458,7 @@ void threads_impl_thread_clear(threadobject *t) t->index = 0; t->flags = 0; t->state = 0; + t->is_in_active_list = false; t->tid = 0; @@ -532,6 +532,11 @@ void threads_impl_thread_reuse(threadobject *t) #endif } +void threads_impl_clear_heap_pointers(threadobject *t) +{ + t->object = 0; + t->flc_object = 0; +} /* threads_impl_preinit ******************************************************** @@ -549,7 +554,6 @@ void threads_impl_preinit(void) /* initialize exit mutex and condition (on exit we join all threads) */ - mutex_join = new Mutex(); cond_join = new Condition(); #if defined(ENABLE_GC_CACAO) @@ -594,30 +598,6 @@ void threads_mutex_gc_unlock(void) } #endif -/* threads_mutex_join_lock ***************************************************** - - Enter the join mutex. - -*******************************************************************************/ - -void threads_mutex_join_lock(void) -{ - mutex_join->lock(); -} - - -/* threads_mutex_join_unlock *************************************************** - - Leave the join mutex. - -*******************************************************************************/ - -void threads_mutex_join_unlock(void) -{ - mutex_join->unlock(); -} - - /* threads_impl_init *********************************************************** Initializes the implementation specific bits. @@ -735,7 +715,7 @@ static void *threads_startup_thread(void *arg) #endif // Get the java.lang.Thread object for this thread. - java_handle_t* object = thread_get_object(t); + java_handle_t* object = LLNI_WRAP(t->object); java_lang_Thread jlt(object); /* set our priority */ @@ -920,7 +900,7 @@ bool thread_detach_current_thread(void) DEBUGTHREADS("detaching", t); - java_handle_t* object = thread_get_object(t); + java_handle_t* object = LLNI_WRAP(t->object); java_lang_Thread jlt(object); #if defined(ENABLE_JAVASE) @@ -1005,11 +985,11 @@ bool thread_detach_current_thread(void) /* XXX Care about exceptions? */ (void) lock_monitor_exit(jlt.get_handle()); - /* Enter the join-mutex before calling thread_free, so - threads_join_all_threads gets the correct number of non-daemon - threads. */ + t->waitmutex->lock(); + t->tid = 0; + t->waitmutex->unlock(); - threads_mutex_join_lock(); + ThreadList::lock(); /* Free the internal thread data-structure. */ @@ -1018,7 +998,10 @@ bool thread_detach_current_thread(void) /* Signal that this thread has finished and leave the mutex. */ cond_join->signal(); - threads_mutex_join_unlock(); + ThreadList::unlock(); + + t->suspendmutex->lock(); + t->suspendmutex->unlock(); return true; } @@ -1052,7 +1035,8 @@ static void threads_suspend_self() #endif // Release the suspension mutex and wait till we are resumed. - thread->suspendcond->wait(thread->suspendmutex); + while (thread->suspend_reason != SUSPEND_REASON_NONE) + thread->suspendcond->wait(thread->suspendmutex); #if defined(ENABLE_GC_CACAO) // XXX This is propably not ok! @@ -1072,7 +1056,7 @@ static void threads_suspend_self() /** * Suspend the passed thread. Execution of that thread stops until the thread - * is explicitly resumend again. + * is explicitly resumed again. * * @param thread The thread to be suspended. * @param reason Reason for suspending the given thread. @@ -1104,13 +1088,14 @@ bool threads_suspend_thread(threadobject *thread, int32_t reason) } else { // Send the suspend signal to the other thread. + if (!thread->tid) + return false; if (pthread_kill(thread->tid, SIGUSR1) != 0) os::abort_errno("threads_suspend_thread: pthread_kill failed"); // Wait for the thread to acknowledge the suspension. - // XXX A possible optimization would be to not wait here, but you - // better think this through twice before trying it! - thread->suspendcond->wait(thread->suspendmutex); + while (!thread->suspended) + thread->suspendcond->wait(thread->suspendmutex); } return true; @@ -1186,18 +1171,18 @@ void threads_join_all_threads(void) /* enter join mutex */ - threads_mutex_join_lock(); + ThreadList::lock(); /* Wait for condition as long as we have non-daemon threads. We compare against 1 because the current (main thread) is also a non-daemon thread. */ while (ThreadList::get_number_of_non_daemon_threads() > 1) - cond_join->wait(mutex_join); + ThreadList::wait_cond(cond_join); /* leave join mutex */ - threads_mutex_join_unlock(); + ThreadList::unlock(); } @@ -1401,7 +1386,8 @@ void threads_thread_interrupt(threadobject *t) /* Interrupt blocking system call using a signal. */ - pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL); + if (t->tid) + pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL); t->waitcond->signal(); diff --git a/src/threads/posix/thread-posix.hpp b/src/threads/posix/thread-posix.hpp index e24f6cc2e..b8e63635f 100644 --- a/src/threads/posix/thread-posix.hpp +++ b/src/threads/posix/thread-posix.hpp @@ -1,6 +1,6 @@ /* src/threads/posix/thread-posix.hpp - POSIX thread functions - Copyright (C) 1996-2005, 2006, 2007, 2008 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -74,6 +74,7 @@ struct threadobject { s4 index; /* thread index, starting with 1 */ u4 flags; /* flag field */ u4 state; /* state field */ + bool is_in_active_list; /* for debugging only */ pthread_t tid; /* pthread id */ diff --git a/src/threads/thread-classpath.cpp b/src/threads/thread-classpath.cpp index 48f0fe999..166052c9a 100644 --- a/src/threads/thread-classpath.cpp +++ b/src/threads/thread-classpath.cpp @@ -77,9 +77,7 @@ void ThreadRuntimeClasspath::setup_thread_vmdata(const java_lang_Thread& jlt, th assert(jlvmt.get_handle() != NULL); assert(jlvmt.get_vmdata() == NULL); - ThreadList::lock(); jlvmt.set_vmdata(t); - ThreadList::unlock(); } void ThreadRuntimeClasspath::print_thread_name(const java_lang_Thread& jlt, FILE *stream) @@ -158,6 +156,11 @@ bool ThreadRuntimeClasspath::invoke_thread_initializer(java_lang_Thread& jlt, th return true; } +void ThreadRuntimeClasspath::clear_heap_reference(java_lang_Thread& jlt) +{ + // Nothing to do. +} + #endif /* ENABLE_THREADS && WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH */ diff --git a/src/threads/thread-classpath.hpp b/src/threads/thread-classpath.hpp index fa6f804cd..eb7862a24 100644 --- a/src/threads/thread-classpath.hpp +++ b/src/threads/thread-classpath.hpp @@ -57,6 +57,7 @@ struct ThreadRuntimeClasspath { static threadobject *get_threadobject_from_thread(java_handle_t *h); static void thread_create_initial_threadgroups(java_handle_t **threadgroup_system, java_handle_t **threadgroup_main); static bool invoke_thread_initializer(java_lang_Thread& jlt, threadobject *t, methodinfo *thread_method_init, java_handle_t *name, java_handle_t *group); + static void clear_heap_reference(java_lang_Thread& jlt); }; typedef ThreadRuntimeClasspath ThreadRuntime; diff --git a/src/threads/thread-cldc11.cpp b/src/threads/thread-cldc11.cpp index 4af35f407..d1d9a4c3e 100644 --- a/src/threads/thread-cldc11.cpp +++ b/src/threads/thread-cldc11.cpp @@ -99,6 +99,11 @@ bool ThreadRuntimeCldc11::invoke_thread_initializer(java_lang_Thread& jlt, threa return false; } +void ThreadRuntimeOpenjdk::clear_heap_reference(java_lang_Thread& jlt) +{ + // Nothing to do. +} + #endif /* ENABLE_THREADS && WITH_JAVA_RUNTIME_LIBRARY_OPENJDK */ diff --git a/src/threads/thread-cldc11.hpp b/src/threads/thread-cldc11.hpp index 3854c9229..8d66657c4 100644 --- a/src/threads/thread-cldc11.hpp +++ b/src/threads/thread-cldc11.hpp @@ -57,6 +57,7 @@ struct ThreadRuntimeCldc11 { static threadobject *get_threadobject_from_thread(java_handle_t *h); static void thread_create_initial_threadgroups(java_handle_t **threadgroup_system, java_handle_t **threadgroup_main); static bool invoke_thread_initializer(java_lang_Thread& jlt, threadobject *t, methodinfo *thread_method_init, java_handle_t *name, java_handle_t *group); + static void clear_heap_reference(java_lang_Thread& jlt); }; typedef ThreadRuntimeCldc11 ThreadRuntime; diff --git a/src/threads/thread-openjdk.cpp b/src/threads/thread-openjdk.cpp index ff46e9d6f..e274b30b4 100644 --- a/src/threads/thread-openjdk.cpp +++ b/src/threads/thread-openjdk.cpp @@ -87,7 +87,7 @@ void ThreadRuntimeOpenjdk::print_thread_name(const java_lang_Thread& jlt, FILE * void ThreadRuntimeOpenjdk::set_javathread_state(threadobject *t, int state) { // Set the state of the java.lang.Thread object. - java_lang_Thread thread(thread_get_object(t)); + java_lang_Thread thread(LLNI_WRAP(t->object)); assert(thread.is_non_null()); thread.set_threadStatus(state); } @@ -152,6 +152,11 @@ bool ThreadRuntimeOpenjdk::invoke_thread_initializer(java_lang_Thread& jlt, thre return true; } +void ThreadRuntimeOpenjdk::clear_heap_reference(java_lang_Thread& jlt) +{ + jlt.set_me(0); +} + #endif /* ENABLE_THREADS && WITH_JAVA_RUNTIME_LIBRARY_OPENJDK */ diff --git a/src/threads/thread-openjdk.hpp b/src/threads/thread-openjdk.hpp index be008819d..c65eef5b5 100644 --- a/src/threads/thread-openjdk.hpp +++ b/src/threads/thread-openjdk.hpp @@ -57,6 +57,7 @@ struct ThreadRuntimeOpenjdk { static threadobject *get_threadobject_from_thread(java_handle_t *h); static void thread_create_initial_threadgroups(java_handle_t **threadgroup_system, java_handle_t **threadgroup_main); static bool invoke_thread_initializer(java_lang_Thread& jlt, threadobject *t, methodinfo *thread_method_init, java_handle_t *name, java_handle_t *group); + static void clear_heap_reference(java_lang_Thread& jlt); }; typedef ThreadRuntimeOpenjdk ThreadRuntime; diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp index c8c3abcd8..b111ca90f 100644 --- a/src/threads/thread.cpp +++ b/src/threads/thread.cpp @@ -49,6 +49,7 @@ #include "vm/jit/builtin.hpp" #include "vm/class.hpp" #include "vm/exceptions.hpp" +#include "vm/finalizer.hpp" #include "vm/globals.hpp" #include "vm/javaobjects.hpp" #include "vm/method.hpp" @@ -139,6 +140,10 @@ void threads_preinit(void) mainthread = thread_new(THREAD_FLAG_JAVA); + /* Add the thread to the thread list. */ + + ThreadList::add_to_active_thread_list(mainthread); + /* The main thread should always have index 1. */ if (mainthread->index != 1) @@ -208,7 +213,7 @@ static bool thread_create_object(threadobject *t, java_handle_t *name, java_hand // Set the Java object in the thread data-structure. This // indicates that the thread is attached to the VM. - thread_set_object(t, jlt.get_handle()); + t->object = LLNI_DIRECT(jlt.get_handle()); return ThreadRuntime::invoke_thread_initializer(jlt, t, thread_method_init, name, group); } @@ -280,6 +285,10 @@ static threadobject *thread_new(int32_t flags) t = ThreadList::get_free_thread(); + /* Unlock the thread lists. */ + + ThreadList::unlock(); + if (t != NULL) { /* Equivalent of MZERO on the else path */ @@ -343,14 +352,6 @@ static threadobject *thread_new(int32_t flags) threads_impl_thread_reuse(t); - /* Add the thread to the thread list. */ - - ThreadList::add_to_active_thread_list(t); - - /* Unlock the thread lists. */ - - ThreadList::unlock(); - return t; } @@ -368,13 +369,15 @@ static threadobject *thread_new(int32_t flags) void thread_free(threadobject *t) { - /* Set the reference to the Java object to NULL. */ + java_handle_t *h = LLNI_WRAP(t->object); + java_lang_Thread jlt(h); + ThreadRuntime::clear_heap_reference(jlt); - thread_set_object(t, NULL); + /* Set the reference to the Java object to NULL. */ - /* Release the thread. */ + t->object = 0; - ThreadList::release_thread(t); + ThreadList::deactivate_thread(t); } @@ -389,29 +392,32 @@ void thread_free(threadobject *t) *******************************************************************************/ +static void thread_cleanup_finalizer(java_handle_t *h, void *data) +{ + threadobject *t = reinterpret_cast(data); + ThreadList::release_thread(t, false); +} + bool threads_thread_start_internal(utf *name, functionptr f) { threadobject *t; - /* Enter the join-mutex, so if the main-thread is currently - waiting to join all threads, the number of non-daemon threads - is correct. */ - - threads_mutex_join_lock(); - /* Create internal thread data-structure. */ t = thread_new(THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON); - /* The thread is flagged as (non-)daemon thread, we can leave the - mutex. */ + /* Add the thread to the thread list. */ - threads_mutex_join_unlock(); + ThreadList::add_to_active_thread_list(t); /* Create the Java thread object. */ - if (!thread_create_object(t, javastring_new(name), threadgroup_system)) + if (!thread_create_object(t, javastring_new(name), threadgroup_system)) { + ThreadList::release_thread(t, true); return false; + } + + Finalizer::attach_custom_finalizer(LLNI_WRAP(t->object), thread_cleanup_finalizer, t); /* Start the thread. */ @@ -437,34 +443,32 @@ void threads_thread_start(java_handle_t *object) { java_lang_Thread jlt(object); - /* Enter the join-mutex, so if the main-thread is currently - waiting to join all threads, the number of non-daemon threads - is correct. */ - - threads_mutex_join_lock(); - /* Create internal thread data-structure. */ - threadobject* t = thread_new(THREAD_FLAG_JAVA); - + u4 flags = THREAD_FLAG_JAVA; #if defined(ENABLE_JAVASE) /* Is this a daemon thread? */ - if (jlt.get_daemon() == true) - t->flags |= THREAD_FLAG_DAEMON; + if (jlt.get_daemon()) + flags |= THREAD_FLAG_DAEMON; #endif - /* The thread is flagged and (non-)daemon thread, we can leave the - mutex. */ - - threads_mutex_join_unlock(); + threadobject* t = thread_new(flags); /* Link the two objects together. */ - thread_set_object(t, object); + t->object = LLNI_DIRECT(object); + + /* Add the thread to the thread list. */ + + ThreadList::add_to_active_thread_list(t); + + Atomic::write_memory_barrier(); ThreadRuntime::setup_thread_vmdata(jlt, t); + Finalizer::attach_custom_finalizer(LLNI_WRAP(t->object), thread_cleanup_finalizer, t); + /* Start the thread. Don't pass a function pointer (NULL) since we want Thread.run()V here. */ @@ -497,18 +501,13 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon) if (result == true) return true; - /* Enter the join-mutex, so if the main-thread is currently - waiting to join all threads, the number of non-daemon threads - is correct. */ - - threads_mutex_join_lock(); - /* Create internal thread data structure. */ - t = thread_new(THREAD_FLAG_JAVA); - + u4 flags = THREAD_FLAG_JAVA; if (isdaemon) - t->flags |= THREAD_FLAG_DAEMON; + flags |= THREAD_FLAG_DAEMON; + + t = thread_new(flags); /* Store the internal thread data-structure in the TSD. */ @@ -517,7 +516,9 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon) /* The thread is flagged and (non-)daemon thread, we can leave the mutex. */ - threads_mutex_join_unlock(); + /* Add the thread to the thread list. */ + + ThreadList::add_to_active_thread_list(t); DEBUGTHREADS("attaching", t); @@ -557,8 +558,10 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon) /* Create the Java thread object. */ - if (!thread_create_object(t, name, group)) + if (!thread_create_object(t, name, group)) { + ThreadList::release_thread(t, true); return false; + } /* The thread is completely initialized. */ @@ -653,10 +656,10 @@ bool thread_detach_current_external_thread(void) void thread_fprint_name(threadobject *t, FILE *stream) { - if (thread_get_object(t) == NULL) + if (LLNI_WRAP(t->object) == NULL) vm_abort(""); - java_lang_Thread jlt(thread_get_object(t)); + java_lang_Thread jlt(LLNI_WRAP(t->object)); ThreadRuntime::print_thread_name(jlt, stream); } @@ -673,7 +676,7 @@ void thread_fprint_name(threadobject *t, FILE *stream) void thread_print_info(threadobject *t) { - java_lang_Thread jlt(thread_get_object(t)); + java_lang_Thread jlt(LLNI_WRAP(t->object)); /* Print as much as we can when we are in state NEW. */ @@ -885,13 +888,9 @@ void thread_set_state_terminated(threadobject *t) { /* Set the state inside a lock. */ - ThreadList::lock(); - thread_set_state(t, THREAD_STATE_TERMINATED); DEBUGTHREADS("is TERMINATED", t); - - ThreadList::unlock(); } @@ -1003,8 +1002,6 @@ void thread_set_interrupted(threadobject *t, bool interrupted) 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. */ @@ -1022,8 +1019,6 @@ void thread_handle_set_priority(java_handle_t *th, int priority) bool thread_handle_is_interrupted(java_handle_t *th) { - ThreadListLocker l; - threadobject *t = thread_get_thread(th); return t ? thread_is_interrupted(t) : false; } @@ -1038,8 +1033,6 @@ bool thread_handle_is_interrupted(java_handle_t *th) 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. */ @@ -1057,8 +1050,6 @@ void thread_handle_interrupt(java_handle_t *th) 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; } diff --git a/src/threads/thread.hpp b/src/threads/thread.hpp index e5a372d75..30eee48f3 100644 --- a/src/threads/thread.hpp +++ b/src/threads/thread.hpp @@ -100,40 +100,6 @@ extern "C" { /* inline functions ***********************************************************/ -/* thread_get_object *********************************************************** - - Return the Java for the given thread. - - ARGUMENTS: - t ... thread - - RETURN: - the Java object - -*******************************************************************************/ - -inline static java_handle_t *thread_get_object(threadobject *t) -{ - return LLNI_WRAP(t->object); -} - - -/* threads_thread_set_object *************************************************** - - Set the Java object for the given thread. - - ARGUMENTS: - t ... thread - o ... Java object - -*******************************************************************************/ - -inline static void thread_set_object(threadobject *t, java_handle_t *o) -{ - t->object = LLNI_DIRECT(o); -} - - /* thread_get_current_object ************************************************** Return the Java object of the current thread. @@ -149,7 +115,7 @@ inline static java_handle_t *thread_get_current_object(void) java_handle_t *o; t = THREADOBJECT; - o = thread_get_object(t); + o = LLNI_WRAP(t->object); return o; } @@ -190,7 +156,7 @@ inline static bool thread_is_attached(threadobject *t) { java_handle_t *o; - o = thread_get_object(t); + o = LLNI_WRAP(t->object); return o != NULL; } @@ -282,11 +248,9 @@ void threads_mutex_gc_lock(void); void threads_mutex_gc_unlock(void); #endif -void threads_mutex_join_lock(void); -void threads_mutex_join_unlock(void); - void threads_impl_thread_clear(threadobject *t); void threads_impl_thread_reuse(threadobject *t); +void threads_impl_clear_heap_pointers(threadobject *t); void threads_impl_thread_start(threadobject *thread, functionptr f); void threads_yield(void); diff --git a/src/threads/threadlist.cpp b/src/threads/threadlist.cpp index ab3339662..a24ba4441 100644 --- a/src/threads/threadlist.cpp +++ b/src/threads/threadlist.cpp @@ -52,6 +52,8 @@ int32_t ThreadList::_number_of_active_java_threads; int32_t ThreadList::_peak_of_active_java_threads; int32_t ThreadList::_number_of_non_daemon_threads; +int32_t ThreadList::_last_index = 0; + /** * Dumps info for all threads running in the VM. This function is @@ -150,7 +152,7 @@ void ThreadList::get_active_java_threads(List &list) /** - * Return a free thread object. Caller must hold the thread list lock. + * Return a free thread object. * * @return free thread object or NULL if none available */ @@ -158,6 +160,8 @@ threadobject* ThreadList::get_free_thread() { threadobject* t = NULL; + lock(); + // Do we have free threads in the free-list? if (_free_thread_list.empty() == false) { // Yes, get the index and remove it from the free list. @@ -165,12 +169,14 @@ threadobject* ThreadList::get_free_thread() _free_thread_list.remove(t); } + unlock(); + return t; } /** - * Return a free thread index. Caller must hold the thread list lock. + * Return a free thread index. * * @return free thread index */ @@ -178,6 +184,8 @@ int32_t ThreadList::get_free_thread_index() { int32_t index; + lock(); + // Do we have free indexes in the free-list? if (_free_index_list.empty() == false) { // Yes, get the index and remove it from the free list. @@ -186,9 +194,11 @@ int32_t ThreadList::get_free_thread_index() } else { // Get a new the thread index. - index = _active_thread_list.size() + 1; + index = ++_last_index; } + unlock(); + return index; } @@ -313,18 +323,28 @@ threadobject* ThreadList::get_thread_from_java_object(java_handle_t* h) return NULL; } +void ThreadList::deactivate_thread(threadobject *t) +{ + ThreadListLocker lock; + remove_from_active_thread_list(t); + threads_impl_clear_heap_pointers(t); // allow it to be garbage collected +} /** * Release the thread. * * @return free thread index */ -void ThreadList::release_thread(threadobject* t) +void ThreadList::release_thread(threadobject* t, bool needs_deactivate) { lock(); - // Move thread from active thread list to free thread list. - remove_from_active_thread_list(t); + if (needs_deactivate) + // Move thread from active thread list to free thread list. + remove_from_active_thread_list(t); + else + assert(!t->is_in_active_list); + add_to_free_thread_list(t); // Add thread index to free index list. @@ -340,7 +360,6 @@ extern "C" { void ThreadList_lock() { ThreadList::lock(); } void ThreadList_unlock() { ThreadList::unlock(); } void ThreadList_dump_threads() { ThreadList::dump_threads(); } - void ThreadList_release_thread(threadobject* t) { ThreadList::release_thread(t); } threadobject* ThreadList_get_free_thread() { return ThreadList::get_free_thread(); } int32_t ThreadList_get_free_thread_index() { return ThreadList::get_free_thread_index(); } void ThreadList_add_to_active_thread_list(threadobject* t) { ThreadList::add_to_active_thread_list(t); } diff --git a/src/threads/threadlist.hpp b/src/threads/threadlist.hpp index fdcdd6e5f..b856c3ba7 100644 --- a/src/threads/threadlist.hpp +++ b/src/threads/threadlist.hpp @@ -1,6 +1,6 @@ /* src/threads/threadlist.hpp - different thread-lists - Copyright (C) 2008, 2009 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -57,6 +57,8 @@ private: // Thread counters for internal usage. static int32_t _number_of_non_daemon_threads; + static int32_t _last_index; + static void remove_from_active_thread_list(threadobject* t); static void add_to_free_thread_list(threadobject* t); static void add_to_free_index_list(int32_t index); @@ -74,8 +76,8 @@ private: public: static void lock() { _mutex.lock(); } static void unlock() { _mutex.unlock(); } + static void wait_cond(Condition *cond) { cond->wait(_mutex); } - // TODO make private static void add_to_active_thread_list(threadobject* t); // Thread management methods. @@ -84,7 +86,8 @@ public: static int32_t get_free_thread_index(); static threadobject* get_thread_by_index(int32_t index); static threadobject* get_thread_from_java_object(java_handle_t* h); - static void release_thread(threadobject* t); + static void release_thread(threadobject* t, bool needs_deactivate); + static void deactivate_thread(threadobject *t); // Thread listing methods. static void get_active_threads(List &list); @@ -113,7 +116,9 @@ struct ThreadListLocker { inline void ThreadList::add_to_active_thread_list(threadobject* t) { + lock(); _active_thread_list.push_back(t); + t->is_in_active_list = true; // Update counter variables. if ((t->flags & THREAD_FLAG_INTERNAL) == 0) { @@ -121,56 +126,81 @@ inline void ThreadList::add_to_active_thread_list(threadobject* t) _number_of_active_java_threads++; _peak_of_active_java_threads = MAX(_peak_of_active_java_threads, _number_of_active_java_threads); } + unlock(); } inline void ThreadList::remove_from_active_thread_list(threadobject* t) { + lock(); _active_thread_list.remove(t); + t->is_in_active_list = false; // Update counter variables. if ((t->flags & THREAD_FLAG_INTERNAL) == 0) { _number_of_active_java_threads--; } + unlock(); } inline void ThreadList::add_to_free_thread_list(threadobject* t) { + lock(); _free_thread_list.push_back(t); + unlock(); } inline void ThreadList::add_to_free_index_list(int32_t index) { + lock(); _free_index_list.push_back(index); + unlock(); } inline threadobject* ThreadList::get_main_thread() { - return _active_thread_list.front(); + lock(); + threadobject *r = _active_thread_list.front(); + unlock(); + return r; } inline int32_t ThreadList::get_number_of_active_threads() { - return _active_thread_list.size(); + lock(); + int32_t size = _active_thread_list.size(); + unlock(); + return size; } inline int32_t ThreadList::get_number_of_started_java_threads() { - return _number_of_started_java_threads; + lock(); + int32_t num = _number_of_started_java_threads; + unlock(); + return num; } inline int32_t ThreadList::get_number_of_active_java_threads() { - return _number_of_active_java_threads; + lock(); + int32_t num = _number_of_active_java_threads; + unlock(); + return num; } inline int32_t ThreadList::get_peak_of_active_java_threads() { - return _peak_of_active_java_threads; + lock(); + int32_t num = _peak_of_active_java_threads; + unlock(); + return num; } inline void ThreadList::reset_peak_of_active_java_threads() { + lock(); _peak_of_active_java_threads = _number_of_active_java_threads; + unlock(); } #else @@ -180,7 +210,6 @@ typedef struct ThreadList ThreadList; void ThreadList_lock(); void ThreadList_unlock(); void ThreadList_dump_threads(); -void ThreadList_release_thread(threadobject* t); threadobject* ThreadList_get_free_thread(); int32_t ThreadList_get_free_thread_index(); void ThreadList_add_to_active_thread_list(threadobject* t); diff --git a/src/vm/exceptions.cpp b/src/vm/exceptions.cpp index 69a748feb..707efa4c3 100644 --- a/src/vm/exceptions.cpp +++ b/src/vm/exceptions.cpp @@ -1,6 +1,6 @@ /* src/vm/exceptions.cpp - exception related functions - Copyright (C) 1996-2005, 2006, 2007, 2008 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -2021,7 +2021,7 @@ void exceptions_print_stacktrace(void) need it afterwards. */ t = thread_get_current(); - to = (java_lang_Thread *) thread_get_object(t); + to = (java_lang_Thread *) LLNI_WRAP(t->object); if (to != NULL) { fprintf(stderr, "in thread \""); diff --git a/src/vm/javaobjects.cpp b/src/vm/javaobjects.cpp index 0aa5af11f..cb862ee2c 100644 --- a/src/vm/javaobjects.cpp +++ b/src/vm/javaobjects.cpp @@ -1,6 +1,6 @@ /* src/vm/javaobjects.cpp - functions to create and access Java objects - Copyright (C) 2010, 2011 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2008, 2009 Theobroma Systems Ltd. @@ -253,6 +253,7 @@ off_t java_lang_Thread::offset_daemon; off_t java_lang_Thread::offset_group; off_t java_lang_Thread::offset_uncaughtExceptionHandler; off_t java_lang_Thread::offset_threadStatus; +off_t java_lang_Thread::offset_me; static DynOffsetEntry dyn_entries_java_lang_Thread[] = { { &java_lang_Thread::set_priority_offset, "priority" }, @@ -260,6 +261,7 @@ static DynOffsetEntry dyn_entries_java_lang_Thread[] = { { &java_lang_Thread::set_group_offset, "group" }, { &java_lang_Thread::set_uncaughtExceptionHandler_offset, "uncaughtExceptionHandler" }, { &java_lang_Thread::set_threadStatus_offset, "threadStatus" }, + { &java_lang_Thread::set_me_offset, "me" }, { 0, 0 } }; diff --git a/src/vm/javaobjects.hpp b/src/vm/javaobjects.hpp index 0aaa29504..f60026b97 100644 --- a/src/vm/javaobjects.hpp +++ b/src/vm/javaobjects.hpp @@ -1,6 +1,6 @@ /* src/vm/javaobjects.hpp - functions to create and access Java objects - Copyright (C) 2010, 2011 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2008, 2009 Theobroma Systems Ltd. @@ -1969,6 +1969,7 @@ private: static off_t offset_group; static off_t offset_uncaughtExceptionHandler; static off_t offset_threadStatus; + static off_t offset_me; public: java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {} @@ -1983,6 +1984,7 @@ public: void set_priority (int32_t value); void set_group (java_handle_t* value); void set_threadStatus(int32_t value); + void set_me (java_handle_t* value); // Offset initializers static void set_priority_offset(int32_t off) { offset_priority = off; } @@ -1990,6 +1992,7 @@ public: static void set_group_offset(int32_t off) { offset_group = off; } static void set_uncaughtExceptionHandler_offset(int32_t off) { offset_uncaughtExceptionHandler = off; } static void set_threadStatus_offset(int32_t off) { offset_threadStatus = off; } + static void set_me_offset(int32_t off) { offset_me = off; } }; @@ -2029,6 +2032,11 @@ inline void java_lang_Thread::set_threadStatus(int32_t value) set(_handle, offset_threadStatus, value); } +inline void java_lang_Thread::set_me(java_handle_t* value) +{ + set(_handle, offset_me, value); +} + /** @@ -2765,12 +2773,6 @@ public: }; -// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h) -// { -// java_lang_Thread(thread_get_object(t)); -// } - - inline int32_t java_lang_Thread::get_priority() const { return get(_handle, offset_priority); diff --git a/src/vm/jit/stacktrace.cpp b/src/vm/jit/stacktrace.cpp index ad3b43825..1593bd2fa 100644 --- a/src/vm/jit/stacktrace.cpp +++ b/src/vm/jit/stacktrace.cpp @@ -1,6 +1,6 @@ /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system - Copyright (C) 1996-2005, 2006, 2007, 2008 + Copyright (C) 1996-2011 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2009 Theobroma Systems Ltd. @@ -1402,7 +1402,8 @@ stacktrace_t* stacktrace_get_of_thread(threadobject* t) /* stacktrace_print_of_thread ************************************************** - Print the current stacktrace of the given thread. + Print the current stacktrace of the given thread. It will only work + for suspended threads. ARGUMENTS: t ... thread @@ -1422,7 +1423,7 @@ void stacktrace_print_of_thread(threadobject *t) sfi = t->_stackframeinfo; - if (sfi == NULL) { + if (!t->suspended || sfi == NULL) { puts("\t<>"); fflush(stdout); return;