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