From: Stefan Ring Date: Mon, 18 Apr 2011 19:15:16 +0000 (+0200) Subject: * src/threads/thread.cpp: Use a finalizer to remove dead threads. X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=faf9ced36a84879b43e9b41783ba891cce356dd0 * src/threads/thread.cpp: Use a finalizer to remove dead threads. * 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. --- diff --git a/src/threads/posix/thread-posix.cpp b/src/threads/posix/thread-posix.cpp index 45c71405f..058a3bda9 100644 --- a/src/threads/posix/thread-posix.cpp +++ b/src/threads/posix/thread-posix.cpp @@ -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 ******************************************************** diff --git a/src/threads/posix/thread-posix.hpp b/src/threads/posix/thread-posix.hpp index e24f6cc2e..b8e63635f 100644 --- a/src/threads/posix/thread-posix.hpp +++ b/src/threads/posix/thread-posix.hpp @@ -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 */ diff --git a/src/threads/thread-classpath.cpp b/src/threads/thread-classpath.cpp index 48f0fe999..eae414a30 100644 --- a/src/threads/thread-classpath.cpp +++ b/src/threads/thread-classpath.cpp @@ -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) diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp index 15bd67c58..4520da859 100644 --- a/src/threads/thread.cpp +++ b/src/threads/thread.cpp @@ -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(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; } diff --git a/src/threads/thread.hpp b/src/threads/thread.hpp index e5a372d75..7124b4cf8 100644 --- a/src/threads/thread.hpp +++ b/src/threads/thread.hpp @@ -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); diff --git a/src/threads/threadlist.cpp b/src/threads/threadlist.cpp index ab3339662..0350a1620 100644 --- a/src/threads/threadlist.cpp +++ b/src/threads/threadlist.cpp @@ -150,7 +150,7 @@ void ThreadList::get_active_java_threads(List &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); } diff --git a/src/threads/threadlist.hpp b/src/threads/threadlist.hpp index 0d6043aa7..76cd7c553 100644 --- a/src/threads/threadlist.hpp +++ b/src/threads/threadlist.hpp @@ -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 &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);