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