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 8027 2007-06-07 10:30:33Z michi $
37 #include "mm/memory.h"
39 #include "native/jni.h"
41 #include "native/include/java_lang_Object.h"
42 #include "native/include/java_lang_String.h"
43 #include "native/include/java_lang_Thread.h"
45 #if defined(WITH_CLASSPATH_GNU)
46 # include "native/include/java_lang_VMThread.h"
49 #include "threads/critical.h"
50 #include "threads/lock-common.h"
51 #include "threads/threads-common.h"
53 #include "toolbox/list.h"
55 #include "vm/builtin.h"
56 #include "vm/stringlocal.h"
59 #include "vm/jit/stacktrace.h"
61 #include "vmcore/class.h"
63 #if defined(ENABLE_STATISTICS)
64 # include "vmcore/options.h"
65 # include "vmcore/statistics.h"
68 #include "vmcore/utf8.h"
71 /* global variables ***********************************************************/
73 /* global threads list */
74 static list_t *list_threads;
76 /* global threads free-list */
77 static list_t *list_threads_free;
79 #if defined(__LINUX__)
80 /* XXX Remove for exact-GC. */
81 bool threads_pthreads_implementation_nptl;
85 /* threads_preinit *************************************************************
87 Do some early initialization of stuff required.
89 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
90 is called AFTER this function!
92 *******************************************************************************/
94 void threads_preinit(void)
96 threadobject *mainthread;
97 #if defined(__LINUX__)
102 #if defined(__LINUX__)
103 /* XXX Remove for exact-GC. */
105 /* On Linux we need to check the pthread implementation. */
107 /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
108 /* If the glibc is a pre-2.3.2 version, we fall back to
111 # if defined(_CS_GNU_LIBPTHREAD_VERSION)
112 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
114 pathbuf = MNEW(char, len);
116 (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
118 if (strstr(pathbuf, "NPTL") != NULL)
119 threads_pthreads_implementation_nptl = true;
121 threads_pthreads_implementation_nptl = false;
123 threads_pthreads_implementation_nptl = false;
127 /* initialize the threads lists */
129 list_threads = list_create(OFFSET(threadobject, linkage));
130 list_threads_free = list_create(OFFSET(threadobject, linkage));
132 /* Initialize the threads implementation (sets the thinlock on the
135 threads_impl_preinit();
137 /* create internal thread data-structure for the main thread */
139 mainthread = threads_thread_new();
141 /* thread is a Java thread and running */
143 mainthread->flags = THREAD_FLAG_JAVA;
144 mainthread->state = THREAD_STATE_RUNNABLE;
146 /* store the internal thread data-structure in the TSD */
148 threads_set_current_threadobject(mainthread);
150 /* initialize locking subsystems */
154 /* initialize the critical section */
160 /* threads_list_first **********************************************************
162 Return the first entry in the threads list.
164 NOTE: This function does not lock the lists.
166 *******************************************************************************/
168 threadobject *threads_list_first(void)
172 t = list_first_unsynced(list_threads);
178 /* threads_list_next ***********************************************************
180 Return the next entry in the threads list.
182 NOTE: This function does not lock the lists.
184 *******************************************************************************/
186 threadobject *threads_list_next(threadobject *t)
190 next = list_next_unsynced(list_threads, t);
196 /* threads_list_get_non_daemons ************************************************
198 Return the number of non-daemon threads.
200 NOTE: This function does a linear-search over the threads list,
201 because it's only used for joining the threads.
203 *******************************************************************************/
205 s4 threads_list_get_non_daemons(void)
210 /* lock the threads lists */
216 for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
217 if (!(t->flags & THREAD_FLAG_DAEMON))
221 /* unlock the threads lists */
223 threads_list_unlock();
229 /* threads_thread_new **********************************************************
231 Allocates and initializes an internal thread data-structure and
232 adds it to the threads list.
234 *******************************************************************************/
236 threadobject *threads_thread_new(void)
240 /* lock the threads-lists */
244 /* try to get a thread from the free-list */
246 t = list_first_unsynced(list_threads_free);
248 /* is a free thread available? */
251 /* yes, remove it from the free list */
253 list_remove_unsynced(list_threads_free, t);
256 /* no, allocate a new one */
258 #if defined(ENABLE_GC_BOEHM)
259 t = GCNEW_UNCOLLECTABLE(threadobject, 1);
261 t = NEW(threadobject);
264 #if defined(ENABLE_STATISTICS)
266 size_threadobject += sizeof(threadobject);
271 MZERO(t, threadobject, 1);
273 /* set the threads-index */
275 t->index = list_threads->size + 1;
278 /* pre-compute the thinlock-word */
280 assert(t->index != 0);
282 t->thinlock = lock_pre_compute_thinlock(t->index);
284 t->state = THREAD_STATE_NEW;
286 #if defined(ENABLE_GC_CACAO)
287 t->flags |= THREAD_FLAG_IN_NATIVE;
290 /* initialize the implementation-specific bits */
292 threads_impl_thread_new(t);
294 /* add the thread to the threads-list */
296 list_add_last_unsynced(list_threads, t);
298 /* unlock the threads-lists */
300 threads_list_unlock();
306 /* threads_thread_free *********************************************************
308 Frees an internal thread data-structure by removing it from the
309 threads-list and adding it to the free-list.
311 NOTE: The data-structure is NOT freed, the pointer keeps valid!
313 *******************************************************************************/
315 void threads_thread_free(threadobject *t)
319 /* lock the threads-lists */
323 /* cleanup the implementation-specific bits */
325 threads_impl_thread_free(t);
327 /* remove the thread from the threads-list */
329 list_remove_unsynced(list_threads, t);
331 /* Clear memory, but keep the thread-index. */
332 /* ATTENTION: Do this after list_remove, otherwise the linkage
333 pointers are invalid. */
337 MZERO(t, threadobject, 1);
341 /* add the thread to the free list */
343 list_add_first_unsynced(list_threads_free, t);
345 /* unlock the threads-lists */
347 threads_list_unlock();
351 /* threads_thread_start_internal ***********************************************
353 Start an internal thread in the JVM. No Java thread objects exists
357 name.......UTF-8 name of the thread
358 f..........function pointer to C function to start
360 *******************************************************************************/
362 bool threads_thread_start_internal(utf *name, functionptr f)
365 java_lang_Thread *object;
366 #if defined(WITH_CLASSPATH_GNU)
367 java_lang_VMThread *vmt;
370 /* Enter the join-mutex, so if the main-thread is currently
371 waiting to join all threads, the number of non-daemon threads
374 threads_mutex_join_lock();
376 /* create internal thread data-structure */
378 t = threads_thread_new();
380 t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
382 /* The thread is flagged as (non-)daemon thread, we can leave the
385 threads_mutex_join_unlock();
387 /* create the java thread object */
389 object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
391 /* XXX memory leak!!! */
395 #if defined(WITH_CLASSPATH_GNU)
396 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
398 /* XXX memory leak!!! */
402 vmt->thread = object;
403 vmt->vmdata = (java_lang_Object *) t;
405 object->vmThread = vmt;
406 #elif defined(WITH_CLASSPATH_CLDC1_1)
407 object->vm_thread = (java_lang_Object *) t;
410 #if defined(ENABLE_GC_CACAO)
411 /* register reference to java.lang.Thread with the GC */
413 gc_reference_register(&(t->object));
418 /* set java.lang.Thread fields */
420 #if defined(WITH_CLASSPATH_GNU)
421 object->name = (java_lang_String *) javastring_new(name);
422 #elif defined(WITH_CLASSPATH_CLDC1_1)
423 /* FIXME: In cldc the name is a char[] */
424 /* object->name = (java_chararray *) javastring_new(name); */
428 #if defined(ENABLE_JAVASE)
429 object->daemon = true;
432 object->priority = NORM_PRIORITY;
434 /* start the thread */
436 threads_impl_thread_start(t, f);
438 /* everything's ok */
444 /* threads_thread_start ********************************************************
446 Start a Java thread in the JVM. Only the java thread object exists
450 object.....the java thread object java.lang.Thread
452 *******************************************************************************/
454 void threads_thread_start(java_lang_Thread *object)
456 threadobject *thread;
458 /* Enter the join-mutex, so if the main-thread is currently
459 waiting to join all threads, the number of non-daemon threads
462 threads_mutex_join_lock();
464 /* create internal thread data-structure */
466 thread = threads_thread_new();
468 /* this is a normal Java thread */
470 thread->flags |= THREAD_FLAG_JAVA;
472 #if defined(ENABLE_JAVASE)
473 /* is this a daemon thread? */
475 if (object->daemon == true)
476 thread->flags |= THREAD_FLAG_DAEMON;
479 /* The thread is flagged and (non-)daemon thread, we can leave the
482 threads_mutex_join_unlock();
484 #if defined(ENABLE_GC_CACAO)
485 /* register reference to java.lang.Thread with the GC */
487 gc_reference_register(&(thread->object));
490 /* link the two objects together */
492 thread->object = object;
494 #if defined(WITH_CLASSPATH_GNU)
495 assert(object->vmThread);
496 assert(object->vmThread->vmdata == NULL);
498 object->vmThread->vmdata = (java_lang_Object *) thread;
499 #elif defined(WITH_CLASSPATH_CLDC1_1)
500 object->vm_thread = (java_lang_Object *) thread;
503 /* Start the thread. Don't pass a function pointer (NULL) since
504 we want Thread.run()V here. */
506 threads_impl_thread_start(thread, NULL);
510 /* threads_thread_print_info ***************************************************
512 Print information of the passed thread.
514 *******************************************************************************/
516 void threads_thread_print_info(threadobject *t)
518 java_lang_Thread *object;
521 assert(t->state != THREAD_STATE_NEW);
523 /* the thread may be currently in initalization, don't print it */
527 if (object != NULL) {
528 /* get thread name */
530 #if defined(ENABLE_JAVASE)
531 name = javastring_toutf((java_objectheader *) object->name, false);
532 #elif defined(ENABLE_JAVAME_CLDC1_1)
533 /* FIXME: In cldc the name is a char[] */
534 /* name = object->name; */
539 utf_display_printable_ascii(name);
542 if (t->flags & THREAD_FLAG_DAEMON)
545 printf(" prio=%d", object->priority);
547 #if SIZEOF_VOID_P == 8
548 printf(" t=0x%016lx tid=0x%016lx (%ld)",
549 (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
551 printf(" t=0x%08x tid=0x%08x (%d)",
552 (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
555 printf(" index=%d", t->index);
557 /* print 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_thread_print_info: unknown thread state %d",
586 /* threads_get_current_tid *****************************************************
588 Return the tid of the current thread.
593 *******************************************************************************/
595 ptrint threads_get_current_tid(void)
597 threadobject *thread;
599 thread = THREADOBJECT;
601 /* this may happen during bootstrap */
606 return (ptrint) thread->tid;
610 /* threads_thread_state_runnable ***********************************************
612 Set the current state of the given thread to THREAD_STATE_RUNNABLE.
614 *******************************************************************************/
616 void threads_thread_state_runnable(threadobject *t)
618 /* set the state inside the lock */
622 t->state = THREAD_STATE_RUNNABLE;
624 threads_list_unlock();
628 /* threads_thread_state_waiting ************************************************
630 Set the current state of the given thread to THREAD_STATE_WAITING.
632 *******************************************************************************/
634 void threads_thread_state_waiting(threadobject *t)
636 /* set the state in the lock */
640 t->state = THREAD_STATE_WAITING;
642 threads_list_unlock();
646 /* threads_thread_state_timed_waiting ******************************************
648 Set the current state of the given thread to
649 THREAD_STATE_TIMED_WAITING.
651 *******************************************************************************/
653 void threads_thread_state_timed_waiting(threadobject *t)
655 /* set the state in the lock */
659 t->state = THREAD_STATE_TIMED_WAITING;
661 threads_list_unlock();
665 /* threads_thread_state_terminated *********************************************
667 Set the current state of the given thread to
668 THREAD_STATE_TERMINATED.
670 *******************************************************************************/
672 void threads_thread_state_terminated(threadobject *t)
674 /* set the state in the lock */
678 t->state = THREAD_STATE_TERMINATED;
680 threads_list_unlock();
684 /* threads_thread_get_state ****************************************************
686 Returns the current state of the given thread.
688 *******************************************************************************/
690 utf *threads_thread_get_state(threadobject *t)
695 case THREAD_STATE_NEW:
696 u = utf_new_char("NEW");
698 case THREAD_STATE_RUNNABLE:
699 u = utf_new_char("RUNNABLE");
701 case THREAD_STATE_BLOCKED:
702 u = utf_new_char("BLOCKED");
704 case THREAD_STATE_WAITING:
705 u = utf_new_char("WAITING");
707 case THREAD_STATE_TIMED_WAITING:
708 u = utf_new_char("TIMED_WAITING");
710 case THREAD_STATE_TERMINATED:
711 u = utf_new_char("TERMINATED");
714 vm_abort("threads_get_state: unknown thread state %d", t->state);
716 /* keep compiler happy */
725 /* threads_thread_is_alive *****************************************************
727 Returns if the give thread is alive.
729 *******************************************************************************/
731 bool threads_thread_is_alive(threadobject *thread)
735 switch (thread->state) {
736 case THREAD_STATE_NEW:
737 case THREAD_STATE_TERMINATED:
741 case THREAD_STATE_RUNNABLE:
742 case THREAD_STATE_BLOCKED:
743 case THREAD_STATE_WAITING:
744 case THREAD_STATE_TIMED_WAITING:
749 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
751 /* keep compiler happy */
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)
771 /* XXX we should stop the world here */
773 /* lock the threads lists */
777 printf("Full thread dump CACAO "VERSION":\n");
779 /* iterate over all started threads */
781 for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
782 /* print thread info */
785 threads_thread_print_info(t);
788 /* print trace of thread */
790 threads_thread_print_stacktrace(t);
793 /* unlock the threads lists */
795 threads_list_unlock();
799 /* threads_thread_print_stacktrace *********************************************
801 Print the current stacktrace of the current thread.
803 *******************************************************************************/
805 void threads_thread_print_stacktrace(threadobject *thread)
808 stacktracebuffer *stb;
811 /* mark start of dump memory area */
813 dumpsize = dump_size();
815 /* create a stacktrace for the passed thread */
817 sfi = thread->_stackframeinfo;
819 stb = stacktrace_create(sfi);
821 /* print stacktrace */
824 stacktrace_print_trace_from_buffer(stb);
826 puts("\t<<No stacktrace available>>");
830 dump_release(dumpsize);
834 /* threads_print_stacktrace ****************************************************
836 Print the current stacktrace of the current thread.
838 *******************************************************************************/
840 void threads_print_stacktrace(void)
842 threadobject *thread;
844 thread = THREADOBJECT;
846 threads_thread_print_stacktrace(thread);
851 * These are local overrides for various environment variables in Emacs.
852 * Please do not remove this and leave it at the end of the file, where
853 * Emacs will automagically detect them.
854 * ---------------------------------------------------------------------
857 * indent-tabs-mode: t
861 * vim:noexpandtab:sw=4:ts=4: