From 6661612c5b436511fdc0caf372587fa6a6225782 Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Thu, 24 Sep 2009 11:06:20 +0200 Subject: [PATCH] * src/threads/threadlist.hpp (ThreadList): Adapted thread counting methods to hide internal threads from Java. Also added some comments. * src/threads/threadlist.cpp (ThreadList::get_active_java_threads): Implemented. (ThreadList::get_number_of_daemon_java_threads): Likewise. * src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp: Adapted to above changes. * src/native/vm/openjdk/jvm.cpp (JVM_GetAllThreads): Likewise. * src/threads/posix/thread-posix.cpp: Removed obsolete counting code. * src/threads/thread.cpp (thread_new): Counting via threadlist requires that flags are set during threadobject creation. * src/vm/global.h (MAX): Defined as macro. * src/vm/vm.cpp (VM::VM): Remember VM initialization time. * src/vm/vm.hpp (VM::get_inittime): Returns above time. --- ...ava_lang_management_VMThreadMXBeanImpl.cpp | 17 ++--- src/native/vm/openjdk/jvm.cpp | 2 +- src/threads/posix/thread-posix.cpp | 27 -------- src/threads/thread.cpp | 27 +++----- src/threads/threadlist.cpp | 67 +++++++++++++++++- src/threads/threadlist.hpp | 69 +++++++++++++++++-- src/vm/global.h | 4 ++ src/vm/vm.cpp | 16 ++--- src/vm/vm.hpp | 2 + 9 files changed, 155 insertions(+), 76 deletions(-) diff --git a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp index 359931c25..dd11f7c46 100644 --- a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp +++ b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp @@ -36,6 +36,8 @@ # include "native/vm/include/gnu_java_lang_management_VMThreadMXBeanImpl.h" #endif +#include "threads/threadlist.hpp" + #include "toolbox/logging.hpp" #include "vm/classcache.hpp" @@ -92,10 +94,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurr */ JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getPeakThreadCount(JNIEnv *env, jclass clazz) { -/* return _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount; */ -#warning Move to C++ - log_println("Java_gnu_java_lang_management_ThreadMXBean_getPeakThreadCount: MOVE TO C++!"); - return 0; + return ThreadList::get_peak_of_active_java_threads(); } @@ -145,10 +144,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThre */ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTotalStartedThreadCount(JNIEnv *env, jclass clazz) { -/* return _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount; */ -#warning Move to C++ - log_println("Java_gnu_java_lang_management_ThreadMXBean_getTotalStartedThreadCount: MOVE TO C++!"); - return 0; + return ThreadList::get_number_of_started_java_threads(); } @@ -159,10 +155,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTota */ JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount(JNIEnv *env, jclass clazz) { -/* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */ -#warning Move to C++ - log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount: MOVE TO C++!"); + return ThreadList::reset_peak_of_active_java_threads(); } } // extern "C" diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index 5186c6add..045fc054d 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -3187,7 +3187,7 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) { // Get a list of all active threads. List active_threads; - ThreadList::get_active_threads(active_threads); + ThreadList::get_active_java_threads(active_threads); // Allocate array to hold the java.lang.Thread objects. int32_t length = active_threads.size(); diff --git a/src/threads/posix/thread-posix.cpp b/src/threads/posix/thread-posix.cpp index b91e50f1d..0efabc005 100644 --- a/src/threads/posix/thread-posix.cpp +++ b/src/threads/posix/thread-posix.cpp @@ -824,17 +824,6 @@ static void *threads_startup_thread(void *arg) if (m == NULL) vm_abort("threads_startup_thread: run() method not found in class"); - /* set ThreadMXBean variables */ - -/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */ - -/* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */ -#warning Move to C++ - #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) // We need to start the run method of java.lang.VMThread. @@ -854,17 +843,6 @@ static void *threads_startup_thread(void *arg) (void) vm_call_method(m, h); } else { - /* set ThreadMXBean variables */ - -/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */ - -/* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */ -/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */ -#warning Move to C++ - /* call passed function, e.g. finalizer_thread */ (function)(); @@ -883,11 +861,6 @@ static void *threads_startup_thread(void *arg) (void) thread_detach_current_thread(); - /* set ThreadMXBean variables */ - -/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */ -#warning Move to C++ - return NULL; } diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp index 5eaf0c2b1..bae816118 100644 --- a/src/threads/thread.cpp +++ b/src/threads/thread.cpp @@ -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? */ @@ -710,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; diff --git a/src/threads/threadlist.cpp b/src/threads/threadlist.cpp index 546aa0682..e6dd58371 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. @@ -47,6 +47,9 @@ 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; @@ -121,6 +124,34 @@ void ThreadList::get_active_threads(List &list) } +/** + * 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; + + // We skip internal threads. + if (t->flags & THREAD_FLAG_INTERNAL) + continue; + + list.push_back(t); + } + + // Unlock the thread lists. + unlock(); +} + + /** * Return a free thread object. * @@ -165,6 +196,40 @@ int32_t ThreadList::get_free_thread_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. * diff --git a/src/threads/threadlist.hpp b/src/threads/threadlist.hpp index 40e33171d..fdcdd6e5f 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 + Copyright (C) 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -34,6 +34,8 @@ #include "toolbox/list.hpp" +#include "vm/global.h" + /* ThreadList *****************************************************************/ @@ -47,6 +49,12 @@ private: static List _free_thread_list; // list of free threads static List _free_index_list; // list of free thread indexes + // Thread counters visible to Java. + static int32_t _number_of_started_java_threads; + static int32_t _number_of_active_java_threads; + static int32_t _peak_of_active_java_threads; + + // Thread counters for internal usage. static int32_t _number_of_non_daemon_threads; static void remove_from_active_thread_list(threadobject* t); @@ -70,15 +78,31 @@ public: // TODO make private static void add_to_active_thread_list(threadobject* t); - static void dump_threads(); - static void get_active_threads(List &list); + // Thread management methods. static threadobject* get_main_thread(); static threadobject* get_free_thread(); static int32_t get_free_thread_index(); - static int32_t get_number_of_non_daemon_threads(); 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); + + // Thread listing methods. + static void get_active_threads(List &list); + static void get_active_java_threads(List &list); + + // Thread counting methods visible to Java. + static int32_t get_number_of_started_java_threads(); + static int32_t get_number_of_active_java_threads(); + static int32_t get_number_of_daemon_java_threads(); + static int32_t get_peak_of_active_java_threads(); + static void reset_peak_of_active_java_threads(); + + // Thread counting methods for internal use. + static int32_t get_number_of_active_threads(); + static int32_t get_number_of_non_daemon_threads(); + + // Debugging methods. + static void dump_threads(); }; struct ThreadListLocker { @@ -90,11 +114,23 @@ struct ThreadListLocker { inline void ThreadList::add_to_active_thread_list(threadobject* t) { _active_thread_list.push_back(t); + + // Update counter variables. + if ((t->flags & THREAD_FLAG_INTERNAL) == 0) { + _number_of_started_java_threads++; + _number_of_active_java_threads++; + _peak_of_active_java_threads = MAX(_peak_of_active_java_threads, _number_of_active_java_threads); + } } inline void ThreadList::remove_from_active_thread_list(threadobject* t) { _active_thread_list.remove(t); + + // Update counter variables. + if ((t->flags & THREAD_FLAG_INTERNAL) == 0) { + _number_of_active_java_threads--; + } } inline void ThreadList::add_to_free_thread_list(threadobject* t) @@ -112,6 +148,31 @@ inline threadobject* ThreadList::get_main_thread() return _active_thread_list.front(); } +inline int32_t ThreadList::get_number_of_active_threads() +{ + return _active_thread_list.size(); +} + +inline int32_t ThreadList::get_number_of_started_java_threads() +{ + return _number_of_started_java_threads; +} + +inline int32_t ThreadList::get_number_of_active_java_threads() +{ + return _number_of_active_java_threads; +} + +inline int32_t ThreadList::get_peak_of_active_java_threads() +{ + return _peak_of_active_java_threads; +} + +inline void ThreadList::reset_peak_of_active_java_threads() +{ + _peak_of_active_java_threads = _number_of_active_java_threads; +} + #else typedef struct ThreadList ThreadList; diff --git a/src/vm/global.h b/src/vm/global.h index 4443a806f..45287193b 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -97,6 +97,10 @@ typedef union { # define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif +#ifndef MAX +# define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + /* forward typedefs ***********************************************************/ diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index fb56384e0..87f71f38e 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -1444,7 +1444,10 @@ VM::VM(JavaVMInitArgs* vm_args) // Initialization is done, VM is created. _created = true; _initializing = false; - + + // Set the VM inittime. + _inittime = builtin_currenttimemillis(); + // Print the run-time VM configuration after all stuff is set and // the VM is initialized. if (opt_PrintConfig) @@ -1725,17 +1728,6 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) typeinfo_test(); #endif - /* set ThreadMXBean variables */ - -// _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; -// _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; - -// if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > -// _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) -// _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = -// _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; -#warning Move to C++ - /* start the main thread */ (void) vm_call_method(m, NULL, oa.get_handle()); diff --git a/src/vm/vm.hpp b/src/vm/vm.hpp index 8ddb1464a..901f58201 100644 --- a/src/vm/vm.hpp +++ b/src/vm/vm.hpp @@ -65,6 +65,7 @@ private: bool _created; bool _exiting; int64_t _starttime; + int64_t _inittime; // Subsystems. Properties _properties; ///< Commandline properties. @@ -101,6 +102,7 @@ public: bool is_created() { return _created; } bool is_exiting() { return _exiting; } int64_t get_starttime() { return _starttime; } + int64_t get_inittime() { return _inittime; } Properties& get_properties () { return _properties; } Recompiler& get_recompiler () { return _recompiler; } // REMOVEME -- 2.25.1