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