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