From e220e26c156e3af39585c68c1d2a3d9dbd7fe3e1 Mon Sep 17 00:00:00 2001 From: twisti Date: Thu, 24 May 2007 10:21:16 +0000 Subject: [PATCH] * src/threads/threads-common.c (mm/memory.h): Added. (toolbox/list.h): Likewise. (threads_table): Removed. (list_threads, list_threads_free): Added. (threads_preinit): Initialize lists. (threads_table_init): Removed. (threads_table_add): Likewise. (threads_table_remove): Likewise. (threads_table_get): Likewise. (threads_table_get_threads): Likewise. (threads_table_get_non_daemons): Likewise. (threads_table_first): Likewise. (threads_table_next): Likewise. (threads_table_dump): Likewise. (threads_list_first): New function. (threads_list_next): Likewise. (threads_list_get_non_daemons): Likewise. (threads_thread_new): Likewise. (threads_thread_free): Likewise. (threads_thread_print_info): Added state-assert, print thread index. (threads_thread_state_runnable): New function. (threads_thread_state_waiting): Likewise. (threads_thread_state_timed_waiting): Likewise. (threads_thread_state_terminated): Likewise. (threads_dump): Use threads-list functions. * src/threads/threads-common.h: Likewise. (threads_table_entry_t): Removed. (threads_table_t): Likewise. * src/threads/native/threads.c (mutex_threads_table): Renamed to mutex_threads_list. (threads_cast_sendsignals): Use threads-list functions. (threads_table_lock): Renamed to threads_list_lock. (threads_table_unlock): Renamed to threads_list_unlock. (threads_startup_thread): Use threads-state functions. (threads_detach_thread): Likewise. (threads_wait_with_timeout): Likewise. (threads_join_all_threads): Use threads-list functions. * src/threads/native/threads.h (threadobject): Added linkage. --- src/threads/native/threads.c | 131 ++++---- src/threads/native/threads.h | 3 +- src/threads/threads-common.c | 581 ++++++++++++----------------------- src/threads/threads-common.h | 62 +--- 4 files changed, 277 insertions(+), 500 deletions(-) diff --git a/src/threads/native/threads.c b/src/threads/native/threads.c index 1e0704532..39e15de9c 100644 --- a/src/threads/native/threads.c +++ b/src/threads/native/threads.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: threads.c 7904 2007-05-14 13:29:32Z twisti $ + $Id: threads.c 7963 2007-05-24 10:21:16Z twisti $ */ @@ -227,7 +227,7 @@ pthread_key_t threads_current_threadobject_key; #endif /* global mutex for the threads table */ -static pthread_mutex_t mutex_threads_table; +static pthread_mutex_t mutex_threads_list; /* global mutex for stop-the-world */ static pthread_mutex_t stopworldlock; @@ -366,21 +366,40 @@ void unlock_stopworld(void) #if !defined(__DARWIN__) /* Caller must hold threadlistlock */ -static void threads_cast_sendsignals(int sig) +static s4 threads_cast_sendsignals(s4 sig) { threadobject *t; threadobject *self; + s4 count; self = THREADOBJECT; /* iterate over all started threads */ - for (t = threads_table_first(); t != NULL; t = threads_table_next(t)) { + count = 0; + + for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) { /* don't send the signal to ourself */ - if (t != self) - pthread_kill(t->tid, sig); + if (t == self) + continue; + + /* don't send the signal to NEW threads (because they are not + completely initialized) */ + + if (t->state == THREAD_STATE_NEW) + continue; + + /* send the signal */ + + pthread_kill(t->tid, sig); + + /* increase threads count */ + + count++; } + + return count; } #else @@ -464,14 +483,14 @@ static void threads_cast_irixresume(void) void threads_cast_stopworld(void) { #if !defined(__DARWIN__) && !defined(__CYGWIN__) - int count, i; + s4 count, i; #endif lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING); - /* lock the threads table */ + /* lock the threads lists */ - threads_table_lock(); + threads_list_lock(); #if defined(__DARWIN__) threads_cast_darwinstop(); @@ -481,27 +500,22 @@ void threads_cast_stopworld(void) #else /* send all threads the suspend signal */ - threads_cast_sendsignals(GC_signum1()); - - /* wait for all threads to suspend (except the current one) */ + count = threads_cast_sendsignals(GC_signum1()); - count = threads_table_get_threads() - 1; + /* wait for all threads signaled to suspend */ for (i = 0; i < count; i++) threads_sem_wait(&suspend_ack); #endif - /* unlock the threads table */ - - threads_table_unlock(); + /* ATTENTION: Don't unlock the threads-lists here so that + non-signaled NEW threads can't change their state and execute + code. */ } + void threads_cast_startworld(void) { - /* lock the threads table */ - - threads_table_lock(); - #if defined(__DARWIN__) threads_cast_darwinresume(); #elif defined(__MIPS__) @@ -510,12 +524,12 @@ void threads_cast_startworld(void) /* TODO */ assert(0); #else - threads_cast_sendsignals(GC_signum2()); + (void) threads_cast_sendsignals(GC_signum2()); #endif - /* unlock the threads table */ + /* unlock the threads lists */ - threads_table_unlock(); + threads_list_unlock(); unlock_stopworld(); } @@ -682,38 +696,38 @@ void threads_impl_preinit(void) void threads_impl_table_init(void) { - pthread_mutex_init(&mutex_threads_table, NULL); + pthread_mutex_init(&mutex_threads_list, NULL); } -/* threads_table_lock ********************************************************** +/* threads_list_lock *********************************************************** Enter the threads table mutex. NOTE: We need this function as we can't use an internal lock for - the threads table because the thread's lock is initialized in + the threads lists because the thread's lock is initialized in threads_table_add (when we have the thread index), but we already need the lock at the entry of the function. *******************************************************************************/ -void threads_table_lock(void) +void threads_list_lock(void) { - if (pthread_mutex_lock(&mutex_threads_table) != 0) + if (pthread_mutex_lock(&mutex_threads_list) != 0) vm_abort("threads_table_lock: pthread_mutex_lock failed: %s", strerror(errno)); } -/* threads_table_unlock ******************************************************** +/* threads_list_unlock ********************************************************* - Leave the threads table mutex. + Leave the threads list mutex. *******************************************************************************/ -void threads_table_unlock(void) +void threads_list_unlock(void) { - if (pthread_mutex_unlock(&mutex_threads_table) != 0) + if (pthread_mutex_unlock(&mutex_threads_list) != 0) vm_abort("threads_table_unlock: pthread_mutex_unlock failed: %s", strerror(errno)); } @@ -765,9 +779,9 @@ bool threads_init(void) return false; /* Get the main-thread (NOTE: The main threads is always the first - thread in the table). */ + thread in the list). */ - mainthread = threads_table_first(); + mainthread = threads_list_first(); /* create a java.lang.Thread for the main thread */ @@ -890,14 +904,14 @@ bool threads_init(void) threads_startup. IN: - t............the argument passed to pthread_create, ie. a pointer to + arg..........the argument passed to pthread_create, ie. a pointer to a startupinfo struct. CAUTION: When the `psem` semaphore is posted, the startupinfo struct becomes invalid! (It is allocated on the stack of threads_start_thread.) ******************************************************************************/ -static void *threads_startup_thread(void *t) +static void *threads_startup_thread(void *arg) { startupinfo *startup; threadobject *thread; @@ -925,8 +939,7 @@ static void *threads_startup_thread(void *t) /* get passed startupinfo structure and the values in there */ - startup = t; - t = NULL; /* make sure it's not used wrongly */ + startup = arg; thread = startup->thread; function = startup->function; @@ -946,13 +959,13 @@ static void *threads_startup_thread(void *t) threads_set_current_threadobject(thread); - /* thread is running */ + /* set our priority */ - thread->state = THREAD_STATE_RUNNABLE; + threads_set_thread_priority(thread->tid, thread->object->priority); - /* insert the thread into the threads table */ + /* thread is completely initialized */ - threads_table_add(thread); + threads_thread_state_runnable(thread); /* tell threads_startup_thread that we registered ourselves */ /* CAUTION: *startup becomes invalid with this! */ @@ -960,10 +973,6 @@ static void *threads_startup_thread(void *t) startup = NULL; threads_sem_post(psem); - /* set our priority */ - - threads_set_thread_priority(thread->tid, thread->object->priority); - #if defined(ENABLE_INTRP) /* set interpreter stack */ @@ -1213,11 +1222,9 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon) if (isdaemon) thread->flags |= THREAD_FLAG_DAEMON; - thread->state = THREAD_STATE_RUNNABLE; + /* thread is completely initialized */ - /* insert the thread into the threads table */ - - threads_table_add(thread); + threads_thread_state_runnable(thread); #if !defined(NDEBUG) if (opt_verbosethreads) { @@ -1263,7 +1270,7 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon) #if defined(ENABLE_JAVASE) /* get the main thread */ - mainthread = threads_table_first(); + mainthread = threads_list_first(); group = mainthread->object->group; #endif } @@ -1357,11 +1364,7 @@ bool threads_detach_thread(threadobject *thread) /* thread is terminated */ - thread->state = THREAD_STATE_TERMINATED; - - /* remove thread from the threads table */ - - threads_table_remove(thread); + threads_thread_state_terminated(thread); #if !defined(NDEBUG) if (opt_verbosethreads) { @@ -1393,15 +1396,15 @@ bool threads_detach_thread(threadobject *thread) void threads_join_all_threads(void) { - threadobject *thread; + threadobject *t; /* get current thread */ - thread = THREADOBJECT; + t = THREADOBJECT; /* this thread is waiting for all non-daemon threads to exit */ - thread->state = THREAD_STATE_WAITING; + threads_thread_state_waiting(t); /* enter join mutex */ @@ -1411,7 +1414,7 @@ void threads_join_all_threads(void) compare against 1 because the current (main thread) is also a non-daemon thread. */ - while (threads_table_get_non_daemons() > 1) + while (threads_list_get_non_daemons() > 1) pthread_cond_wait(&cond_join, &mutex_join); /* leave join mutex */ @@ -1512,22 +1515,22 @@ static bool threads_wait_with_timeout(threadobject *thread, while (!thread->interrupted && !thread->signaled && threads_current_time_is_earlier_than(wakeupTime)) { - thread->state = THREAD_STATE_TIMED_WAITING; + threads_thread_state_timed_waiting(thread); pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex, wakeupTime); - thread->state = THREAD_STATE_RUNNABLE; + threads_thread_state_runnable(thread); } } else { /* no timeout */ while (!thread->interrupted && !thread->signaled) { - thread->state = THREAD_STATE_WAITING; + threads_thread_state_waiting(thread); pthread_cond_wait(&thread->waitcond, &thread->waitmutex); - thread->state = THREAD_STATE_RUNNABLE; + threads_thread_state_runnable(thread); } } diff --git a/src/threads/native/threads.h b/src/threads/native/threads.h index 15b4053cf..343fb1175 100644 --- a/src/threads/native/threads.h +++ b/src/threads/native/threads.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: threads.h 7899 2007-05-11 19:31:04Z twisti $ + $Id: threads.h 7963 2007-05-24 10:21:16Z twisti $ */ @@ -135,6 +135,7 @@ struct threadobject { #endif dumpinfo_t dumpinfo; /* dump memory info structure */ + listnode_t linkage; /* threads-list */ }; diff --git a/src/threads/threads-common.c b/src/threads/threads-common.c index a30e3ad5c..97d7aadfa 100644 --- a/src/threads/threads-common.c +++ b/src/threads/threads-common.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: threads-common.c 7914 2007-05-18 14:17:34Z twisti $ + $Id: threads-common.c 7963 2007-05-24 10:21:16Z twisti $ */ @@ -33,6 +33,8 @@ #include "vm/types.h" +#include "mm/memory.h" + #include "native/jni.h" #include "native/include/java_lang_Object.h" @@ -47,6 +49,8 @@ #include "threads/lock-common.h" #include "threads/threads-common.h" +#include "toolbox/list.h" + #include "vm/builtin.h" #include "vm/stringlocal.h" #include "vm/vm.h" @@ -65,13 +69,11 @@ /* global variables ***********************************************************/ -/* global threads table */ -static threads_table_t threads_table; - - -/* prototypes *****************************************************************/ +/* global threads list */ +static list_t *list_threads; -static void threads_table_init(threadobject *mainthread); +/* global threads free-list */ +static list_t *list_threads_free; /* threads_preinit ************************************************************* @@ -87,6 +89,11 @@ void threads_preinit(void) { threadobject *mainthread; + /* initialize the threads lists */ + + list_threads = list_create(OFFSET(threadobject, linkage)); + list_threads_free = list_create(OFFSET(threadobject, linkage)); + /* Initialize the threads implementation (sets the thinlock on the main thread). */ @@ -96,10 +103,6 @@ void threads_preinit(void) mainthread = threads_thread_new(); - mainthread->object = NULL; - mainthread->index = 1; - mainthread->thinlock = lock_pre_compute_thinlock(mainthread->index); - /* thread is a Java thread and running */ mainthread->flags = THREAD_FLAG_JAVA; @@ -108,10 +111,6 @@ void threads_preinit(void) /* store the internal thread data-structure in the TSD */ threads_set_current_threadobject(mainthread); - - /* initialize the threads table with the main-thread */ - - threads_table_init(mainthread); /* initialize locking subsystems */ @@ -123,459 +122,189 @@ void threads_preinit(void) } -/* threads_table_init ********************************************************** - - Initialize the global threads table. We initialize the table with - the main-thread, which has always the index 1. - - IN: - mainthread....the main-thread - -*******************************************************************************/ - -#define THREADS_INITIAL_TABLE_SIZE 8 - -static void threads_table_init(threadobject *mainthread) -{ - threads_table_entry_t *ttemain; - s4 size; - s4 i; - - /* initialize the threads table lock */ - - threads_impl_table_init(); - - /* initialize the table */ - - size = THREADS_INITIAL_TABLE_SIZE; - - threads_table.table = MNEW(threads_table_entry_t, size); - threads_table.size = size; - threads_table.used = 0; - threads_table.daemons = 0; - - /* Link the entries in a freelist. Skip 2 entries: 0 is the - free-list header and 1 is the main thread. */ - - for (i = 2; i < size; i++) { - threads_table.table[i].thread = NULL; - threads_table.table[i].next = i + 1; - } - - threads_table.table[0].next = 2; - - /* terminate the freelist */ - - threads_table.table[size - 1].next = 0; /* index 0 is never free */ - - /* insert the main-thread */ - - ttemain = &(threads_table.table[1]); - - ttemain->thread = mainthread; - ttemain->next = 0; - - /* now 1 entry is used */ - - threads_table.used = 1; -} - - -/* threads_table_add *********************************************************** +/* threads_list_first ********************************************************** - Add a thread to the global threads table. The index is entered in the - threadobject. The thinlock value for the thread is pre-computed. + Return the first entry in the threads list. - IN: - thread............the thread to add - - RETURN VALUE: - The table index for the newly added thread. This value has also been - entered in the threadobject. + NOTE: This function does not lock the lists. *******************************************************************************/ -s4 threads_table_add(threadobject *thread) +threadobject *threads_list_first(void) { - threads_table_entry_t *ttefree; - threads_table_entry_t *ttemain; - threads_table_entry_t *tte; - s4 index; - s4 oldsize; - s4 newsize; - s4 i; - - /* lock the threads table */ - - threads_table_lock(); - - /* get free and main entry */ - - ttefree = &(threads_table.table[0]); - ttemain = &(threads_table.table[1]); - - /* get the next free index */ - - index = ttefree->next; - - /* no entry free anymore? resize the table */ - - if (index == 0) { - /* we must grow the table */ - - oldsize = threads_table.size; - newsize = oldsize * 2; - - threads_table.table = MREALLOC(threads_table.table, - threads_table_entry_t, oldsize, newsize); - threads_table.size = newsize; - - /* the addresses have changed, get them again */ - - ttefree = &(threads_table.table[0]); - ttemain = &(threads_table.table[1]); - - /* link the new entries to a free list */ - - for (i = oldsize; i < newsize; i++) { - threads_table.table[i].thread = NULL; - threads_table.table[i].next = i + 1; - } - - ttefree->next = oldsize; - - /* terminate the freelist */ - - threads_table.table[newsize - 1].next = 0; /* index 0 is never free */ - - /* use the first of the new entries */ - - index = ttefree->next; - } - - /* get the entry with the assigned index */ - - tte = &(threads_table.table[index]); - - /* store the next free index into the free-list header */ - - ttefree->next = tte->next; - - /* store the thread in the table */ - - tte->thread = thread; - - /* link the new entry into the used-list */ - - tte->next = ttemain->next; - ttemain->next = index; - - /* update the counters */ - - threads_table.used++; - - if (thread->flags & THREAD_FLAG_DAEMON) - threads_table.daemons++; - - assert(threads_table.used < threads_table.size); - - /* set the thread variables */ - - thread->index = index; - thread->thinlock = lock_pre_compute_thinlock(index); - - /* unlock the threads table */ - - threads_table_unlock(); - - return index; -} - - -/* threads_table_remove ******************************************************* - - Remove a thread from the global threads table. - - IN: - thread............the thread to remove - -******************************************************************************/ - -void threads_table_remove(threadobject *thread) -{ - threads_table_entry_t *ttefree; - threads_table_entry_t *tte; - s4 index; - s4 i; - - /* lock the threads table */ - - threads_table_lock(); - - /* get the free entry */ - - ttefree = &(threads_table.table[0]); - - /* get the current entry */ - - index = thread->index; - tte = &(threads_table.table[index]); - - assert(tte->thread == thread); - - /* Find the entry which has the one to be removed as next entry (I - think it's better to do it at the removal in linear time than - to have a list or to do it every time we iterate over all - threads). */ - - for (i = 0; i < threads_table.size; i++) { - if (threads_table.table[i].next == index) { - threads_table.table[i].next = tte->next; - break; - } - } - - /* clear the thread pointer in the entry */ - - tte->thread = NULL; - - /* this entry is free now, add it to the free-list */ - - tte->next = ttefree->next; - ttefree->next = index; - - /* update the counters */ - - threads_table.used--; - - if (thread->flags & THREAD_FLAG_DAEMON) - threads_table.daemons--; - - assert(threads_table.used >= 0); - - /* delete the index in the threadobject to discover bugs */ -#if !defined(NDEBUG) - thread->index = 0; -#endif + threadobject *t; - /* unlock the threads table */ + t = list_first_unsynced(list_threads); - threads_table_unlock(); + return t; } -/* threads_table_get *********************************************************** +/* threads_list_next *********************************************************** - Return the thread of the given table-entry index. + Return the next entry in the threads list. - NOTE: It is valid to pass and index of 0, as this entry is the - free-list header where the thread pointer is always NULL and - this is thre expected behavior. - - NOTE: This function does not lock the table. + NOTE: This function does not lock the lists. *******************************************************************************/ -static threadobject *threads_table_get(s4 index) +threadobject *threads_list_next(threadobject *t) { - threadobject *thread; + threadobject *next; - /* get the requested entry */ + next = list_next_unsynced(list_threads, t); - assert((index >= 0) && (index < threads_table.size)); - - thread = threads_table.table[index].thread; - - return thread; + return next; } -/* threads_table_get_threads *************************************************** +/* threads_list_get_non_daemons ************************************************ - Return the number of running threads. + Return the number of non-daemon threads. - NOTE: This function does not lock the table. + NOTE: This function does a linear-search over the threads list, + because it's only used for joining the threads. *******************************************************************************/ -s4 threads_table_get_threads(void) +s4 threads_list_get_non_daemons(void) { - return threads_table.used; -} - - -/* threads_table_get_non_daemons *********************************************** - - Return the number of non-daemon threads. - -*******************************************************************************/ + threadobject *t; + s4 nondaemons; -s4 threads_table_get_non_daemons(void) -{ - s4 nondaemons; + /* lock the threads lists */ - /* lock the threads table */ + threads_list_lock(); - threads_table_lock(); + nondaemons = 0; - nondaemons = threads_table.used - threads_table.daemons; + for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) { + if (!(t->flags & THREAD_FLAG_DAEMON)) + nondaemons++; + } - /* unlock the threads table */ + /* unlock the threads lists */ - threads_table_unlock(); + threads_list_unlock(); return nondaemons; } -/* threads_table_first ********************************************************* - - Return the first thread of the threads table. - - NOTE: This is always the entry with index 1 and must be the main - thread. +/* threads_thread_new ********************************************************** - NOTE: This function does not lock the table. + Allocates and initializes an internal thread data-structure and + adds it to the threads list. *******************************************************************************/ -threadobject *threads_table_first(void) +threadobject *threads_thread_new(void) { - threadobject *thread; - - /* get the requested entry */ - - thread = threads_table_get(1); - - return thread; -} - + threadobject *t; -/* threads_table_next ********************************************************** + /* lock the threads-lists */ - Return the next thread of the threads table relative to the passed - one. + threads_list_lock(); - NOTE: This function does not lock the table. + /* try to get a thread from the free-list */ -*******************************************************************************/ + t = list_first_unsynced(list_threads_free); -threadobject *threads_table_next(threadobject *thread) -{ - threads_table_entry_t *tte; - threadobject *next; - s4 index; + /* is a free thread available? */ - index = thread->index; + if (t != NULL) { + /* yes, remove it from the free list */ - /* get the passed entry */ + list_remove_unsynced(list_threads_free, t); + } + else { + /* no, allocate a new one */ - assert((index > 0) && (index < threads_table.size)); +#if defined(ENABLE_GC_BOEHM) + t = GCNEW_UNCOLLECTABLE(threadobject, 1); +#else + t = NEW(threadobject); +#endif - tte = &(threads_table.table[index]); +#if defined(ENABLE_STATISTICS) + if (opt_stat) + size_threadobject += sizeof(threadobject); +#endif - /* get the requested entry */ + /* clear memory */ - next = threads_table_get(tte->next); + MZERO(t, threadobject, 1); - return next; -} + /* set the threads-index */ + t->index = list_threads->size + 1; + } -/* threads_table_dump ********************************************************* + /* pre-compute the thinlock-word */ - Dump the threads table for debugging purposes. + assert(t->index != 0); -******************************************************************************/ + t->thinlock = lock_pre_compute_thinlock(t->index); + t->state = THREAD_STATE_NEW; -#if !defined(NDEBUG) -void threads_table_dump(void) -{ - s4 i; - s4 size; - ptrint index; + /* initialize the implementation-specific bits */ - size = threads_table.size; + threads_impl_thread_new(t); - log_println("threads table =========="); + /* add the thread to the threads-list */ - log_println("size: %d", size); - log_println("used: %d", threads_table.used); - log_println("daemons: %d", threads_table.daemons); + list_add_last_unsynced(list_threads, t); - for (i = 0; i < size; i++) { - index = threads_table.table[i].next; + /* unlock the threads-lists */ - if (threads_table.table[i].thread != NULL) - log_println("%4d: thread=0x%08x, next=%d", i, - threads_table.table[i].thread->tid, (int) index); - else - log_println("%4d: free, next=%d", i, (int) index); - } + threads_list_unlock(); - log_println("end of threads table =========="); + return t; } -#endif -/* threads_thread_new ********************************************************** +/* threads_thread_free ********************************************************* - Allocates and initializes an internal thread data-structure. + Frees an internal thread data-structure by removing it from the + threads-list and adding it to the free-list. + + NOTE: The data-structure is NOT freed, the pointer keeps valid! *******************************************************************************/ -threadobject *threads_thread_new(void) +void threads_thread_free(threadobject *t) { - threadobject *t; + s4 index; - /* allocate internal thread data-structure */ + /* lock the threads-lists */ -#if defined(ENABLE_GC_BOEHM) - t = GCNEW_UNCOLLECTABLE(threadobject, 1); -#else - t = NEW(threadobject); -#endif + threads_list_lock(); -#if defined(ENABLE_STATISTICS) - if (opt_stat) - size_threadobject += sizeof(threadobject); -#endif + /* cleanup the implementation-specific bits */ - /* initialize thread data structure */ + threads_impl_thread_free(t); - t->index = 0; - t->interrupted = false; - t->signaled = false; - t->sleeping = false; + /* remove the thread from the threads-list */ - threads_impl_thread_new(t); + list_remove_unsynced(list_threads, t); - return t; -} + /* Clear memory, but keep the thread-index. */ + /* ATTENTION: Do this after list_remove, otherwise the linkage + pointers are invalid. */ + index = t->index; -/* threads_thread_free ********************************************************* + MZERO(t, threadobject, 1); - Frees an internal thread data-structure. + t->index = index; -*******************************************************************************/ + /* add the thread to the free list */ -void threads_thread_free(threadobject *t) -{ - /* cleanup the implementation-specific bits */ - - threads_impl_thread_free(t); + list_add_first_unsynced(list_threads_free, t); -#if defined(ENABLE_GC_BOEHM) - GCFREE(t); -#else - FREE(t, threadobject); -#endif + /* unlock the threads-lists */ -#if defined(ENABLE_STATISTICS) - if (opt_stat) - size_threadobject -= sizeof(threadobject); -#endif + threads_list_unlock(); } @@ -705,6 +434,8 @@ void threads_thread_print_info(threadobject *t) java_lang_Thread *object; utf *name; + assert(t->state != THREAD_STATE_NEW); + /* the thread may be currently in initalization, don't print it */ object = t->object; @@ -735,6 +466,8 @@ void threads_thread_print_info(threadobject *t) (ptrint) t, (ptrint) t->tid, (ptrint) t->tid); #endif + printf(" index=%d", t->index); + /* print thread state */ switch (t->state) { @@ -788,17 +521,91 @@ ptrint threads_get_current_tid(void) } +/* threads_thread_state_runnable *********************************************** + + Set the current state of the given thread to THREAD_STATE_RUNNABLE. + +*******************************************************************************/ + +void threads_thread_state_runnable(threadobject *t) +{ + /* set the state inside the lock */ + + threads_list_lock(); + + t->state = THREAD_STATE_RUNNABLE; + + threads_list_unlock(); +} + + +/* threads_thread_state_waiting ************************************************ + + Set the current state of the given thread to THREAD_STATE_WAITING. + +*******************************************************************************/ + +void threads_thread_state_waiting(threadobject *t) +{ + /* set the state in the lock */ + + threads_list_lock(); + + t->state = THREAD_STATE_WAITING; + + threads_list_unlock(); +} + + +/* threads_thread_state_timed_waiting ****************************************** + + Set the current state of the given thread to + THREAD_STATE_TIMED_WAITING. + +*******************************************************************************/ + +void threads_thread_state_timed_waiting(threadobject *t) +{ + /* set the state in the lock */ + + threads_list_lock(); + + t->state = THREAD_STATE_TIMED_WAITING; + + threads_list_unlock(); +} + + +/* threads_thread_state_terminated ********************************************* + + Set the current state of the given thread to + THREAD_STATE_TERMINATED. + +*******************************************************************************/ + +void threads_thread_state_terminated(threadobject *t) +{ + /* set the state in the lock */ + + threads_list_lock(); + + t->state = THREAD_STATE_TERMINATED; + + threads_list_unlock(); +} + + /* threads_thread_get_state **************************************************** Returns the current state of the given thread. *******************************************************************************/ -utf *threads_thread_get_state(threadobject *thread) +utf *threads_thread_get_state(threadobject *t) { utf *u; - switch (thread->state) { + switch (t->state) { case THREAD_STATE_NEW: u = utf_new_char("NEW"); break; @@ -818,7 +625,7 @@ utf *threads_thread_get_state(threadobject *thread) u = utf_new_char("TERMINATED"); break; default: - vm_abort("threads_get_state: unknown thread state %d", thread->state); + vm_abort("threads_get_state: unknown thread state %d", t->state); /* keep compiler happy */ @@ -877,15 +684,15 @@ void threads_dump(void) /* XXX we should stop the world here */ - /* lock the threads table */ + /* lock the threads lists */ - threads_table_lock(); + threads_list_lock(); printf("Full thread dump CACAO "VERSION":\n"); /* iterate over all started threads */ - for (t = threads_table_first(); t != NULL; t = threads_table_next(t)) { + for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) { /* print thread info */ printf("\n"); @@ -897,9 +704,9 @@ void threads_dump(void) threads_thread_print_stacktrace(t); } - /* unlock the threads table */ + /* unlock the threads lists */ - threads_table_unlock(); + threads_list_unlock(); } diff --git a/src/threads/threads-common.h b/src/threads/threads-common.h index 1e8ed0496..0bbf2b2bd 100644 --- a/src/threads/threads-common.h +++ b/src/threads/threads-common.h @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: threads-common.h 7959 2007-05-23 19:37:26Z twisti $ + $Id: threads-common.h 7963 2007-05-24 10:21:16Z twisti $ */ @@ -50,12 +50,6 @@ #if defined(ENABLE_THREADS) -/* typedefs *******************************************************************/ - -typedef struct threads_table_entry_t threads_table_entry_t; -typedef struct threads_table_t threads_table_t; - - /* thread states **************************************************************/ #define THREAD_STATE_NEW 1 @@ -73,58 +67,30 @@ typedef struct threads_table_t threads_table_t; #define MAX_PRIORITY 10 -/* threads_table_entry_t ******************************************************* - - An entry in the global threads table. - -*******************************************************************************/ - -struct threads_table_entry_t { - threadobject *thread; /* an existing thread */ - s4 next; /* next free or used index */ -}; - - -/* threads_table_t ************************************************************* - - Struct for the global threads table. - -*******************************************************************************/ - -struct threads_table_t { - threads_table_entry_t *table; /* the table, threads[0] is the head */ - /* of the free list. Real entries */ - /* start at threads[1]. */ - s4 size; /* current size of the table */ - s4 used; /* number of thread entries */ - s4 daemons; /* number of daemon thread entries */ -}; - - /* function prototypes ********************************************************/ void threads_preinit(void); -s4 threads_table_add(threadobject *thread); -void threads_table_remove(threadobject *thread); -s4 threads_table_get_threads(void); -s4 threads_table_get_non_daemons(void); -threadobject *threads_table_first(void); -threadobject *threads_table_next(threadobject *thread); - -#if !defined(NDEBUG) -void threads_table_dump(void); -#endif +threadobject *threads_list_first(void); +threadobject *threads_list_next(threadobject *t); +s4 threads_list_get_non_daemons(void); threadobject *threads_thread_new(void); void threads_thread_free(threadobject *t); + bool threads_thread_start_internal(utf *name, functionptr f); void threads_thread_start(java_lang_Thread *object); void threads_thread_print_info(threadobject *t); ptrint threads_get_current_tid(void); -utf *threads_thread_get_state(threadobject *thread); + +void threads_thread_state_runnable(threadobject *t); +void threads_thread_state_waiting(threadobject *t); +void threads_thread_state_timed_waiting(threadobject *t); +void threads_thread_state_terminated(threadobject *t); +utf *threads_thread_get_state(threadobject *t); + bool threads_thread_is_alive(threadobject *thread); void threads_dump(void); @@ -137,8 +103,8 @@ void threads_print_stacktrace(void); void threads_impl_preinit(void); void threads_impl_table_init(void); -void threads_table_lock(void); -void threads_table_unlock(void); +void threads_list_lock(void); +void threads_list_unlock(void); void threads_set_current_threadobject(threadobject *thread); void threads_impl_thread_new(threadobject *t); -- 2.25.1