/* 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.
#include <stdint.h>
+#include <algorithm>
+
#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"
/* class variables */
Mutex ThreadList::_mutex; // a mutex for all thread lists
-list<threadobject*> ThreadList::_active_thread_list; // list of active threads
-list<threadobject*> ThreadList::_free_thread_list; // list of free threads
-list<int32_t> ThreadList::_free_index_list; // list of free thread indexes
+List<threadobject*> ThreadList::_active_thread_list; // list of active threads
+List<threadobject*> ThreadList::_free_thread_list; // list of free threads
+List<int32_t> 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;
*/
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<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
threadobject* t = *it;
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. */
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<threadobject*> &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<threadobject*> &list)
+{
+ // Lock the thread lists.
+ lock();
+
+ // Iterate over all active threads.
+ for (List<threadobject*>::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 (threads_resume_thread(t) == false)
- vm_abort("threads_dump: threads_resume_thread failed");
-#endif
+ list.push_back(t);
}
// Unlock the thread lists.
}
+/**
+ * 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<threadobject*>::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.
*
*/
threadobject* ThreadList::get_thread_by_index(int32_t index)
{
- threadobject* t = NULL;
-
lock();
- for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
- t = *it;
+ List<threadobject*>::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;
+ }
- if (t->index == index)
- break;
+ threadobject* t = *it;
+
+ // The thread found is in state new.
+ if (t->state == THREAD_STATE_NEW) {
+ unlock();
+ return NULL;
}
unlock();
-
return t;
}