1 /* src/threads/threads-common.c - machine independent thread functions
3 Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: threads-common.c 7893 2007-05-10 13:27:29Z twisti $
36 #include "native/jni.h"
38 #include "native/include/java_lang_Object.h"
39 #include "native/include/java_lang_String.h"
40 #include "native/include/java_lang_Thread.h"
42 #if defined(WITH_CLASSPATH_GNU)
43 # include "native/include/java_lang_VMThread.h"
46 #include "threads/critical.h"
47 #include "threads/lock-common.h"
48 #include "threads/threads-common.h"
50 #include "vm/builtin.h"
51 #include "vm/stringlocal.h"
54 #include "vm/jit/stacktrace.h"
56 #include "vmcore/class.h"
58 #if defined(ENABLE_STATISTICS)
59 # include "vmcore/options.h"
60 # include "vmcore/statistics.h"
63 #include "vmcore/utf8.h"
66 /* global variables ***********************************************************/
68 /* global threads table */
69 static threads_table_t threads_table;
72 /* prototypes *****************************************************************/
74 static void threads_table_init(threadobject *mainthread);
77 /* threads_preinit *************************************************************
79 Do some early initialization of stuff required.
81 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
82 is called AFTER this function!
84 *******************************************************************************/
86 void threads_preinit(void)
88 threadobject *mainthread;
90 /* Initialize the threads implementation (sets the thinlock on the
93 threads_impl_preinit();
95 /* create internal thread data-structure for the main thread */
97 mainthread = threads_create_thread();
99 mainthread->object = NULL;
100 mainthread->index = 1;
101 mainthread->thinlock = lock_pre_compute_thinlock(mainthread->index);
103 /* thread is a Java thread and running */
105 mainthread->flags = THREAD_FLAG_JAVA;
106 mainthread->state = THREAD_STATE_RUNNABLE;
108 /* store the internal thread data-structure in the TSD */
110 threads_set_current_threadobject(mainthread);
112 /* initialize the threads table with the main-thread */
114 threads_table_init(mainthread);
116 /* initialize locking subsystems */
120 /* initialize the critical section */
126 /* threads_table_init **********************************************************
128 Initialize the global threads table. We initialize the table with
129 the main-thread, which has always the index 1.
132 mainthread....the main-thread
134 *******************************************************************************/
136 #define THREADS_INITIAL_TABLE_SIZE 8
138 static void threads_table_init(threadobject *mainthread)
140 threads_table_entry_t *ttemain;
144 /* initialize the threads table lock */
146 threads_impl_table_init();
148 /* initialize the table */
150 size = THREADS_INITIAL_TABLE_SIZE;
152 threads_table.table = MNEW(threads_table_entry_t, size);
153 threads_table.size = size;
154 threads_table.used = 0;
155 threads_table.daemons = 0;
157 /* Link the entries in a freelist. Skip 2 entries: 0 is the
158 free-list header and 1 is the main thread. */
160 for (i = 2; i < size; i++) {
161 threads_table.table[i].thread = NULL;
162 threads_table.table[i].next = i + 1;
165 threads_table.table[0].next = 2;
167 /* terminate the freelist */
169 threads_table.table[size - 1].next = 0; /* index 0 is never free */
171 /* insert the main-thread */
173 ttemain = &(threads_table.table[1]);
175 ttemain->thread = mainthread;
178 /* now 1 entry is used */
180 threads_table.used = 1;
184 /* threads_table_add ***********************************************************
186 Add a thread to the global threads table. The index is entered in the
187 threadobject. The thinlock value for the thread is pre-computed.
190 thread............the thread to add
193 The table index for the newly added thread. This value has also been
194 entered in the threadobject.
196 *******************************************************************************/
198 s4 threads_table_add(threadobject *thread)
200 threads_table_entry_t *ttefree;
201 threads_table_entry_t *ttemain;
202 threads_table_entry_t *tte;
208 /* lock the threads table */
210 threads_table_lock();
212 /* get free and main entry */
214 ttefree = &(threads_table.table[0]);
215 ttemain = &(threads_table.table[1]);
217 /* get the next free index */
219 index = ttefree->next;
221 /* no entry free anymore? resize the table */
224 /* we must grow the table */
226 oldsize = threads_table.size;
227 newsize = oldsize * 2;
229 threads_table.table = MREALLOC(threads_table.table,
230 threads_table_entry_t, oldsize, newsize);
231 threads_table.size = newsize;
233 /* the addresses have changed, get them again */
235 ttefree = &(threads_table.table[0]);
236 ttemain = &(threads_table.table[1]);
238 /* link the new entries to a free list */
240 for (i = oldsize; i < newsize; i++) {
241 threads_table.table[i].thread = NULL;
242 threads_table.table[i].next = i + 1;
245 ttefree->next = oldsize;
247 /* terminate the freelist */
249 threads_table.table[newsize - 1].next = 0; /* index 0 is never free */
251 /* use the first of the new entries */
253 index = ttefree->next;
256 /* get the entry with the assigned index */
258 tte = &(threads_table.table[index]);
260 /* store the next free index into the free-list header */
262 ttefree->next = tte->next;
264 /* store the thread in the table */
266 tte->thread = thread;
268 /* link the new entry into the used-list */
270 tte->next = ttemain->next;
271 ttemain->next = index;
273 /* update the counters */
275 threads_table.used++;
277 if (thread->flags & THREAD_FLAG_DAEMON)
278 threads_table.daemons++;
280 assert(threads_table.used < threads_table.size);
282 /* set the thread variables */
284 thread->index = index;
285 thread->thinlock = lock_pre_compute_thinlock(index);
287 /* unlock the threads table */
289 threads_table_unlock();
295 /* threads_table_remove *******************************************************
297 Remove a thread from the global threads table.
300 thread............the thread to remove
302 ******************************************************************************/
304 void threads_table_remove(threadobject *thread)
306 threads_table_entry_t *ttefree;
307 threads_table_entry_t *tte;
311 /* lock the threads table */
313 threads_table_lock();
315 /* get the free entry */
317 ttefree = &(threads_table.table[0]);
319 /* get the current entry */
321 index = thread->index;
322 tte = &(threads_table.table[index]);
324 assert(tte->thread == thread);
326 /* Find the entry which has the one to be removed as next entry (I
327 think it's better to do it at the removal in linear time than
328 to have a list or to do it every time we iterate over all
331 for (i = 0; i < threads_table.size; i++) {
332 if (threads_table.table[i].next == index) {
333 threads_table.table[i].next = tte->next;
338 /* clear the thread pointer in the entry */
342 /* this entry is free now, add it to the free-list */
344 tte->next = ttefree->next;
345 ttefree->next = index;
347 /* update the counters */
349 threads_table.used--;
351 if (thread->flags & THREAD_FLAG_DAEMON)
352 threads_table.daemons--;
354 assert(threads_table.used >= 0);
356 /* delete the index in the threadobject to discover bugs */
361 /* unlock the threads table */
363 threads_table_unlock();
367 /* threads_table_get ***********************************************************
369 Return the thread of the given table-entry index.
371 NOTE: It is valid to pass and index of 0, as this entry is the
372 free-list header where the thread pointer is always NULL and
373 this is thre expected behavior.
375 NOTE: This function does not lock the table.
377 *******************************************************************************/
379 static threadobject *threads_table_get(s4 index)
381 threadobject *thread;
383 /* get the requested entry */
385 assert((index >= 0) && (index < threads_table.size));
387 thread = threads_table.table[index].thread;
393 /* threads_table_get_threads ***************************************************
395 Return the number of running threads.
397 NOTE: This function does not lock the table.
399 *******************************************************************************/
401 s4 threads_table_get_threads(void)
403 return threads_table.used;
407 /* threads_table_get_non_daemons ***********************************************
409 Return the number of non-daemon threads.
411 *******************************************************************************/
413 s4 threads_table_get_non_daemons(void)
417 /* lock the threads table */
419 threads_table_lock();
421 nondaemons = threads_table.used - threads_table.daemons;
423 /* unlock the threads table */
425 threads_table_unlock();
431 /* threads_table_first *********************************************************
433 Return the first thread of the threads table.
435 NOTE: This is always the entry with index 1 and must be the main
438 NOTE: This function does not lock the table.
440 *******************************************************************************/
442 threadobject *threads_table_first(void)
444 threadobject *thread;
446 /* get the requested entry */
448 thread = threads_table_get(1);
454 /* threads_table_next **********************************************************
456 Return the next thread of the threads table relative to the passed
459 NOTE: This function does not lock the table.
461 *******************************************************************************/
463 threadobject *threads_table_next(threadobject *thread)
465 threads_table_entry_t *tte;
469 index = thread->index;
471 /* get the passed entry */
473 assert((index > 0) && (index < threads_table.size));
475 tte = &(threads_table.table[index]);
477 /* get the requested entry */
479 next = threads_table_get(tte->next);
485 /* threads_table_dump *********************************************************
487 Dump the threads table for debugging purposes.
489 ******************************************************************************/
492 void threads_table_dump(void)
498 size = threads_table.size;
500 log_println("threads table ==========");
502 log_println("size: %d", size);
503 log_println("used: %d", threads_table.used);
504 log_println("daemons: %d", threads_table.daemons);
506 for (i = 0; i < size; i++) {
507 index = threads_table.table[i].next;
509 if (threads_table.table[i].thread != NULL)
510 log_println("%4d: thread=0x%08x, next=%d", i,
511 threads_table.table[i].thread->tid, (int) index);
513 log_println("%4d: free, next=%d", i, (int) index);
516 log_println("end of threads table ==========");
521 /* threads_create_thread *******************************************************
523 Creates and initializes an internal thread data-structure.
525 *******************************************************************************/
527 threadobject *threads_create_thread(void)
529 threadobject *thread;
531 /* allocate internal thread data-structure */
533 #if defined(ENABLE_GC_BOEHM)
534 thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
536 thread = NEW(threadobject);
539 #if defined(ENABLE_STATISTICS)
541 size_threadobject += sizeof(threadobject);
544 /* initialize thread data structure */
546 threads_init_threadobject(thread);
547 lock_init_execution_env(thread);
553 /* threads_thread_start_internal ***********************************************
555 Start an internal thread in the JVM. No Java thread objects exists
559 name.......UTF-8 name of the thread
560 f..........function pointer to C function to start
562 *******************************************************************************/
564 bool threads_thread_start_internal(utf *name, functionptr f)
566 threadobject *thread;
568 #if defined(WITH_CLASSPATH_GNU)
569 java_lang_VMThread *vmt;
572 /* create internal thread data-structure */
574 thread = threads_create_thread();
576 /* create the java thread object */
578 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
583 #if defined(WITH_CLASSPATH_GNU)
584 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
590 vmt->vmdata = (java_lang_Object *) thread;
593 #elif defined(WITH_CLASSPATH_CLDC1_1)
594 t->vm_thread = (java_lang_Object *) thread;
599 thread->flags = THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
601 /* set java.lang.Thread fields */
603 t->name = (java_lang_String *) javastring_new(name);
604 #if defined(ENABLE_JAVASE)
607 t->priority = NORM_PRIORITY;
609 /* start the thread */
611 threads_impl_thread_start(thread, f);
613 /* everything's ok */
619 /* threads_thread_start ********************************************************
621 Start a Java thread in the JVM. Only the java thread object exists
625 object.....the java thread object java.lang.Thread
627 *******************************************************************************/
629 void threads_thread_start(java_lang_Thread *object)
631 threadobject *thread;
633 /* create internal thread data-structure */
635 thread = threads_create_thread();
637 /* link the two objects together */
639 thread->object = object;
641 /* this is a normal Java thread */
643 thread->flags = THREAD_FLAG_JAVA;
645 #if defined(ENABLE_JAVASE)
646 /* is this a daemon thread? */
648 if (object->daemon == true)
649 thread->flags |= THREAD_FLAG_DAEMON;
652 #if defined(WITH_CLASSPATH_GNU)
653 assert(object->vmThread);
654 assert(object->vmThread->vmdata == NULL);
656 object->vmThread->vmdata = (java_lang_Object *) thread;
657 #elif defined(WITH_CLASSPATH_CLDC1_1)
658 object->vm_thread = (java_lang_Object *) thread;
661 /* Start the thread. Don't pass a function pointer (NULL) since
662 we want Thread.run()V here. */
664 threads_impl_thread_start(thread, NULL);
668 /* threads_get_current_tid *****************************************************
670 Return the tid of the current thread.
675 *******************************************************************************/
677 ptrint threads_get_current_tid(void)
679 threadobject *thread;
681 thread = THREADOBJECT;
683 /* this may happen during bootstrap */
688 return (ptrint) thread->tid;
692 /* threads_thread_get_state ****************************************************
694 Returns the current state of the given thread.
696 *******************************************************************************/
698 utf *threads_thread_get_state(threadobject *thread)
702 switch (thread->state) {
703 case THREAD_STATE_NEW:
704 u = utf_new_char("NEW");
706 case THREAD_STATE_RUNNABLE:
707 u = utf_new_char("RUNNABLE");
709 case THREAD_STATE_BLOCKED:
710 u = utf_new_char("BLOCKED");
712 case THREAD_STATE_WAITING:
713 u = utf_new_char("WAITING");
715 case THREAD_STATE_TIMED_WAITING:
716 u = utf_new_char("TIMED_WAITING");
718 case THREAD_STATE_TERMINATED:
719 u = utf_new_char("TERMINATED");
722 vm_abort("threads_get_state: unknown thread state %d", thread->state);
729 /* threads_thread_is_alive *****************************************************
731 Returns if the give thread is alive.
733 *******************************************************************************/
735 bool threads_thread_is_alive(threadobject *thread)
739 switch (thread->state) {
740 case THREAD_STATE_NEW:
741 case THREAD_STATE_TERMINATED:
745 case THREAD_STATE_RUNNABLE:
746 case THREAD_STATE_BLOCKED:
747 case THREAD_STATE_WAITING:
748 case THREAD_STATE_TIMED_WAITING:
753 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
760 /* threads_dump ****************************************************************
762 Dumps info for all threads running in the JVM. This function is
763 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
765 *******************************************************************************/
767 void threads_dump(void)
770 java_lang_Thread *object;
773 /* XXX we should stop the world here */
775 /* lock the threads table */
777 threads_table_lock();
779 printf("Full thread dump CACAO "VERSION":\n");
781 /* iterate over all started threads */
783 for (t = threads_table_first(); t != NULL; t = threads_table_next(t)) {
784 /* get thread object */
788 /* the thread may be currently in initalization, don't print it */
790 if (object != NULL) {
791 /* get thread name */
793 #if defined(ENABLE_JAVASE)
794 name = javastring_toutf((java_objectheader *) object->name, false);
795 #elif defined(ENABLE_JAVAME_CLDC1_1)
800 utf_display_printable_ascii(name);
803 if (t->flags & THREAD_FLAG_DAEMON)
806 printf(" prio=%d", object->priority);
808 #if SIZEOF_VOID_P == 8
809 printf(" tid=0x%016lx (%ld)", (ptrint) t->tid, (ptrint) t->tid);
811 printf(" tid=0x%08x (%d)", (ptrint) t->tid, (ptrint) t->tid);
814 /* print thread state */
817 case THREAD_STATE_NEW:
820 case THREAD_STATE_RUNNABLE:
823 case THREAD_STATE_BLOCKED:
826 case THREAD_STATE_WAITING:
829 case THREAD_STATE_TIMED_WAITING:
830 printf(" waiting on condition");
832 case THREAD_STATE_TERMINATED:
833 printf(" terminated");
836 vm_abort("threads_dump: unknown thread state %d", t->state);
841 /* print trace of thread */
843 threads_thread_print_stacktrace(t);
847 /* unlock the threads table */
849 threads_table_unlock();
853 /* threads_thread_print_stacktrace *********************************************
855 Print the current stacktrace of the current thread.
857 *******************************************************************************/
859 void threads_thread_print_stacktrace(threadobject *thread)
862 stacktracebuffer *stb;
865 /* mark start of dump memory area */
867 dumpsize = dump_size();
869 /* create a stacktrace for the passed thread */
871 sfi = thread->_stackframeinfo;
873 stb = stacktrace_create(sfi);
875 /* print stacktrace */
878 stacktrace_print_trace_from_buffer(stb);
880 puts("\t<<No stacktrace available>>");
884 dump_release(dumpsize);
888 /* threads_print_stacktrace ****************************************************
890 Print the current stacktrace of the current thread.
892 *******************************************************************************/
894 void threads_print_stacktrace(void)
896 threadobject *thread;
898 thread = THREADOBJECT;
900 threads_thread_print_stacktrace(thread);
905 * These are local overrides for various environment variables in Emacs.
906 * Please do not remove this and leave it at the end of the file, where
907 * Emacs will automagically detect them.
908 * ---------------------------------------------------------------------
911 * indent-tabs-mode: t
915 * vim:noexpandtab:sw=4:ts=4: