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