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 7830 2007-04-26 11:14:39Z 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(void);
76 #if !defined(NDEBUG) && 0
77 static void threads_table_dump(FILE *file);
81 /* threads_preinit *************************************************************
83 Do some early initialization of stuff required.
85 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
86 is called AFTER this function!
88 *******************************************************************************/
90 void threads_preinit(void)
92 /* initialize the threads implementation */
94 threads_impl_preinit();
96 /* initialize the threads table */
100 /* initialize subsystems */
108 /* threads_table_init **********************************************************
110 Initialize the global threads table.
112 *******************************************************************************/
114 #define THREADS_INITIAL_TABLE_SIZE 8
116 static void threads_table_init(void)
121 size = THREADS_INITIAL_TABLE_SIZE;
123 threads_table.table = MNEW(threads_table_entry_t, size);
124 threads_table.size = size;
126 /* link the entries in a freelist */
128 for (i = 0; i < size; i++) {
129 threads_table.table[i].nextfree = i + 1;
132 /* terminate the freelist */
134 threads_table.table[size - 1].nextfree = 0; /* index 0 is never free */
138 /* threads_table_add ***********************************************************
140 Add a thread to the global threads table. The index is entered in the
141 threadobject. The thinlock value for the thread is pre-computed.
144 thread............the thread to add
147 The table index for the newly added thread. This value has also been
148 entered in the threadobject.
151 The caller must hold the threadlistlock!
153 *******************************************************************************/
155 s4 threads_table_add(threadobject *thread)
162 /* table[0] serves as the head of the freelist */
164 index = threads_table.table[0].nextfree;
166 /* if we got a free index, use it */
170 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
171 threads_table.table[index].thread = thread;
173 thread->index = index;
174 thread->thinlock = lock_pre_compute_thinlock(index);
179 /* we must grow the table */
181 oldsize = threads_table.size;
182 newsize = oldsize * 2;
184 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
186 threads_table.size = newsize;
188 /* link the new entries to a free list */
190 for (i = oldsize; i < newsize; i++) {
191 threads_table.table[i].nextfree = i + 1;
194 /* terminate the freelist */
196 threads_table.table[newsize - 1].nextfree = 0; /* index 0 is never free */
198 /* use the first of the new entries */
205 /* threads_table_remove *******************************************************
207 Remove a thread from the global threads table.
210 thread............the thread to remove
213 The caller must hold the threadlistlock!
215 ******************************************************************************/
217 void threads_table_remove(threadobject *thread)
221 index = thread->index;
223 /* put the index into the freelist */
225 threads_table.table[index] = threads_table.table[0];
226 threads_table.table[0].nextfree = index;
228 /* delete the index in the threadobject to discover bugs */
235 /* threads_table_dump *********************************************************
237 Dump the threads table for debugging purposes.
240 file..............stream to write to
242 ******************************************************************************/
244 #if !defined(NDEBUG) && 0
245 static void threads_table_dump(FILE *file)
251 pthread_mutex_lock(&threadlistlock);
253 size = threads_table.size;
255 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
257 for (i=0; i<size; ++i) {
258 index = threads_table.table[i].nextfree;
260 fprintf(file, "%4d: ", i);
263 fprintf(file, "free, nextfree = %d\n", (int) index);
266 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
270 fprintf(file, "======== END OF THREADS TABLE ========\n");
272 pthread_mutex_unlock(&threadlistlock);
277 /* threads_create_thread *******************************************************
279 Creates and initializes an internal thread data-structure.
281 *******************************************************************************/
283 threadobject *threads_create_thread(void)
285 threadobject *thread;
287 /* allocate internal thread data-structure */
289 #if defined(ENABLE_GC_BOEHM)
290 thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
292 thread = NEW(threadobject);
295 #if defined(ENABLE_STATISTICS)
297 size_threadobject += sizeof(threadobject);
300 /* initialize thread data structure */
302 threads_init_threadobject(thread);
303 lock_init_execution_env(thread);
309 /* threads_thread_create_internal **********************************************
311 Creates an internal thread data-structure with the given name, plus
312 necessary Java objects for the VM (e.g. finalizer-thread,
315 *******************************************************************************/
317 threadobject *threads_thread_create_internal(utf *name)
319 threadobject *thread;
321 #if defined(WITH_CLASSPATH_GNU)
322 java_lang_VMThread *vmt;
325 /* create internal thread data-structure */
327 thread = threads_create_thread();
329 /* create the java thread object */
331 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
336 #if defined(WITH_CLASSPATH_GNU)
337 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
343 vmt->vmdata = (java_lang_Object *) thread;
346 #elif defined(WITH_CLASSPATH_CLDC1_1)
347 t->vm_thread = (java_lang_Object *) thread;
351 thread->flags = THREAD_FLAG_DAEMON;
353 /* set java.lang.Thread fields */
355 t->name = (java_lang_String *) javastring_new(name);
356 #if defined(ENABLE_JAVASE)
359 t->priority = NORM_PRIORITY;
361 /* return the thread data-structure */
367 /* threads_start_javathread ****************************************************
369 Start a thread in the JVM. Only the java thread object exists so far.
372 object.....the java thread object java.lang.Thread
374 *******************************************************************************/
376 void threads_start_javathread(java_lang_Thread *object)
378 threadobject *thread;
380 /* create internal thread data-structure */
382 thread = threads_create_thread();
384 /* link the two objects together */
386 thread->object = object;
388 #if defined(ENABLE_JAVASE)
389 /* is this a daemon thread? */
391 if (object->daemon == true)
392 thread->flags |= THREAD_FLAG_DAEMON;
395 #if defined(WITH_CLASSPATH_GNU)
396 assert(object->vmThread);
397 assert(object->vmThread->vmdata == NULL);
399 object->vmThread->vmdata = (java_lang_Object *) thread;
400 #elif defined(WITH_CLASSPATH_CLDC1_1)
401 object->vm_thread = (java_lang_Object *) thread;
404 /* Actually start the thread. Don't pass a function pointer
405 (NULL) since we want Thread.run()V here. */
407 threads_start_thread(thread, NULL);
411 /* threads_get_current_tid *****************************************************
413 Return the tid of the current thread.
418 *******************************************************************************/
420 ptrint threads_get_current_tid(void)
422 threadobject *thread;
424 thread = THREADOBJECT;
426 /* this may happen during bootstrap */
431 return (ptrint) thread->tid;
435 /* threads_thread_get_state ****************************************************
437 Returns the current state of the given thread.
439 *******************************************************************************/
441 utf *threads_thread_get_state(threadobject *thread)
445 switch (thread->state) {
446 case THREAD_STATE_NEW:
447 u = utf_new_char("NEW");
449 case THREAD_STATE_RUNNABLE:
450 u = utf_new_char("RUNNABLE");
452 case THREAD_STATE_BLOCKED:
453 u = utf_new_char("BLOCKED");
455 case THREAD_STATE_WAITING:
456 u = utf_new_char("WAITING");
458 case THREAD_STATE_TIMED_WAITING:
459 u = utf_new_char("TIMED_WAITING");
461 case THREAD_STATE_TERMINATED:
462 u = utf_new_char("TERMINATED");
465 vm_abort("threads_get_state: unknown thread state %d", thread->state);
472 /* threads_thread_is_alive *****************************************************
474 Returns if the give thread is alive.
476 *******************************************************************************/
478 bool threads_thread_is_alive(threadobject *thread)
482 switch (thread->state) {
483 case THREAD_STATE_NEW:
484 case THREAD_STATE_TERMINATED:
488 case THREAD_STATE_RUNNABLE:
489 case THREAD_STATE_BLOCKED:
490 case THREAD_STATE_WAITING:
491 case THREAD_STATE_TIMED_WAITING:
496 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
503 /* threads_dump ****************************************************************
505 Dumps info for all threads running in the JVM. This function is
506 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
508 *******************************************************************************/
510 void threads_dump(void)
512 threadobject *thread;
516 /* XXX we should stop the world here */
518 printf("Full thread dump CACAO "VERSION":\n");
520 /* iterate over all started threads */
522 thread = mainthreadobj;
525 /* get thread object */
529 /* the thread may be currently in initalization, don't print it */
532 /* get thread name */
534 #if defined(ENABLE_JAVASE)
535 name = javastring_toutf((java_objectheader *) t->name, false);
536 #elif defined(ENABLE_JAVAME_CLDC1_1)
541 utf_display_printable_ascii(name);
544 if (thread->flags & THREAD_FLAG_DAEMON)
547 printf(" prio=%d", t->priority);
549 #if SIZEOF_VOID_P == 8
550 printf(" tid=0x%016lx (%ld)",
551 (ptrint) thread->tid, (ptrint) thread->tid);
553 printf(" tid=0x%08x (%d)",
554 (ptrint) thread->tid, (ptrint) thread->tid);
557 /* print thread state */
559 switch (thread->state) {
560 case THREAD_STATE_NEW:
563 case THREAD_STATE_RUNNABLE:
566 case THREAD_STATE_BLOCKED:
569 case THREAD_STATE_WAITING:
572 case THREAD_STATE_TIMED_WAITING:
573 printf(" waiting on condition");
575 case THREAD_STATE_TERMINATED:
576 printf(" terminated");
579 vm_abort("threads_dump: unknown thread state %d",
585 /* print trace of thread */
587 threads_thread_print_stacktrace(thread);
590 thread = thread->next;
591 } while ((thread != NULL) && (thread != mainthreadobj));
595 /* threads_thread_print_stacktrace *********************************************
597 Print the current stacktrace of the current thread.
599 *******************************************************************************/
601 void threads_thread_print_stacktrace(threadobject *thread)
604 stacktracebuffer *stb;
607 /* mark start of dump memory area */
609 dumpsize = dump_size();
611 /* create a stacktrace for the passed thread */
613 sfi = thread->_stackframeinfo;
615 stb = stacktrace_create(sfi);
617 /* print stacktrace */
620 stacktrace_print_trace_from_buffer(stb);
622 puts("\t<<No stacktrace available>>");
626 dump_release(dumpsize);
630 /* threads_print_stacktrace ****************************************************
632 Print the current stacktrace of the current thread.
634 *******************************************************************************/
636 void threads_print_stacktrace(void)
638 threadobject *thread;
640 thread = THREADOBJECT;
642 threads_thread_print_stacktrace(thread);
647 * These are local overrides for various environment variables in Emacs.
648 * Please do not remove this and leave it at the end of the file, where
649 * Emacs will automagically detect them.
650 * ---------------------------------------------------------------------
653 * indent-tabs-mode: t
657 * vim:noexpandtab:sw=4:ts=4: