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 7853 2007-05-02 20:40:11Z 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 *******************************************************************************/
377 threadobject *threads_table_get(s4 index)
379 threadobject *thread;
381 /* lock the threads table */
383 threads_table_lock();
385 /* get the requested entry */
387 assert((index >= 0) && (index < threads_table.size));
389 thread = threads_table.table[index].thread;
391 /* unlock the threads table */
393 threads_table_unlock();
399 /* threads_table_get_threads ***************************************************
401 Return the number of running threads.
403 NOTE: This function does not lock the table.
405 *******************************************************************************/
407 s4 threads_table_get_threads(void)
409 return threads_table.used;
413 /* threads_table_get_non_daemons ***********************************************
415 Return the number of non-daemon threads.
417 *******************************************************************************/
419 s4 threads_table_get_non_daemons(void)
423 /* lock the threads table */
425 threads_table_lock();
427 nondaemons = threads_table.used - threads_table.daemons;
429 /* unlock the threads table */
431 threads_table_unlock();
437 /* threads_table_first *********************************************************
439 Return the first thread of the threads table.
441 NOTE: This is always the entry with index 1 and must be the main
444 *******************************************************************************/
446 threadobject *threads_table_first(void)
448 threadobject *thread;
450 /* get the requested entry */
452 thread = threads_table_get(1);
458 /* threads_table_next **********************************************************
460 Return the next thread of the threads table relative to the passed
463 *******************************************************************************/
465 threadobject *threads_table_next(threadobject *thread)
467 threads_table_entry_t *tte;
471 index = thread->index;
473 /* get the passed entry */
475 assert((index > 0) && (index < threads_table.size));
477 tte = &(threads_table.table[index]);
479 /* get the requested entry */
481 next = threads_table_get(tte->next);
487 /* threads_table_dump *********************************************************
489 Dump the threads table for debugging purposes.
491 ******************************************************************************/
494 void threads_table_dump(void)
500 size = threads_table.size;
502 log_println("threads table ==========");
504 log_println("size: %d", size);
505 log_println("used: %d", threads_table.used);
506 log_println("daemons: %d", threads_table.daemons);
508 for (i = 0; i < size; i++) {
509 index = threads_table.table[i].next;
511 if (threads_table.table[i].thread != NULL)
512 log_println("%4d: thread=0x%08x, next=%d", i,
513 threads_table.table[i].thread->tid, (int) index);
515 log_println("%4d: free, next=%d", i, (int) index);
518 log_println("end of threads table ==========");
523 /* threads_create_thread *******************************************************
525 Creates and initializes an internal thread data-structure.
527 *******************************************************************************/
529 threadobject *threads_create_thread(void)
531 threadobject *thread;
533 /* allocate internal thread data-structure */
535 #if defined(ENABLE_GC_BOEHM)
536 thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
538 thread = NEW(threadobject);
541 #if defined(ENABLE_STATISTICS)
543 size_threadobject += sizeof(threadobject);
546 /* initialize thread data structure */
548 threads_init_threadobject(thread);
549 lock_init_execution_env(thread);
555 /* threads_thread_start_internal ***********************************************
557 Start an internal thread in the JVM. No Java thread objects exists
561 name.......UTF-8 name of the thread
562 f..........function pointer to C function to start
564 *******************************************************************************/
566 bool threads_thread_start_internal(utf *name, functionptr f)
568 threadobject *thread;
570 #if defined(WITH_CLASSPATH_GNU)
571 java_lang_VMThread *vmt;
574 /* create internal thread data-structure */
576 thread = threads_create_thread();
578 /* create the java thread object */
580 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
585 #if defined(WITH_CLASSPATH_GNU)
586 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
592 vmt->vmdata = (java_lang_Object *) thread;
595 #elif defined(WITH_CLASSPATH_CLDC1_1)
596 t->vm_thread = (java_lang_Object *) thread;
600 thread->flags = THREAD_FLAG_DAEMON;
602 /* set java.lang.Thread fields */
604 t->name = (java_lang_String *) javastring_new(name);
605 #if defined(ENABLE_JAVASE)
608 t->priority = NORM_PRIORITY;
610 /* start the thread */
612 threads_impl_thread_start(thread, f);
614 /* everything's ok */
620 /* threads_thread_start ********************************************************
622 Start a Java thread in the JVM. Only the java thread object exists
626 object.....the java thread object java.lang.Thread
628 *******************************************************************************/
630 void threads_thread_start(java_lang_Thread *object)
632 threadobject *thread;
634 /* create internal thread data-structure */
636 thread = threads_create_thread();
638 /* link the two objects together */
640 thread->object = object;
642 #if defined(ENABLE_JAVASE)
643 /* is this a daemon thread? */
645 if (object->daemon == true)
646 thread->flags |= THREAD_FLAG_DAEMON;
649 #if defined(WITH_CLASSPATH_GNU)
650 assert(object->vmThread);
651 assert(object->vmThread->vmdata == NULL);
653 object->vmThread->vmdata = (java_lang_Object *) thread;
654 #elif defined(WITH_CLASSPATH_CLDC1_1)
655 object->vm_thread = (java_lang_Object *) thread;
658 /* Start the thread. Don't pass a function pointer (NULL) since
659 we want Thread.run()V here. */
661 threads_impl_thread_start(thread, NULL);
665 /* threads_get_current_tid *****************************************************
667 Return the tid of the current thread.
672 *******************************************************************************/
674 ptrint threads_get_current_tid(void)
676 threadobject *thread;
678 thread = THREADOBJECT;
680 /* this may happen during bootstrap */
685 return (ptrint) thread->tid;
689 /* threads_thread_get_state ****************************************************
691 Returns the current state of the given thread.
693 *******************************************************************************/
695 utf *threads_thread_get_state(threadobject *thread)
699 switch (thread->state) {
700 case THREAD_STATE_NEW:
701 u = utf_new_char("NEW");
703 case THREAD_STATE_RUNNABLE:
704 u = utf_new_char("RUNNABLE");
706 case THREAD_STATE_BLOCKED:
707 u = utf_new_char("BLOCKED");
709 case THREAD_STATE_WAITING:
710 u = utf_new_char("WAITING");
712 case THREAD_STATE_TIMED_WAITING:
713 u = utf_new_char("TIMED_WAITING");
715 case THREAD_STATE_TERMINATED:
716 u = utf_new_char("TERMINATED");
719 vm_abort("threads_get_state: unknown thread state %d", thread->state);
726 /* threads_thread_is_alive *****************************************************
728 Returns if the give thread is alive.
730 *******************************************************************************/
732 bool threads_thread_is_alive(threadobject *thread)
736 switch (thread->state) {
737 case THREAD_STATE_NEW:
738 case THREAD_STATE_TERMINATED:
742 case THREAD_STATE_RUNNABLE:
743 case THREAD_STATE_BLOCKED:
744 case THREAD_STATE_WAITING:
745 case THREAD_STATE_TIMED_WAITING:
750 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
757 /* threads_dump ****************************************************************
759 Dumps info for all threads running in the JVM. This function is
760 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
762 *******************************************************************************/
764 void threads_dump(void)
766 threadobject *thread;
767 java_lang_Thread *object;
770 /* XXX we should stop the world here */
772 printf("Full thread dump CACAO "VERSION":\n");
774 /* iterate over all started threads */
776 for (thread = threads_table_first(); thread != NULL;
777 thread = threads_table_next(thread)) {
778 /* get thread object */
780 object = thread->object;
782 /* the thread may be currently in initalization, don't print it */
784 if (object != NULL) {
785 /* get thread name */
787 #if defined(ENABLE_JAVASE)
788 name = javastring_toutf((java_objectheader *) object->name, false);
789 #elif defined(ENABLE_JAVAME_CLDC1_1)
794 utf_display_printable_ascii(name);
797 if (thread->flags & THREAD_FLAG_DAEMON)
800 printf(" prio=%d", object->priority);
802 #if SIZEOF_VOID_P == 8
803 printf(" tid=0x%016lx (%ld)",
804 (ptrint) thread->tid, (ptrint) thread->tid);
806 printf(" tid=0x%08x (%d)",
807 (ptrint) thread->tid, (ptrint) thread->tid);
810 /* print thread state */
812 switch (thread->state) {
813 case THREAD_STATE_NEW:
816 case THREAD_STATE_RUNNABLE:
819 case THREAD_STATE_BLOCKED:
822 case THREAD_STATE_WAITING:
825 case THREAD_STATE_TIMED_WAITING:
826 printf(" waiting on condition");
828 case THREAD_STATE_TERMINATED:
829 printf(" terminated");
832 vm_abort("threads_dump: unknown thread state %d",
838 /* print trace of thread */
840 threads_thread_print_stacktrace(thread);
846 /* threads_thread_print_stacktrace *********************************************
848 Print the current stacktrace of the current thread.
850 *******************************************************************************/
852 void threads_thread_print_stacktrace(threadobject *thread)
855 stacktracebuffer *stb;
858 /* mark start of dump memory area */
860 dumpsize = dump_size();
862 /* create a stacktrace for the passed thread */
864 sfi = thread->_stackframeinfo;
866 stb = stacktrace_create(sfi);
868 /* print stacktrace */
871 stacktrace_print_trace_from_buffer(stb);
873 puts("\t<<No stacktrace available>>");
877 dump_release(dumpsize);
881 /* threads_print_stacktrace ****************************************************
883 Print the current stacktrace of the current thread.
885 *******************************************************************************/
887 void threads_print_stacktrace(void)
889 threadobject *thread;
891 thread = THREADOBJECT;
893 threads_thread_print_stacktrace(thread);
898 * These are local overrides for various environment variables in Emacs.
899 * Please do not remove this and leave it at the end of the file, where
900 * Emacs will automagically detect them.
901 * ---------------------------------------------------------------------
904 * indent-tabs-mode: t
908 * vim:noexpandtab:sw=4:ts=4: