9011a6321b04db64a60ce104c120d769db59114c
[cacao.git] / src / threads / thread.cpp
1 /* src/threads/thread.cpp - machine independent thread functions
2
3    Copyright (C) 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
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.
12
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.
17
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
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <unistd.h>
31
32 #include "vm/types.h"
33
34 #include "mm/memory.h"
35
36 #if defined(ENABLE_GC_BOEHM)
37 /* We need to include Boehm's gc.h here for GC_register_my_thread and
38    friends. */
39 # include "mm/boehm-gc/include/gc.h"
40 #endif
41
42 #include "native/jni.h"
43 #include "native/llni.h"
44 #include "native/native.h"
45
46 #include "native/include/java_lang_Object.h"
47 #include "native/include/java_lang_String.h"
48 #include "native/include/java_lang_Thread.h"
49
50 #if defined(ENABLE_JAVASE)
51 # include "native/include/java_lang_ThreadGroup.h"
52 #endif
53
54 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
55 # include "native/include/java_lang_VMThread.h"
56 #endif
57
58 #include "threads/lock-common.h"
59 #include "threads/threadlist.h"
60 #include "threads/thread.hpp"
61
62 #include "vm/builtin.h"
63 #include "vm/exceptions.hpp"
64 #include "vm/string.hpp"
65 #include "vm/vm.hpp"
66
67 #include "vm/jit/stacktrace.hpp"
68
69 #include "vmcore/class.h"
70 #include "vmcore/globals.hpp"
71 #include "vmcore/method.h"
72 #include "vmcore/options.h"
73
74 #if defined(ENABLE_STATISTICS)
75 # include "vmcore/statistics.h"
76 #endif
77
78 #include "vmcore/utf8.h"
79
80
81 // FIXME
82 extern "C" {
83
84 /* global variables ***********************************************************/
85
86 static methodinfo    *thread_method_init;
87 static java_handle_t *threadgroup_system;
88 static java_handle_t *threadgroup_main;
89
90 #if defined(__LINUX__)
91 /* XXX Remove for exact-GC. */
92 bool threads_pthreads_implementation_nptl;
93 #endif
94
95
96 /* static functions ***********************************************************/
97
98 static void          thread_create_initial_threadgroups(void);
99 static void          thread_create_initial_thread(void);
100 static threadobject *thread_new(void);
101
102
103 /* threads_preinit *************************************************************
104
105    Do some early initialization of stuff required.
106
107 *******************************************************************************/
108
109 void threads_preinit(void)
110 {
111         threadobject *mainthread;
112 #if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
113         char         *pathbuf;
114         size_t        len;
115 #endif
116
117         TRACESUBSYSTEMINITIALIZATION("threads_preinit");
118
119 #if defined(__LINUX__)
120         /* XXX Remove for exact-GC. */
121
122         /* On Linux we need to check the pthread implementation. */
123
124         /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
125         /* If the glibc is a pre-2.3.2 version, we fall back to
126            linuxthreads. */
127
128 # if defined(_CS_GNU_LIBPTHREAD_VERSION)
129         len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
130
131         /* Some systems return as length 0 (maybe cross-compilation
132            related).  In this case we also fall back to linuxthreads. */
133
134         if (len > 0) {
135                 pathbuf = MNEW(char, len);
136
137                 (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
138
139                 if (strstr(pathbuf, "NPTL") != NULL)
140                         threads_pthreads_implementation_nptl = true;
141                 else
142                         threads_pthreads_implementation_nptl = false;
143         }
144         else
145                 threads_pthreads_implementation_nptl = false;
146 # else
147         threads_pthreads_implementation_nptl = false;
148 # endif
149 #endif
150
151         /* Initialize the threads implementation (sets the thinlock on the
152            main thread). */
153
154         threads_impl_preinit();
155
156         /* Create internal thread data-structure for the main thread. */
157
158         mainthread = thread_new();
159
160         /* The main thread should always have index 1. */
161
162         if (mainthread->index != 1)
163                 vm_abort("threads_preinit: main thread index not 1: %d != 1",
164                                  mainthread->index);
165
166         /* thread is a Java thread and running */
167
168         mainthread->flags |= THREAD_FLAG_JAVA;
169         mainthread->state = THREAD_STATE_RUNNABLE;
170
171         /* Store the internal thread data-structure in the TSD. */
172
173         thread_set_current(mainthread);
174 }
175
176
177 /* threads_init ****************************************************************
178
179    Initialize the main thread.
180
181 *******************************************************************************/
182
183 void threads_init(void)
184 {
185         TRACESUBSYSTEMINITIALIZATION("threads_init");
186
187         /* Create the system and main thread groups. */
188
189         thread_create_initial_threadgroups();
190
191         /* Cache the java.lang.Thread initialization method. */
192
193 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
194
195         thread_method_init =
196                 class_resolveclassmethod(class_java_lang_Thread,
197                                                                  utf_init,
198                                                                  utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
199                                                                  class_java_lang_Thread,
200                                                                  true);
201
202 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
203
204         thread_method_init =
205                 class_resolveclassmethod(class_java_lang_Thread,
206                                                                  utf_init,
207                                                                  utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"),
208                                                                  class_java_lang_Thread,
209                                                                  true);
210
211 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
212
213         thread_method_init =
214                 class_resolveclassmethod(class_java_lang_Thread,
215                                                                  utf_init,
216                                                                  utf_java_lang_String__void,
217                                                                  class_java_lang_Thread,
218                                                                  true);
219
220 #else
221 # error unknown classpath configuration
222 #endif
223
224         if (thread_method_init == NULL)
225                 vm_abort("threads_init: failed to resolve thread init method");
226
227         thread_create_initial_thread();
228 }
229
230
231 /* thread_create_object ********************************************************
232
233    Create a Java thread object for the given thread data-structure,
234    initializes it and adds the thread to the threadgroup.
235
236    ARGUMENTS:
237
238        t ....... thread
239        name .... thread name
240        group ... threadgroup
241
242    RETURN:
243
244 *******************************************************************************/
245
246 static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
247 {
248         java_handle_t    *o;
249         java_lang_Thread *to;
250
251 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
252         java_lang_VMThread    *vmto;
253         classinfo             *c;
254         methodinfo            *m;
255         bool                   isdaemon;
256 #endif
257
258         /* Create a java.lang.Thread Java object. */
259
260         o = builtin_new(class_java_lang_Thread);
261
262         if (o == NULL)
263                 return false;
264
265         to = (java_lang_Thread *) o;
266
267         /* Set the Java object in the thread data-structure.  This
268            indicates that the thread is attached to the VM. */
269
270         thread_set_object(t, (java_handle_t *) to);
271
272 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
273
274         /* Create a java.lang.VMThread Java object. */
275
276         vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
277
278         if (vmto == NULL)
279                 return false;
280
281         /* Set the Java thread object in the Java VM-thread object. */
282
283         LLNI_field_set_ref(vmto, thread, to);
284
285         /* Set the thread data-structure in the Java VM-thread object. */
286
287         LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
288
289         /* Call:
290            java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
291
292         isdaemon = thread_is_daemon(t);
293
294         (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
295                                                   isdaemon);
296
297         if (exceptions_get_exception())
298                 return false;
299
300         /* Set the threadgroup in the Java thread object. */
301
302         LLNI_field_set_ref(to, group, (java_lang_ThreadGroup *) group);
303
304         /* Add thread to the threadgroup. */
305
306         LLNI_class_get(group, c);
307
308         m = class_resolveclassmethod(c,
309                                                                  utf_addThread,
310                                                                  utf_java_lang_Thread__V,
311                                                                  class_java_lang_ThreadGroup,
312                                                                  true);
313
314         if (m == NULL)
315                 return false;
316
317         (void) vm_call_method(m, group, to);
318
319         if (exceptions_get_exception())
320                 return false;
321
322 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
323
324         /* OpenJDK's java.lang.Thread does not have a VMThread field in
325            the class.  Nothing to do here. */
326
327         /* Set the priority.  java.lang.Thread.<init> requires it because
328            it sets the priority of the current thread to the parent's one
329            (which is the current thread in this case). */
330
331         LLNI_field_set_val(to, priority, NORM_PRIORITY);
332
333         /* Call:
334            java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
335
336         (void) vm_call_method(thread_method_init, o, group, name);
337
338         if (exceptions_get_exception())
339                 return false;
340
341 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
342
343         /* Set the thread data-structure in the Java thread object. */
344
345         LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
346
347         /* Call: public Thread(Ljava/lang/String;)V */
348
349         (void) vm_call_method(thread_method_init, o, name);
350
351         if (exceptions_get_exception())
352                 return false;
353
354 #else
355 # error unknown classpath configuration
356 #endif
357
358         return true;
359 }
360
361
362 /* thread_create_initial_threadgroups ******************************************
363
364    Create the initial threadgroups.
365
366    GNU Classpath:
367        Create the main threadgroup only and set the system
368        threadgroup to the main threadgroup.
369
370    SUN:
371        Create the system and main threadgroup.
372
373    CLDC:
374        This function is a no-op.
375
376 *******************************************************************************/
377
378 static void thread_create_initial_threadgroups(void)
379 {
380 #if defined(ENABLE_JAVASE)
381 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
382
383         /* Allocate and initialize the main thread group. */
384
385         threadgroup_main = native_new_and_init(class_java_lang_ThreadGroup);
386
387         if (threadgroup_main == NULL)
388                 vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
389
390         /* Use the same threadgroup for system as for main. */
391
392         threadgroup_system = threadgroup_main;
393
394 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
395
396         java_handle_t *name;
397         methodinfo    *m;
398
399         /* Allocate and initialize the system thread group. */
400
401         threadgroup_system = native_new_and_init(class_java_lang_ThreadGroup);
402
403         if (threadgroup_system == NULL)
404                 vm_abort("thread_create_initial_threadgroups: failed to allocate system threadgroup");
405
406         /* Allocate and initialize the main thread group. */
407
408         threadgroup_main = builtin_new(class_java_lang_ThreadGroup);
409
410         if (threadgroup_main == NULL)
411                 vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
412
413         name = javastring_new(utf_main);
414
415         m = class_resolveclassmethod(class_java_lang_ThreadGroup,
416                                                                  utf_init,
417                                                                  utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V,
418                                                                  class_java_lang_ThreadGroup,
419                                                                  true);
420
421         if (m == NULL)
422                 vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
423
424         (void) vm_call_method(m, threadgroup_main, threadgroup_system, name);
425
426         if (exceptions_get_exception())
427                 vm_abort("thread_create_initial_threadgroups: exception while initializing main threadgroup");
428
429 # else
430 #  error unknown classpath configuration
431 # endif
432 #endif
433 }
434
435
436 /* thread_create_initial_thread ***********************************************
437
438    Create the initial thread: main
439
440 *******************************************************************************/
441
442 static void thread_create_initial_thread(void)
443 {
444         threadobject  *t;
445         java_handle_t *name;
446
447         /* Get the main-thread (NOTE: The main thread is always the first
448            thread in the list). */
449
450         t = threadlist_first();
451
452         /* The thread name. */
453
454         name = javastring_new(utf_main);
455
456 #if defined(ENABLE_INTRP)
457         /* create interpreter stack */
458
459         if (opt_intrp) {
460                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
461                 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
462         }
463 #endif
464
465         /* Create the Java thread object. */
466
467         if (!thread_create_object(t, name, threadgroup_main))
468                 vm_abort("thread_create_initial_thread: failed to create Java object");
469
470         /* Initialize the implementation specific bits. */
471
472         threads_impl_init();
473
474         DEBUGTHREADS("starting (main)", t);
475 }
476
477
478 /* thread_new ******************************************************************
479
480    Allocates and initializes an internal thread data-structure and
481    adds it to the threads list.
482
483 *******************************************************************************/
484
485 static threadobject *thread_new(void)
486 {
487         int32_t       index;
488         threadobject *t;
489         
490         /* Lock the thread lists */
491
492         threadlist_lock();
493
494         index = threadlist_get_free_index();
495
496         /* Allocate a thread data structure. */
497
498         /* First, try to get one from the free-list. */
499
500         t = threadlist_free_first();
501
502         if (t != NULL) {
503                 /* Remove from free list. */
504
505                 threadlist_free_remove(t);
506
507                 /* Equivalent of MZERO on the else path */
508
509                 threads_impl_thread_clear(t);
510         }
511         else {
512 #if defined(ENABLE_GC_BOEHM)
513                 t = GCNEW_UNCOLLECTABLE(threadobject, 1);
514 #else
515                 t = NEW(threadobject);
516 #endif
517
518 #if defined(ENABLE_STATISTICS)
519                 if (opt_stat)
520                         size_threadobject += sizeof(threadobject);
521 #endif
522
523                 /* Clear memory. */
524
525                 MZERO(t, threadobject, 1);
526
527 #if defined(ENABLE_GC_CACAO)
528                 /* Register reference to java.lang.Thread with the GC. */
529                 /* FIXME is it ok to do this only once? */
530
531                 gc_reference_register(&(t->object), GC_REFTYPE_THREADOBJECT);
532                 gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
533 #endif
534
535                 /* Initialize the implementation-specific bits. */
536
537                 threads_impl_thread_init(t);
538         }
539
540         /* Pre-compute the thinlock-word. */
541
542         assert(index != 0);
543
544         t->index     = index;
545         t->thinlock  = lock_pre_compute_thinlock(t->index);
546         t->flags     = 0;
547         t->state     = THREAD_STATE_NEW;
548
549 #if defined(ENABLE_GC_CACAO)
550         t->flags    |= THREAD_FLAG_IN_NATIVE; 
551 #endif
552
553         /* Initialize the implementation-specific bits. */
554
555         threads_impl_thread_reuse(t);
556
557         /* Add the thread to the thread list. */
558
559         threadlist_add(t);
560
561         /* Unlock the thread lists. */
562
563         threadlist_unlock();
564
565         return t;
566 }
567
568
569 /* thread_free *****************************************************************
570
571    Remove the thread from the threads-list and free the internal
572    thread data structure.  The thread index is added to the
573    thread-index free-list.
574
575    IN:
576        t ... thread data structure
577
578 *******************************************************************************/
579
580 void thread_free(threadobject *t)
581 {
582         /* Lock the thread lists. */
583
584         threadlist_lock();
585
586         /* Remove the thread from the thread-list. */
587
588         threadlist_remove(t);
589
590         /* Add the thread index to the free list. */
591
592         threadlist_index_add(t->index);
593
594         /* Set the reference to the Java object to NULL. */
595
596         thread_set_object(t, NULL);
597
598         /* Add the thread data structure to the free list. */
599
600         threadlist_free_add(t);
601
602         /* Unlock the thread lists. */
603
604         threadlist_unlock();
605 }
606
607
608 /* threads_thread_start_internal ***********************************************
609
610    Start an internal thread in the JVM.  No Java thread objects exists
611    so far.
612
613    IN:
614       name.......UTF-8 name of the thread
615       f..........function pointer to C function to start
616
617 *******************************************************************************/
618
619 bool threads_thread_start_internal(utf *name, functionptr f)
620 {
621         threadobject *t;
622
623         /* Enter the join-mutex, so if the main-thread is currently
624            waiting to join all threads, the number of non-daemon threads
625            is correct. */
626
627         threads_mutex_join_lock();
628
629         /* Create internal thread data-structure. */
630
631         t = thread_new();
632
633         t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
634
635         /* The thread is flagged as (non-)daemon thread, we can leave the
636            mutex. */
637
638         threads_mutex_join_unlock();
639
640         /* Create the Java thread object. */
641
642         if (!thread_create_object(t, javastring_new(name), threadgroup_system))
643                 return false;
644
645         /* Start the thread. */
646
647         threads_impl_thread_start(t, f);
648
649         /* everything's ok */
650
651         return true;
652 }
653
654
655 /* threads_thread_start ********************************************************
656
657    Start a Java thread in the JVM.  Only the java thread object exists
658    so far.
659
660    IN:
661       object.....the java thread object java.lang.Thread
662
663 *******************************************************************************/
664
665 void threads_thread_start(java_handle_t *object)
666 {
667         java_lang_Thread   *to;
668         threadobject       *t;
669 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
670         java_lang_VMThread *vmto;
671 #endif
672
673         to = (java_lang_Thread *) object;
674
675         /* Enter the join-mutex, so if the main-thread is currently
676            waiting to join all threads, the number of non-daemon threads
677            is correct. */
678
679         threads_mutex_join_lock();
680
681         /* Create internal thread data-structure. */
682
683         t = thread_new();
684
685         /* this is a normal Java thread */
686
687         t->flags |= THREAD_FLAG_JAVA;
688
689 #if defined(ENABLE_JAVASE)
690         /* Is this a daemon thread? */
691
692         if (LLNI_field_direct(to, daemon) == true)
693                 t->flags |= THREAD_FLAG_DAEMON;
694 #endif
695
696         /* The thread is flagged and (non-)daemon thread, we can leave the
697            mutex. */
698
699         threads_mutex_join_unlock();
700
701         /* Link the two objects together. */
702
703         thread_set_object(t, object);
704
705 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
706
707         /* Get the java.lang.VMThread object and do some sanity checks. */
708
709         LLNI_field_get_ref(to, vmThread, vmto);
710
711         assert(vmto);
712         assert(LLNI_field_direct(vmto, vmdata) == NULL);
713
714         LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
715
716 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
717
718         /* Nothing to do. */
719
720 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
721
722         LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
723
724 #else
725 # error unknown classpath configuration
726 #endif
727
728         /* Start the thread.  Don't pass a function pointer (NULL) since
729            we want Thread.run()V here. */
730
731         threads_impl_thread_start(t, NULL);
732 }
733
734
735 /**
736  * Attaches the current thread to the VM.
737  *
738  * @param vm_aargs Attach arguments.
739  * @param isdaemon true if the attached thread should be a daemon
740  *                 thread.
741  *
742  * @return true on success, false otherwise.
743  */
744 bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
745 {
746         bool           result;
747         threadobject  *t;
748         utf           *u;
749         java_handle_t *name;
750         java_handle_t *group;
751
752     /* If the current thread has already been attached, this operation
753            is a no-op. */
754
755         result = thread_current_is_attached();
756
757         if (result == true)
758                 return true;
759
760         /* Enter the join-mutex, so if the main-thread is currently
761            waiting to join all threads, the number of non-daemon threads
762            is correct. */
763
764         threads_mutex_join_lock();
765
766         /* Create internal thread data structure. */
767
768         t = thread_new();
769
770         /* Thread is a Java thread and running. */
771
772         t->flags = THREAD_FLAG_JAVA;
773
774         if (isdaemon)
775                 t->flags |= THREAD_FLAG_DAEMON;
776
777         /* Store the internal thread data-structure in the TSD. */
778
779         thread_set_current(t);
780
781         /* The thread is flagged and (non-)daemon thread, we can leave the
782            mutex. */
783
784         threads_mutex_join_unlock();
785
786         DEBUGTHREADS("attaching", t);
787
788         /* Get the thread name. */
789
790         if (vm_aargs != NULL) {
791                 u = utf_new_char(vm_aargs->name);
792         }
793         else {
794                 u = utf_null;
795         }
796
797         name = javastring_new(u);
798
799 #if defined(ENABLE_JAVASE)
800         /* Get the threadgroup. */
801
802         if (vm_aargs != NULL)
803                 group = (java_handle_t *) vm_aargs->group;
804         else
805                 group = NULL;
806
807         /* If no threadgroup was given, use the main threadgroup. */
808
809         if (group == NULL)
810                 group = threadgroup_main;
811 #endif
812
813 #if defined(ENABLE_INTRP)
814         /* create interpreter stack */
815
816         if (opt_intrp) {
817                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
818                 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
819         }
820 #endif
821
822         /* Create the Java thread object. */
823
824         if (!thread_create_object(t, name, group))
825                 return false;
826
827         /* The thread is completely initialized. */
828
829         thread_set_state_runnable(t);
830
831         return true;
832 }
833
834
835 /**
836  * Attaches the current external thread to the VM.  This function is
837  * called by JNI's AttachCurrentThread.
838  *
839  * @param vm_aargs Attach arguments.
840  * @param isdaemon true if the attached thread should be a daemon
841  *                 thread.
842  *
843  * @return true on success, false otherwise.
844  */
845 bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
846 {
847         int result;
848
849 #if defined(ENABLE_GC_BOEHM)
850         struct GC_stack_base sb;
851 #endif
852
853 #if defined(ENABLE_GC_BOEHM)
854         /* Register the thread with Boehm-GC.  This must happen before the
855            thread allocates any memory from the GC heap.*/
856
857         result = GC_get_stack_base(&sb);
858
859         if (result != GC_SUCCESS)
860                 vm_abort("threads_attach_current_thread: GC_get_stack_base failed");
861
862         GC_register_my_thread(&sb);
863 #endif
864
865         result = thread_attach_current_thread(vm_aargs, isdaemon);
866
867         if (result == false) {
868 #if defined(ENABLE_GC_BOEHM)
869                 /* Unregister the thread. */
870
871                 GC_unregister_my_thread();
872 #endif
873
874                 return false;
875         }
876
877         return true;
878 }
879
880
881 /**
882  * Detaches the current external thread from the VM.  This function is
883  * called by JNI's DetachCurrentThread.
884  *
885  * @return true on success, false otherwise.
886  */
887 bool thread_detach_current_external_thread(void)
888 {
889         int result;
890
891         result = thread_detach_current_thread();
892
893         if (result == false)
894                 return false;
895
896 #if defined(ENABLE_GC_BOEHM)
897         /* Unregister the thread with Boehm-GC.  This must happen after
898            the thread allocates any memory from the GC heap. */
899
900         /* Don't detach the main thread.  This is a workaround for
901            OpenJDK's java binary. */
902         if (thread_get_current()->index != 1)
903                 GC_unregister_my_thread();
904 #endif
905
906         return true;
907 }
908
909
910 /* thread_fprint_name **********************************************************
911
912    Print the name of the given thread to the given stream.
913
914    ARGUMENTS:
915        t ........ thread data-structure
916        stream ... stream to print to
917
918 *******************************************************************************/
919
920 void thread_fprint_name(threadobject *t, FILE *stream)
921 {
922         java_lang_Thread *to;
923
924 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
925         java_lang_String *name;
926 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
927         java_chararray_t *name;
928 #endif
929
930         to = (java_lang_Thread *) thread_get_object(t);
931
932         if (to == NULL)
933                 vm_abort("");
934
935         LLNI_field_get_ref(to, name, name);
936
937 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
938
939         javastring_fprint((java_handle_t *) name, stream);
940
941 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
942
943         /* FIXME: In OpenJDK and CLDC the name is a char[]. */
944         /* FIXME This prints to stdout. */
945         utf_display_printable_ascii(utf_null);
946
947 #else
948 # error unknown classpath configuration
949 #endif
950 }
951
952
953 /* thread_print_info ***********************************************************
954
955    Print information of the passed thread.
956
957    ARGUMENTS:
958        t ... thread data-structure.
959
960 *******************************************************************************/
961
962 void thread_print_info(threadobject *t)
963 {
964         java_lang_Thread *to;
965         int               state;
966
967         /* If the thread is currently in initalization, don't print it. */
968
969         to = (java_lang_Thread *) thread_get_object(t);
970
971         /* Print as much as we can when we are in state NEW. */
972
973         if (to != NULL) {
974                 /* Print thread name. */
975
976                 printf("\"");
977                 thread_fprint_name(t, stdout);
978                 printf("\"");
979         }
980         else {
981         }
982
983         if (thread_is_daemon(t))
984                 printf(" daemon");
985
986         if (to != NULL) {
987                 printf(" prio=%d", LLNI_field_direct(to, priority));
988         }
989
990 #if SIZEOF_VOID_P == 8
991         printf(" t=0x%016lx tid=0x%016lx (%ld)",
992                    (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
993 #else
994         printf(" t=0x%08x tid=0x%08x (%d)",
995                    (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
996 #endif
997
998         printf(" index=%d", t->index);
999
1000         /* Print thread state. */
1001
1002         state = cacaothread_get_state(t);
1003
1004         switch (state) {
1005         case THREAD_STATE_NEW:
1006                 printf(" new");
1007                 break;
1008         case THREAD_STATE_RUNNABLE:
1009                 printf(" runnable");
1010                 break;
1011         case THREAD_STATE_BLOCKED:
1012                 printf(" blocked");
1013                 break;
1014         case THREAD_STATE_WAITING:
1015                 printf(" waiting");
1016                 break;
1017         case THREAD_STATE_TIMED_WAITING:
1018                 printf(" waiting on condition");
1019                 break;
1020         case THREAD_STATE_TERMINATED:
1021                 printf(" terminated");
1022                 break;
1023         default:
1024                 vm_abort("thread_print_info: unknown thread state %d", state);
1025         }
1026 }
1027
1028
1029 /* threads_get_current_tid *****************************************************
1030
1031    Return the tid of the current thread.
1032    
1033    RETURN VALUE:
1034        the current tid
1035
1036 *******************************************************************************/
1037
1038 intptr_t threads_get_current_tid(void)
1039 {
1040         threadobject *thread;
1041
1042         thread = THREADOBJECT;
1043
1044         /* this may happen during bootstrap */
1045
1046         if (thread == NULL)
1047                 return 0;
1048
1049         return (intptr_t) thread->tid;
1050 }
1051
1052
1053 /* thread_set_state_runnable ***************************************************
1054
1055    Set the current state of the given thread to THREAD_STATE_RUNNABLE.
1056
1057    NOTE: If the thread has already terminated, don't set the state.
1058          This is important for threads_detach_thread.
1059
1060 *******************************************************************************/
1061
1062 void thread_set_state_runnable(threadobject *t)
1063 {
1064         /* Set the state inside a lock. */
1065
1066         threadlist_lock();
1067
1068         if (t->state != THREAD_STATE_TERMINATED) {
1069                 t->state = THREAD_STATE_RUNNABLE;
1070
1071                 DEBUGTHREADS("is RUNNABLE", t);
1072         }
1073
1074         threadlist_unlock();
1075 }
1076
1077
1078 /* thread_set_state_waiting ****************************************************
1079
1080    Set the current state of the given thread to THREAD_STATE_WAITING.
1081
1082    NOTE: If the thread has already terminated, don't set the state.
1083          This is important for threads_detach_thread.
1084
1085 *******************************************************************************/
1086
1087 void thread_set_state_waiting(threadobject *t)
1088 {
1089         /* Set the state inside a lock. */
1090
1091         threadlist_lock();
1092
1093         if (t->state != THREAD_STATE_TERMINATED) {
1094                 t->state = THREAD_STATE_WAITING;
1095
1096                 DEBUGTHREADS("is WAITING", t);
1097         }
1098
1099         threadlist_unlock();
1100 }
1101
1102
1103 /* thread_set_state_timed_waiting **********************************************
1104
1105    Set the current state of the given thread to
1106    THREAD_STATE_TIMED_WAITING.
1107
1108    NOTE: If the thread has already terminated, don't set the state.
1109          This is important for threads_detach_thread.
1110
1111 *******************************************************************************/
1112
1113 void thread_set_state_timed_waiting(threadobject *t)
1114 {
1115         /* Set the state inside a lock. */
1116
1117         threadlist_lock();
1118
1119         if (t->state != THREAD_STATE_TERMINATED) {
1120                 t->state = THREAD_STATE_TIMED_WAITING;
1121
1122                 DEBUGTHREADS("is TIMED_WAITING", t);
1123         }
1124
1125         threadlist_unlock();
1126 }
1127
1128
1129 /* thread_set_state_terminated *************************************************
1130
1131    Set the current state of the given thread to
1132    THREAD_STATE_TERMINATED.
1133
1134 *******************************************************************************/
1135
1136 void thread_set_state_terminated(threadobject *t)
1137 {
1138         /* Set the state inside a lock. */
1139
1140         threadlist_lock();
1141
1142         t->state = THREAD_STATE_TERMINATED;
1143
1144         DEBUGTHREADS("is TERMINATED", t);
1145
1146         threadlist_unlock();
1147 }
1148
1149
1150 /* thread_get_thread **********************************************************
1151
1152    Return the thread data structure of the given Java thread object.
1153
1154    ARGUMENTS:
1155        h ... java.lang.{VM}Thread object
1156
1157    RETURN VALUE:
1158        the thread object
1159
1160 *******************************************************************************/
1161
1162 threadobject *thread_get_thread(java_handle_t *h)
1163 {
1164         threadobject       *t;
1165 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1166         java_lang_VMThread *vmto;
1167         java_lang_Object   *to;
1168 #endif
1169 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1170         bool                equal;
1171 #endif
1172
1173 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1174
1175         vmto = (java_lang_VMThread *) h;
1176
1177         LLNI_field_get_val(vmto, vmdata, to);
1178
1179         t = (threadobject *) to;
1180
1181 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1182
1183         /* XXX This is just a quick hack. */
1184
1185         threadlist_lock();
1186
1187         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
1188                 LLNI_equals(t->object, h, equal);
1189
1190                 if (equal == true)
1191                         break;
1192         }
1193
1194         threadlist_unlock();
1195
1196 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1197
1198         log_println("threads_get_thread: IMPLEMENT ME!");
1199
1200 #else
1201 # error unknown classpath configuration
1202 #endif
1203
1204         return t;
1205 }
1206
1207
1208 /* threads_thread_is_alive *****************************************************
1209
1210    Returns if the give thread is alive.
1211
1212 *******************************************************************************/
1213
1214 bool threads_thread_is_alive(threadobject *t)
1215 {
1216         int state;
1217
1218         state = cacaothread_get_state(t);
1219
1220         switch (state) {
1221         case THREAD_STATE_NEW:
1222         case THREAD_STATE_TERMINATED:
1223                 return false;
1224
1225         case THREAD_STATE_RUNNABLE:
1226         case THREAD_STATE_BLOCKED:
1227         case THREAD_STATE_WAITING:
1228         case THREAD_STATE_TIMED_WAITING:
1229                 return true;
1230
1231         default:
1232                 vm_abort("threads_thread_is_alive: unknown thread state %d", state);
1233         }
1234
1235         /* keep compiler happy */
1236
1237         return false;
1238 }
1239
1240
1241 /* threads_dump ****************************************************************
1242
1243    Dumps info for all threads running in the JVM.  This function is
1244    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1245
1246 *******************************************************************************/
1247
1248 void threads_dump(void)
1249 {
1250         threadobject *t;
1251
1252         /* XXX we should stop the world here */
1253
1254         /* Lock the thread lists. */
1255
1256         threadlist_lock();
1257
1258         printf("Full thread dump CACAO "VERSION":\n");
1259
1260         /* iterate over all started threads */
1261
1262         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
1263                 /* ignore threads which are in state NEW */
1264                 if (t->state == THREAD_STATE_NEW)
1265                         continue;
1266
1267 #if defined(ENABLE_GC_CACAO)
1268                 /* Suspend the thread. */
1269                 /* XXX Is the suspend reason correct? */
1270
1271                 if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
1272                         vm_abort("threads_dump: threads_suspend_thread failed");
1273 #endif
1274
1275                 /* Print thread info. */
1276
1277                 printf("\n");
1278                 thread_print_info(t);
1279                 printf("\n");
1280
1281                 /* Print trace of thread. */
1282
1283                 stacktrace_print_of_thread(t);
1284
1285 #if defined(ENABLE_GC_CACAO)
1286                 /* Resume the thread. */
1287
1288                 if (threads_resume_thread(t) == false)
1289                         vm_abort("threads_dump: threads_resume_thread failed");
1290 #endif
1291         }
1292
1293         /* Unlock the thread lists. */
1294
1295         threadlist_unlock();
1296 }
1297
1298 } // extern "C"
1299
1300
1301 /*
1302  * These are local overrides for various environment variables in Emacs.
1303  * Please do not remove this and leave it at the end of the file, where
1304  * Emacs will automagically detect them.
1305  * ---------------------------------------------------------------------
1306  * Local variables:
1307  * mode: c++
1308  * indent-tabs-mode: t
1309  * c-basic-offset: 4
1310  * tab-width: 4
1311  * End:
1312  * vim:noexpandtab:sw=4:ts=4:
1313  */