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 7899 2007-05-11 19:31:04Z 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)
531 /* allocate internal thread data-structure */
533 #if defined(ENABLE_GC_BOEHM)
534 t = GCNEW_UNCOLLECTABLE(threadobject, 1);
536 t = NEW(threadobject);
539 #if defined(ENABLE_STATISTICS)
541 size_threadobject += sizeof(threadobject);
544 /* initialize thread data structure */
546 threads_init_threadobject(t);
552 /* threads_thread_start_internal ***********************************************
554 Start an internal thread in the JVM. No Java thread objects exists
558 name.......UTF-8 name of the thread
559 f..........function pointer to C function to start
561 *******************************************************************************/
563 bool threads_thread_start_internal(utf *name, functionptr f)
565 threadobject *thread;
567 #if defined(WITH_CLASSPATH_GNU)
568 java_lang_VMThread *vmt;
571 /* create internal thread data-structure */
573 thread = threads_create_thread();
575 /* create the java thread object */
577 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
582 #if defined(WITH_CLASSPATH_GNU)
583 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
589 vmt->vmdata = (java_lang_Object *) thread;
592 #elif defined(WITH_CLASSPATH_CLDC1_1)
593 t->vm_thread = (java_lang_Object *) thread;
598 thread->flags = THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
600 /* set java.lang.Thread fields */
602 t->name = (java_lang_String *) javastring_new(name);
603 #if defined(ENABLE_JAVASE)
606 t->priority = NORM_PRIORITY;
608 /* start the thread */
610 threads_impl_thread_start(thread, f);
612 /* everything's ok */
618 /* threads_thread_start ********************************************************
620 Start a Java thread in the JVM. Only the java thread object exists
624 object.....the java thread object java.lang.Thread
626 *******************************************************************************/
628 void threads_thread_start(java_lang_Thread *object)
630 threadobject *thread;
632 /* create internal thread data-structure */
634 thread = threads_create_thread();
636 /* link the two objects together */
638 thread->object = object;
640 /* this is a normal Java thread */
642 thread->flags = THREAD_FLAG_JAVA;
644 #if defined(ENABLE_JAVASE)
645 /* is this a daemon thread? */
647 if (object->daemon == true)
648 thread->flags |= THREAD_FLAG_DAEMON;
651 #if defined(WITH_CLASSPATH_GNU)
652 assert(object->vmThread);
653 assert(object->vmThread->vmdata == NULL);
655 object->vmThread->vmdata = (java_lang_Object *) thread;
656 #elif defined(WITH_CLASSPATH_CLDC1_1)
657 object->vm_thread = (java_lang_Object *) thread;
660 /* Start the thread. Don't pass a function pointer (NULL) since
661 we want Thread.run()V here. */
663 threads_impl_thread_start(thread, NULL);
667 /* threads_thread_print_info ***************************************************
669 Print information of the passed thread.
671 *******************************************************************************/
673 void threads_thread_print_info(threadobject *t)
675 java_lang_Thread *object;
678 /* the thread may be currently in initalization, don't print it */
682 if (object != NULL) {
683 /* get thread name */
685 #if defined(ENABLE_JAVASE)
686 name = javastring_toutf((java_objectheader *) object->name, false);
687 #elif defined(ENABLE_JAVAME_CLDC1_1)
692 utf_display_printable_ascii(name);
695 if (t->flags & THREAD_FLAG_DAEMON)
698 printf(" prio=%d", object->priority);
700 #if SIZEOF_VOID_P == 8
701 printf(" t=0x%016lx tid=0x%016lx (%ld)",
702 (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
704 printf(" t=0x%08x tid=0x%08x (%d)",
705 (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
708 /* print thread state */
711 case THREAD_STATE_NEW:
714 case THREAD_STATE_RUNNABLE:
717 case THREAD_STATE_BLOCKED:
720 case THREAD_STATE_WAITING:
723 case THREAD_STATE_TIMED_WAITING:
724 printf(" waiting on condition");
726 case THREAD_STATE_TERMINATED:
727 printf(" terminated");
730 vm_abort("threads_thread_print_info: unknown thread state %d",
737 /* threads_get_current_tid *****************************************************
739 Return the tid of the current thread.
744 *******************************************************************************/
746 ptrint threads_get_current_tid(void)
748 threadobject *thread;
750 thread = THREADOBJECT;
752 /* this may happen during bootstrap */
757 return (ptrint) thread->tid;
761 /* threads_thread_get_state ****************************************************
763 Returns the current state of the given thread.
765 *******************************************************************************/
767 utf *threads_thread_get_state(threadobject *thread)
771 switch (thread->state) {
772 case THREAD_STATE_NEW:
773 u = utf_new_char("NEW");
775 case THREAD_STATE_RUNNABLE:
776 u = utf_new_char("RUNNABLE");
778 case THREAD_STATE_BLOCKED:
779 u = utf_new_char("BLOCKED");
781 case THREAD_STATE_WAITING:
782 u = utf_new_char("WAITING");
784 case THREAD_STATE_TIMED_WAITING:
785 u = utf_new_char("TIMED_WAITING");
787 case THREAD_STATE_TERMINATED:
788 u = utf_new_char("TERMINATED");
791 vm_abort("threads_get_state: unknown thread state %d", thread->state);
798 /* threads_thread_is_alive *****************************************************
800 Returns if the give thread is alive.
802 *******************************************************************************/
804 bool threads_thread_is_alive(threadobject *thread)
808 switch (thread->state) {
809 case THREAD_STATE_NEW:
810 case THREAD_STATE_TERMINATED:
814 case THREAD_STATE_RUNNABLE:
815 case THREAD_STATE_BLOCKED:
816 case THREAD_STATE_WAITING:
817 case THREAD_STATE_TIMED_WAITING:
822 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
829 /* threads_dump ****************************************************************
831 Dumps info for all threads running in the JVM. This function is
832 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
834 *******************************************************************************/
836 void threads_dump(void)
840 /* XXX we should stop the world here */
842 /* lock the threads table */
844 threads_table_lock();
846 printf("Full thread dump CACAO "VERSION":\n");
848 /* iterate over all started threads */
850 for (t = threads_table_first(); t != NULL; t = threads_table_next(t)) {
851 /* print thread info */
854 threads_thread_print_info(t);
857 /* print trace of thread */
859 threads_thread_print_stacktrace(t);
862 /* unlock the threads table */
864 threads_table_unlock();
868 /* threads_thread_print_stacktrace *********************************************
870 Print the current stacktrace of the current thread.
872 *******************************************************************************/
874 void threads_thread_print_stacktrace(threadobject *thread)
877 stacktracebuffer *stb;
880 /* mark start of dump memory area */
882 dumpsize = dump_size();
884 /* create a stacktrace for the passed thread */
886 sfi = thread->_stackframeinfo;
888 stb = stacktrace_create(sfi);
890 /* print stacktrace */
893 stacktrace_print_trace_from_buffer(stb);
895 puts("\t<<No stacktrace available>>");
899 dump_release(dumpsize);
903 /* threads_print_stacktrace ****************************************************
905 Print the current stacktrace of the current thread.
907 *******************************************************************************/
909 void threads_print_stacktrace(void)
911 threadobject *thread;
913 thread = THREADOBJECT;
915 threads_thread_print_stacktrace(thread);
920 * These are local overrides for various environment variables in Emacs.
921 * Please do not remove this and leave it at the end of the file, where
922 * Emacs will automagically detect them.
923 * ---------------------------------------------------------------------
926 * indent-tabs-mode: t
930 * vim:noexpandtab:sw=4:ts=4: