* src/threads/thread.cpp: Use a finalizer to remove dead threads.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 18 Apr 2011 19:15:16 +0000 (21:15 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 18 Apr 2011 19:15:16 +0000 (21:15 +0200)
* src/threads/posix/thread-posix.cpp (threads_impl_clear_heap_pointers): Added.
* src/threads/thread.hpp: Likewise.
* src/threads/posix/thread-posix.hpp: Added flag is_in_active_list.
* src/threads/threadlist.cpp, src/threads/threadlist.hpp: Take thread list lock
for all thread list operations.
(deactivate_thread): Added.
* src/threads/thread-classpath.cpp: Adapted to lock change.

src/threads/posix/thread-posix.cpp
src/threads/posix/thread-posix.hpp
src/threads/thread-classpath.cpp
src/threads/thread.cpp
src/threads/thread.hpp
src/threads/threadlist.cpp
src/threads/threadlist.hpp

index 45c71405f933c7f2bf054b36a8c6d03d54d42ef7..058a3bda94522821d1b4bd600e21c667137f17cb 100644 (file)
@@ -459,6 +459,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 +533,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 ********************************************************
 
index e24f6cc2ee8fee6c75b1f7c1e6f61fb8a981211e..b8e63635f769497cf3e9764a0ef0874069dc4797 100644 (file)
@@ -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                         */
 
index 48f0fe9996855c78ea190025a65e417352be98b4..eae414a30acf1bdab6d57cb056709c05da5f2068 100644 (file)
@@ -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)
index 15bd67c5898826a6025cd91ea238c058cec4be1e..4520da8594b0e929af6d01d310efe66456bdc0f3 100644 (file)
@@ -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"
@@ -372,9 +373,7 @@ void thread_free(threadobject *t)
 
        thread_set_object(t, NULL);
 
-       /* Release the thread. */
-
-       ThreadList::release_thread(t);
+       ThreadList::deactivate_thread(t);
 }
 
 
@@ -389,6 +388,12 @@ void thread_free(threadobject *t)
 
 *******************************************************************************/
 
+static void thread_cleanup_finalizer(java_handle_t *h, void *data)
+{
+       threadobject *t = reinterpret_cast<threadobject*>(data);
+       ThreadList::release_thread(t, false);
+}
+
 bool threads_thread_start_internal(utf *name, functionptr f)
 {
        threadobject *t;
@@ -414,8 +419,12 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
        /* 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(thread_get_object(t), thread_cleanup_finalizer, t);
 
        /* Start the thread. */
 
@@ -470,6 +479,8 @@ void threads_thread_start(java_handle_t *object)
 
        ThreadRuntime::setup_thread_vmdata(jlt, t);
 
+       Finalizer::attach_custom_finalizer(thread_get_object(t), thread_cleanup_finalizer, t);
+
        /* Start the thread.  Don't pass a function pointer (NULL) since
           we want Thread.run()V here. */
 
@@ -566,8 +577,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. */
 
@@ -894,13 +907,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();
 }
 
 
@@ -1012,8 +1021,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. */
@@ -1031,8 +1038,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;
 }
@@ -1047,8 +1052,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. */
@@ -1066,8 +1069,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;
 }
index e5a372d754673a425d026932dd07de2d2269a8ec..7124b4cf83e4f41b825805715b672189af830f6d 100644 (file)
@@ -287,6 +287,7 @@ 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);
index ab3339662bc035fbe1103a0d026f40d3ced6fa81..0350a1620b150f24aabcda1ca07462c671cc7bb3 100644 (file)
@@ -150,7 +150,7 @@ void ThreadList::get_active_java_threads(List<threadobject*> &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 +158,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 +167,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 +182,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.
@@ -189,6 +195,8 @@ int32_t ThreadList::get_free_thread_index()
                index = _active_thread_list.size() + 1;
        }
 
+       unlock();
+
        return index;
 }
 
@@ -313,18 +321,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 +358,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); }
index 0d6043aa72f0bf3499f80f2e25e11e12ff640b9b..76cd7c5538f5dcc58ad80db775337bdf53e078fb 100644 (file)
@@ -83,7 +83,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<threadobject*> &list);
@@ -114,6 +115,7 @@ 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) {
@@ -126,52 +128,76 @@ inline void ThreadList::add_to_active_thread_list(threadobject* t)
 
 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
@@ -181,7 +207,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);