X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fthreads%2Fthreadlist.cpp;h=a24ba44412c1053f844922ab59eeee38f0ca9e03;hb=3936052d73a3af4ed04156a470407915834a4fd6;hp=b791fcdde75988d7604e58892a0b016148f07915;hpb=c0517d179c79be1f1e5d38c0c4573a2899b7b78d;p=cacao.git diff --git a/src/threads/threadlist.cpp b/src/threads/threadlist.cpp index b791fcdde..a24ba4441 100644 --- a/src/threads/threadlist.cpp +++ b/src/threads/threadlist.cpp @@ -1,6 +1,6 @@ /* src/threads/threadlist.cpp - thread list - Copyright (C) 2008 + Copyright (C) 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -27,12 +27,14 @@ #include +#include + #include "threads/mutex.hpp" #include "threads/threadlist.hpp" #include "threads/thread.hpp" #include "toolbox/list.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" #include "vm/jit/stacktrace.hpp" @@ -41,12 +43,17 @@ Mutex ThreadList::_mutex; // a mutex for all thread lists -list ThreadList::_active_thread_list; // list of active threads -list ThreadList::_free_thread_list; // list of free threads -list ThreadList::_free_index_list; // list of free thread indexes +List ThreadList::_active_thread_list; // list of active threads +List ThreadList::_free_thread_list; // list of free threads +List ThreadList::_free_index_list; // list of free thread indexes +int32_t ThreadList::_number_of_started_java_threads; +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 @@ -54,13 +61,15 @@ int32_t ThreadList::_number_of_non_daemon_threads; */ void ThreadList::dump_threads() { - // XXX we should stop the world here + // XXX we should stop the world here and remove explicit + // thread suspension from the loop below. // Lock the thread lists. lock(); - printf("Full thread dump CACAO "VERSION":\n"); + printf("Full thread dump CACAO "VERSION_FULL":\n"); // Iterate over all started threads. + threadobject* self = THREADOBJECT; for (List::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) { threadobject* t = *it; @@ -68,13 +77,10 @@ void ThreadList::dump_threads() if (t->state == THREAD_STATE_NEW) continue; -#if defined(ENABLE_GC_CACAO) - /* Suspend the thread. */ - /* XXX Is the suspend reason correct? */ + /* Suspend the thread (and ignore return value). */ - if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false) - vm_abort("threads_dump: threads_suspend_thread failed"); -#endif + if (t != self) + (void) threads_suspend_thread(t, SUSPEND_REASON_DUMP); /* Print thread info. */ @@ -86,12 +92,58 @@ void ThreadList::dump_threads() stacktrace_print_of_thread(t); -#if defined(ENABLE_GC_CACAO) - /* Resume the thread. */ + /* Resume the thread (and ignore return value). */ + + if (t != self) + (void) threads_resume_thread(t, SUSPEND_REASON_DUMP); + } + + // Unlock the thread lists. + unlock(); +} + + +/** + * Fills the passed list with all currently active threads. Creating a copy + * of the thread list here, is the only way to ensure we do not end up in a + * dead-lock when iterating over the list. + * + * @param list list class to be filled + */ +void ThreadList::get_active_threads(List &list) +{ + // Lock the thread lists. + lock(); + + // Use the assignment operator to create a copy of the thread list. + list = _active_thread_list; + + // Unlock the thread lists. + unlock(); +} + + +/** + * Fills the passed list with all currently active threads which should be + * visible to Java. Creating a copy of the thread list here, is the only way + * to ensure we do not end up in a dead-lock when iterating over the list. + * + * @param list list class to be filled + */ +void ThreadList::get_active_java_threads(List &list) +{ + // Lock the thread lists. + lock(); + + // Iterate over all active threads. + for (List::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) { + threadobject* t = *it; - if (threads_resume_thread(t) == false) - vm_abort("threads_dump: threads_resume_thread failed"); -#endif + // We skip internal threads. + if (t->flags & THREAD_FLAG_INTERNAL) + continue; + + list.push_back(t); } // Unlock the thread lists. @@ -108,13 +160,17 @@ 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. - threadobject* t = _free_thread_list.front(); + t = _free_thread_list.front(); _free_thread_list.remove(t); } + unlock(); + return t; } @@ -128,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. @@ -136,13 +194,49 @@ 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; } +/** + * Return the number of daemon threads visible to Java. + * + * NOTE: This function does a linear-search over the threads list, + * because it is only used by the management interface. + * + * @return number of daemon threads + */ +int32_t ThreadList::get_number_of_daemon_java_threads(void) +{ + int number = 0; + + // Lock the thread lists. + lock(); + + // Iterate over all active threads. + for (List::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) { + threadobject* t = *it; + + // We skip internal threads. + if (t->flags & THREAD_FLAG_INTERNAL) + continue; + + if (thread_is_daemon(t)) + number++; + } + + // Unlock the thread lists. + unlock(); + + return number; +} + + /** * Return the number of non-daemon threads. * @@ -177,22 +271,25 @@ int32_t ThreadList::get_number_of_non_daemon_threads(void) */ threadobject* ThreadList::get_thread_by_index(int32_t index) { - threadobject* t = NULL; - lock(); - for (List::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) { - t = *it; + List::iterator it = find_if(_active_thread_list.begin(), _active_thread_list.end(), std::bind2nd(comparator(), index)); - if (t->state == THREAD_STATE_NEW) - continue; + // No thread found. + if (it == _active_thread_list.end()) { + unlock(); + return NULL; + } + + threadobject* t = *it; - if (t->index == index) - break; + // The thread found is in state new. + if (t->state == THREAD_STATE_NEW) { + unlock(); + return NULL; } unlock(); - return t; } @@ -226,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. @@ -253,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); }