1 /* src/threads/thread.c - machine independent thread functions
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "mm/memory.h"
36 #include "native/jni.h"
37 #include "native/llni.h"
38 #include "native/native.h"
40 #include "native/include/java_lang_Object.h"
41 #include "native/include/java_lang_String.h"
42 #include "native/include/java_lang_Thread.h"
44 #if defined(ENABLE_JAVASE)
45 # include "native/include/java_lang_ThreadGroup.h"
48 #if defined(WITH_CLASSPATH_GNU)
49 # include "native/include/java_lang_VMThread.h"
52 #include "threads/critical.h"
53 #include "threads/lock-common.h"
54 #include "threads/threadlist.h"
55 #include "threads/thread.h"
57 #include "vm/builtin.h"
58 #include "vm/exceptions.h"
59 #include "vm/stringlocal.h"
62 #include "vm/jit/stacktrace.h"
64 #include "vmcore/class.h"
65 #include "vmcore/method.h"
66 #include "vmcore/options.h"
68 #if defined(ENABLE_STATISTICS)
69 # include "vmcore/statistics.h"
72 #include "vmcore/utf8.h"
75 /* global variables ***********************************************************/
77 static methodinfo *thread_method_init;
78 static java_handle_t *threadgroup_system;
79 static java_handle_t *threadgroup_main;
81 #if defined(__LINUX__)
82 /* XXX Remove for exact-GC. */
83 bool threads_pthreads_implementation_nptl;
87 /* static functions ***********************************************************/
89 static void thread_create_initial_threadgroups(void);
90 static void thread_create_initial_thread(void);
91 static threadobject *thread_new(void);
94 /* threads_preinit *************************************************************
96 Do some early initialization of stuff required.
98 *******************************************************************************/
100 void threads_preinit(void)
102 threadobject *mainthread;
103 #if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
108 TRACESUBSYSTEMINITIALIZATION("threads_preinit");
110 #if defined(__LINUX__)
111 /* XXX Remove for exact-GC. */
113 /* On Linux we need to check the pthread implementation. */
115 /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
116 /* If the glibc is a pre-2.3.2 version, we fall back to
119 # if defined(_CS_GNU_LIBPTHREAD_VERSION)
120 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
122 /* Some systems return as length 0 (maybe cross-compilation
123 related). In this case we also fall back to linuxthreads. */
126 pathbuf = MNEW(char, len);
128 (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
130 if (strstr(pathbuf, "NPTL") != NULL)
131 threads_pthreads_implementation_nptl = true;
133 threads_pthreads_implementation_nptl = false;
136 threads_pthreads_implementation_nptl = false;
138 threads_pthreads_implementation_nptl = false;
142 /* Initialize the threads implementation (sets the thinlock on the
145 threads_impl_preinit();
147 /* Create internal thread data-structure for the main thread. */
149 mainthread = thread_new();
151 /* thread is a Java thread and running */
153 mainthread->flags |= THREAD_FLAG_JAVA;
154 mainthread->state = THREAD_STATE_RUNNABLE;
156 /* Store the internal thread data-structure in the TSD. */
158 thread_set_current(mainthread);
162 /* threads_init ****************************************************************
164 Initialize the main thread.
166 *******************************************************************************/
168 void threads_init(void)
170 TRACESUBSYSTEMINITIALIZATION("threads_init");
172 /* Create the system and main thread groups. */
174 thread_create_initial_threadgroups();
176 /* Cache the java.lang.Thread initialization method. */
178 #if defined(WITH_CLASSPATH_GNU)
181 class_resolveclassmethod(class_java_lang_Thread,
183 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
184 class_java_lang_Thread,
187 #elif defined(WITH_CLASSPATH_SUN)
190 class_resolveclassmethod(class_java_lang_Thread,
192 utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"),
193 class_java_lang_Thread,
196 #elif defined(WITH_CLASSPATH_CLDC1_1)
199 class_resolveclassmethod(class_java_lang_Thread,
201 utf_java_lang_String__void,
202 class_java_lang_Thread,
206 # error unknown classpath configuration
209 if (thread_method_init == NULL)
210 vm_abort("threads_init: failed to resolve thread init method");
212 thread_create_initial_thread();
216 /* thread_create_object ********************************************************
218 Create a Java thread object for the given thread data-structure,
219 initializes it and adds the thread to the threadgroup.
224 name .... thread name
225 group ... threadgroup
229 *******************************************************************************/
231 static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
234 java_lang_Thread *to;
236 #if defined(WITH_CLASSPATH_GNU)
237 java_lang_VMThread *vmto;
243 /* Create a java.lang.Thread Java object. */
245 o = builtin_new(class_java_lang_Thread);
250 to = (java_lang_Thread *) o;
252 /* Set the Java object in the thread data-structure. This
253 indicates that the thread is attached to the VM. */
255 threads_thread_set_object(t, (java_handle_t *) to);
257 #if defined(WITH_CLASSPATH_GNU)
259 /* Create a java.lang.VMThread Java object. */
261 vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
266 /* Set the Java thread object in the Java VM-thread object. */
268 LLNI_field_set_ref(vmto, thread, to);
270 /* Set the thread data-structure in the Java VM-thread object. */
272 LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
275 java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
277 isdaemon = thread_is_daemon(t);
279 (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
282 if (exceptions_get_exception())
285 /* Set the threadgroup in the Java thread object. */
287 LLNI_field_set_ref(to, group, (java_lang_ThreadGroup *) group);
289 /* Add thread to the threadgroup. */
291 LLNI_class_get(group, c);
293 m = class_resolveclassmethod(c,
295 utf_java_lang_Thread__V,
296 class_java_lang_ThreadGroup,
302 (void) vm_call_method(m, group, to);
304 if (exceptions_get_exception())
307 #elif defined(WITH_CLASSPATH_SUN)
309 /* OpenJDK's java.lang.Thread does not have a VMThread field in
310 the class. Nothing to do here. */
312 /* Set the priority. java.lang.Thread.<init> requires it because
313 it sets the priority of the current thread to the parent's one
314 (which is the current thread in this case). */
316 LLNI_field_set_val(to, priority, NORM_PRIORITY);
319 java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
321 (void) vm_call_method(thread_method_init, o, group, name);
323 if (exceptions_get_exception())
326 #elif defined(WITH_CLASSPATH_CLDC1_1)
328 /* Set the thread data-structure in the Java thread object. */
330 LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
332 /* Call: public Thread(Ljava/lang/String;)V */
334 (void) vm_call_method(thread_method_init, o, name);
336 if (exceptions_get_exception())
340 # error unknown classpath configuration
347 /* thread_create_initial_threadgroups ******************************************
349 Create the initial threadgroups.
352 Create the main threadgroup only and set the system
353 threadgroup to the main threadgroup.
356 Create the system and main threadgroup.
359 This function is a no-op.
361 *******************************************************************************/
363 static void thread_create_initial_threadgroups(void)
365 #if defined(ENABLE_JAVASE)
366 # if defined(WITH_CLASSPATH_GNU)
368 /* Allocate and initialize the main thread group. */
370 threadgroup_main = native_new_and_init(class_java_lang_ThreadGroup);
372 if (threadgroup_main == NULL)
373 vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
375 /* Use the same threadgroup for system as for main. */
377 threadgroup_system = threadgroup_main;
379 # elif defined(WITH_CLASSPATH_SUN)
384 /* Allocate and initialize the system thread group. */
386 threadgroup_system = native_new_and_init(class_java_lang_ThreadGroup);
388 if (threadgroup_system == NULL)
389 vm_abort("thread_create_initial_threadgroups: failed to allocate system threadgroup");
391 /* Allocate and initialize the main thread group. */
393 threadgroup_main = builtin_new(class_java_lang_ThreadGroup);
395 if (threadgroup_main == NULL)
396 vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
398 name = javastring_new(utf_main);
400 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
402 utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V,
403 class_java_lang_ThreadGroup,
407 vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
409 (void) vm_call_method(m, threadgroup_main, threadgroup_system, name);
411 if (exceptions_get_exception())
412 vm_abort("thread_create_initial_threadgroups: exception while initializing main threadgroup");
415 # error unknown classpath configuration
421 /* thread_create_initial_thread ***********************************************
423 Create the initial thread: main
425 *******************************************************************************/
427 static void thread_create_initial_thread(void)
432 /* Get the main-thread (NOTE: The main thread is always the first
433 thread in the list). */
435 t = threadlist_first();
437 /* The thread name. */
439 name = javastring_new(utf_main);
441 #if defined(ENABLE_INTRP)
442 /* create interpreter stack */
445 MSET(intrp_main_stack, 0, u1, opt_stacksize);
446 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
450 /* Create the Java thread object. */
452 if (!thread_create_object(t, name, threadgroup_main))
453 vm_abort("thread_create_initial_thread: failed to create Java object");
455 /* Initialize the implementation specific bits. */
459 DEBUGTHREADS("starting (main)", t);
463 /* thread_new ******************************************************************
465 Allocates and initializes an internal thread data-structure and
466 adds it to the threads list.
468 *******************************************************************************/
470 static threadobject *thread_new(void)
475 /* Lock the thread lists */
479 index = threadlist_get_free_index();
481 /* Allocate a thread data structure. */
483 /* First, try to get one from the free-list. */
485 t = threadlist_free_first();
488 /* Remove from free list. */
490 threadlist_free_remove(t);
492 /* Equivalent of MZERO on the else path */
494 threads_impl_thread_clear(t);
497 #if defined(ENABLE_GC_BOEHM)
498 t = GCNEW_UNCOLLECTABLE(threadobject, 1);
500 t = NEW(threadobject);
503 #if defined(ENABLE_STATISTICS)
505 size_threadobject += sizeof(threadobject);
510 MZERO(t, threadobject, 1);
512 #if defined(ENABLE_GC_CACAO)
513 /* Register reference to java.lang.Thread with the GC. */
514 /* FIXME is it ok to do this only once? */
516 gc_reference_register(&(t->object), GC_REFTYPE_THREADOBJECT);
517 gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
520 /* Initialize the implementation-specific bits. */
522 threads_impl_thread_init(t);
525 /* Pre-compute the thinlock-word. */
530 t->thinlock = lock_pre_compute_thinlock(t->index);
532 t->state = THREAD_STATE_NEW;
534 #if defined(ENABLE_GC_CACAO)
535 t->flags |= THREAD_FLAG_IN_NATIVE;
538 /* Initialize the implementation-specific bits. */
540 threads_impl_thread_reuse(t);
542 /* Add the thread to the thread list. */
546 /* Unlock the thread lists. */
554 /* thread_free *****************************************************************
556 Remove the thread from the threads-list and free the internal
557 thread data structure. The thread index is added to the
558 thread-index free-list.
561 t ... thread data structure
563 *******************************************************************************/
565 void thread_free(threadobject *t)
567 /* Lock the thread lists. */
571 /* Remove the thread from the thread-list. */
573 threadlist_remove(t);
575 /* Add the thread index to the free list. */
577 threadlist_index_add(t->index);
579 /* Set the reference to the Java object to NULL. */
581 threads_thread_set_object(t, NULL);
583 /* Add the thread data structure to the free list. */
585 threadlist_free_add(t);
587 /* Unlock the thread lists. */
593 /* threads_thread_start_internal ***********************************************
595 Start an internal thread in the JVM. No Java thread objects exists
599 name.......UTF-8 name of the thread
600 f..........function pointer to C function to start
602 *******************************************************************************/
604 bool threads_thread_start_internal(utf *name, functionptr f)
608 /* Enter the join-mutex, so if the main-thread is currently
609 waiting to join all threads, the number of non-daemon threads
612 threads_mutex_join_lock();
614 /* Create internal thread data-structure. */
618 t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
620 /* The thread is flagged as (non-)daemon thread, we can leave the
623 threads_mutex_join_unlock();
625 /* Create the Java thread object. */
627 if (!thread_create_object(t, javastring_new(name), threadgroup_system))
630 /* Start the thread. */
632 threads_impl_thread_start(t, f);
634 /* everything's ok */
640 /* threads_thread_start ********************************************************
642 Start a Java thread in the JVM. Only the java thread object exists
646 object.....the java thread object java.lang.Thread
648 *******************************************************************************/
650 void threads_thread_start(java_handle_t *object)
652 java_lang_Thread *to;
654 #if defined(WITH_CLASSPATH_GNU)
655 java_lang_VMThread *vmto;
658 to = (java_lang_Thread *) object;
660 /* Enter the join-mutex, so if the main-thread is currently
661 waiting to join all threads, the number of non-daemon threads
664 threads_mutex_join_lock();
666 /* Create internal thread data-structure. */
670 /* this is a normal Java thread */
672 t->flags |= THREAD_FLAG_JAVA;
674 #if defined(ENABLE_JAVASE)
675 /* Is this a daemon thread? */
677 if (LLNI_field_direct(to, daemon) == true)
678 t->flags |= THREAD_FLAG_DAEMON;
681 /* The thread is flagged and (non-)daemon thread, we can leave the
684 threads_mutex_join_unlock();
686 /* Link the two objects together. */
688 threads_thread_set_object(t, object);
690 #if defined(WITH_CLASSPATH_GNU)
692 /* Get the java.lang.VMThread object and do some sanity checks. */
694 LLNI_field_get_ref(to, vmThread, vmto);
697 assert(LLNI_field_direct(vmto, vmdata) == NULL);
699 LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
701 #elif defined(WITH_CLASSPATH_SUN)
705 #elif defined(WITH_CLASSPATH_CLDC1_1)
707 LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
710 # error unknown classpath configuration
713 /* Start the thread. Don't pass a function pointer (NULL) since
714 we want Thread.run()V here. */
716 threads_impl_thread_start(t, NULL);
720 /* threads_attach_current_thread ***********************************************
722 Attaches the current thread to the VM. Used in JNI.
724 *******************************************************************************/
726 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
732 java_handle_t *group;
734 /* If the current thread has already been attached, this operation
737 result = thread_current_is_attached();
742 /* Enter the join-mutex, so if the main-thread is currently
743 waiting to join all threads, the number of non-daemon threads
746 threads_mutex_join_lock();
748 /* Create internal thread data structure. */
752 /* Thread is a Java thread and running. */
754 t->flags = THREAD_FLAG_JAVA;
757 t->flags |= THREAD_FLAG_DAEMON;
759 /* The thread is flagged and (non-)daemon thread, we can leave the
762 threads_mutex_join_unlock();
764 DEBUGTHREADS("attaching", t);
766 /* Get the thread name. */
768 if (vm_aargs != NULL) {
769 u = utf_new_char(vm_aargs->name);
775 name = javastring_new(u);
777 #if defined(ENABLE_JAVASE)
778 /* Get the threadgroup. */
780 if (vm_aargs != NULL)
781 group = (java_handle_t *) vm_aargs->group;
783 /* If no threadgroup was given, use the main threadgroup. */
786 group = threadgroup_main;
789 #if defined(ENABLE_INTRP)
790 /* create interpreter stack */
793 MSET(intrp_main_stack, 0, u1, opt_stacksize);
794 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
798 /* Create the Java thread object. */
800 if (!thread_create_object(t, name, group))
803 /* The thread is completely initialized. */
805 threads_thread_state_runnable(t);
811 /* threads_thread_print_info ***************************************************
813 Print information of the passed thread.
815 *******************************************************************************/
817 void threads_thread_print_info(threadobject *t)
819 java_lang_Thread *object;
820 #if defined(WITH_CLASSPATH_GNU)
821 java_lang_String *namestring;
825 assert(t->state != THREAD_STATE_NEW);
827 /* the thread may be currently in initalization, don't print it */
829 object = (java_lang_Thread *) threads_thread_get_object(t);
831 if (object != NULL) {
832 /* get thread name */
834 #if defined(WITH_CLASSPATH_GNU)
835 LLNI_field_get_ref(object, name, namestring);
836 name = javastring_toutf((java_handle_t *) namestring, false);
837 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
838 /* FIXME: In cldc the name is a char[] */
839 /* name = object->name; */
842 # error unknown classpath configuration
846 utf_display_printable_ascii(name);
849 if (thread_is_daemon(t))
852 printf(" prio=%d", LLNI_field_direct(object, priority));
854 #if SIZEOF_VOID_P == 8
855 printf(" t=0x%016lx tid=0x%016lx (%ld)",
856 (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
858 printf(" t=0x%08x tid=0x%08x (%d)",
859 (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
862 printf(" index=%d", t->index);
864 /* print thread state */
867 case THREAD_STATE_NEW:
870 case THREAD_STATE_RUNNABLE:
873 case THREAD_STATE_BLOCKED:
876 case THREAD_STATE_WAITING:
879 case THREAD_STATE_TIMED_WAITING:
880 printf(" waiting on condition");
882 case THREAD_STATE_TERMINATED:
883 printf(" terminated");
886 vm_abort("threads_thread_print_info: unknown thread state %d",
893 /* threads_get_current_tid *****************************************************
895 Return the tid of the current thread.
900 *******************************************************************************/
902 intptr_t threads_get_current_tid(void)
904 threadobject *thread;
906 thread = THREADOBJECT;
908 /* this may happen during bootstrap */
913 return (intptr_t) thread->tid;
917 /* threads_thread_state_runnable ***********************************************
919 Set the current state of the given thread to THREAD_STATE_RUNNABLE.
921 NOTE: If the thread has already terminated, don't set the state.
922 This is important for threads_detach_thread.
924 *******************************************************************************/
926 void threads_thread_state_runnable(threadobject *t)
928 /* Set the state inside a lock. */
932 if (t->state != THREAD_STATE_TERMINATED)
933 t->state = THREAD_STATE_RUNNABLE;
935 DEBUGTHREADS("is RUNNABLE", t);
941 /* threads_thread_state_waiting ************************************************
943 Set the current state of the given thread to THREAD_STATE_WAITING.
945 NOTE: If the thread has already terminated, don't set the state.
946 This is important for threads_detach_thread.
948 *******************************************************************************/
950 void threads_thread_state_waiting(threadobject *t)
952 /* Set the state inside a lock. */
956 if (t->state != THREAD_STATE_TERMINATED)
957 t->state = THREAD_STATE_WAITING;
959 DEBUGTHREADS("is WAITING", t);
965 /* threads_thread_state_timed_waiting ******************************************
967 Set the current state of the given thread to
968 THREAD_STATE_TIMED_WAITING.
970 NOTE: If the thread has already terminated, don't set the state.
971 This is important for threads_detach_thread.
973 *******************************************************************************/
975 void threads_thread_state_timed_waiting(threadobject *t)
977 /* Set the state inside a lock. */
981 if (t->state != THREAD_STATE_TERMINATED)
982 t->state = THREAD_STATE_TIMED_WAITING;
984 DEBUGTHREADS("is TIMED_WAITING", t);
990 /* threads_thread_state_terminated *********************************************
992 Set the current state of the given thread to
993 THREAD_STATE_TERMINATED.
995 *******************************************************************************/
997 void threads_thread_state_terminated(threadobject *t)
999 /* set the state in the lock */
1003 t->state = THREAD_STATE_TERMINATED;
1005 DEBUGTHREADS("is TERMINATED", t);
1007 threadlist_unlock();
1011 /* threads_thread_get_state ****************************************************
1013 Returns the current state of the given thread.
1015 *******************************************************************************/
1017 utf *threads_thread_get_state(threadobject *t)
1022 case THREAD_STATE_NEW:
1023 u = utf_new_char("NEW");
1025 case THREAD_STATE_RUNNABLE:
1026 u = utf_new_char("RUNNABLE");
1028 case THREAD_STATE_BLOCKED:
1029 u = utf_new_char("BLOCKED");
1031 case THREAD_STATE_WAITING:
1032 u = utf_new_char("WAITING");
1034 case THREAD_STATE_TIMED_WAITING:
1035 u = utf_new_char("TIMED_WAITING");
1037 case THREAD_STATE_TERMINATED:
1038 u = utf_new_char("TERMINATED");
1041 vm_abort("threads_get_state: unknown thread state %d", t->state);
1043 /* keep compiler happy */
1052 /* thread_get_thread **********************************************************
1054 Return the thread data structure of the given Java thread object.
1057 h ... java.lang.{VM}Thread object
1062 *******************************************************************************/
1064 threadobject *thread_get_thread(java_handle_t *h)
1067 #if defined(WITH_CLASSPATH_GNU)
1068 java_lang_VMThread *vmto;
1069 java_lang_Object *to;
1071 #if defined(WITH_CLASSPATH_SUN)
1075 #if defined(WITH_CLASSPATH_GNU)
1077 vmto = (java_lang_VMThread *) h;
1079 LLNI_field_get_val(vmto, vmdata, to);
1081 t = (threadobject *) to;
1083 #elif defined(WITH_CLASSPATH_SUN)
1085 /* XXX This is just a quick hack. */
1089 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
1090 LLNI_equals(t->object, h, equal);
1096 threadlist_unlock();
1098 #elif defined(WITH_CLASSPATH_CLDC1_1)
1100 log_println("threads_get_thread: IMPLEMENT ME!");
1103 # error unknown classpath configuration
1110 /* threads_thread_is_alive *****************************************************
1112 Returns if the give thread is alive.
1114 *******************************************************************************/
1116 bool threads_thread_is_alive(threadobject *t)
1119 case THREAD_STATE_NEW:
1120 case THREAD_STATE_TERMINATED:
1123 case THREAD_STATE_RUNNABLE:
1124 case THREAD_STATE_BLOCKED:
1125 case THREAD_STATE_WAITING:
1126 case THREAD_STATE_TIMED_WAITING:
1130 vm_abort("threads_thread_is_alive: unknown thread state %d", t->state);
1133 /* keep compiler happy */
1139 /* threads_dump ****************************************************************
1141 Dumps info for all threads running in the JVM. This function is
1142 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1144 *******************************************************************************/
1146 void threads_dump(void)
1150 /* XXX we should stop the world here */
1152 /* Lock the thread lists. */
1156 printf("Full thread dump CACAO "VERSION":\n");
1158 /* iterate over all started threads */
1160 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
1161 /* ignore threads which are in state NEW */
1162 if (t->state == THREAD_STATE_NEW)
1165 #if defined(ENABLE_GC_CACAO)
1166 /* Suspend the thread. */
1167 /* XXX Is the suspend reason correct? */
1169 if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
1170 vm_abort("threads_dump: threads_suspend_thread failed");
1173 /* Print thread info. */
1176 threads_thread_print_info(t);
1179 /* Print trace of thread. */
1181 threads_thread_print_stacktrace(t);
1183 #if defined(ENABLE_GC_CACAO)
1184 /* Resume the thread. */
1186 if (threads_resume_thread(t) == false)
1187 vm_abort("threads_dump: threads_resume_thread failed");
1191 /* Unlock the thread lists. */
1193 threadlist_unlock();
1197 /* threads_thread_print_stacktrace *********************************************
1199 Print the current stacktrace of the given thread.
1201 *******************************************************************************/
1203 void threads_thread_print_stacktrace(threadobject *thread)
1205 stackframeinfo_t *sfi;
1206 java_handle_bytearray_t *ba;
1209 /* Build a stacktrace for the passed thread. */
1211 sfi = thread->_stackframeinfo;
1212 ba = stacktrace_get(sfi);
1215 /* We need a critical section here as we use the byte-array
1216 data pointer directly. */
1218 LLNI_CRITICAL_START;
1220 st = (stacktrace_t *) LLNI_array_data(ba);
1222 /* Print stacktrace. */
1224 stacktrace_print(st);
1229 puts("\t<<No stacktrace available>>");
1235 /* threads_print_stacktrace ****************************************************
1237 Print the current stacktrace of the current thread.
1239 *******************************************************************************/
1241 void threads_print_stacktrace(void)
1243 threadobject *thread;
1245 thread = THREADOBJECT;
1247 threads_thread_print_stacktrace(thread);
1252 * These are local overrides for various environment variables in Emacs.
1253 * Please do not remove this and leave it at the end of the file, where
1254 * Emacs will automagically detect them.
1255 * ---------------------------------------------------------------------
1258 * indent-tabs-mode: t
1262 * vim:noexpandtab:sw=4:ts=4: