* src/threads/threadlist.hpp (ThreadList): Adapted thread counting methods to
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Thu, 24 Sep 2009 09:06:20 +0000 (11:06 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Thu, 24 Sep 2009 09:06:20 +0000 (11:06 +0200)
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.

src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp
src/native/vm/openjdk/jvm.cpp
src/threads/posix/thread-posix.cpp
src/threads/thread.cpp
src/threads/threadlist.cpp
src/threads/threadlist.hpp
src/vm/global.h
src/vm/vm.cpp
src/vm/vm.hpp

index 359931c254fe82d3b79a60699afaa6a63c062460..dd11f7c4628ea0cea176b985e49956ac09ba8094 100644 (file)
@@ -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"
index 5186c6add1311a9e017e60cdaecdc31c06a49fd2..045fc054d9a89ee03ccee75b1be2b291475ab782 100644 (file)
@@ -3187,7 +3187,7 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy)
 {
        // Get a list of all active threads.
        List<threadobject*> 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();
index b91e50f1d6725fb3149f1a49ff4fb6d9922417da..0efabc005dc959f30e088507ebd4e1c0439d7beb 100644 (file)
@@ -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;
 }
 
index 5eaf0c2b15554029b7751feca22ddda1d9b7e35d..bae8161187875bfa5451d69c81704d1892f67db9 100644 (file)
@@ -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;
index 546aa06822984303e1e701368dacb5674bfa61e7..e6dd58371dc9c869a9358bad2b55ead53e7e4f99 100644 (file)
@@ -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<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;
 
 
@@ -121,6 +124,34 @@ void ThreadList::get_active_threads(List<threadobject*> &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<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;
+
+               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<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.
  *
index 40e33171dfb3777ef206b397deddfd3bec64ce8a..fdcdd6e5ffbb3019463e74e25d1f4981beda2bcc 100644 (file)
@@ -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<threadobject*> _free_thread_list;   // list of free threads
        static List<int32_t>       _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<threadobject*> &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<threadobject*> &list);
+       static void                 get_active_java_threads(List<threadobject*> &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;
index 4443a806f0782a9c3974ddbd55371c86e8e51e87..45287193b1bcab37471c04ca56d04be3132fc8e4 100644 (file)
@@ -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 ***********************************************************/
 
index fb56384e03ab5daeeeeb9ef912bf7a2aa75a0d7e..87f71f38e7473a36cd52b1c1b3b27bd1812ffcc2 100644 (file)
@@ -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());
index 8ddb1464a0d11b32139de7e3863e8513f1fcc77b..901f5820175cbda98d8c47810b53bfb45328f077 100644 (file)
@@ -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