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