31d345c6da9b85e2cef34ab4e6c36f9ea3fdca64
[cacao.git] / src / threads / threads-common.c
1 /* src/threads/threads-common.c - machine independent thread functions
2
3    Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: threads-common.c 8295 2007-08-11 17:57:24Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <unistd.h>
35
36 #include "vm/types.h"
37
38 #include "mm/memory.h"
39
40 #include "native/jni.h"
41 #include "native/llni.h"
42
43 #include "native/include/java_lang_Object.h"
44 #include "native/include/java_lang_String.h"
45 #include "native/include/java_lang_Thread.h"
46
47 #if defined(WITH_CLASSPATH_GNU)
48 # include "native/include/java_lang_VMThread.h"
49 #endif
50
51 #include "threads/critical.h"
52 #include "threads/lock-common.h"
53 #include "threads/threads-common.h"
54
55 #include "toolbox/list.h"
56
57 #include "vm/builtin.h"
58 #include "vm/stringlocal.h"
59 #include "vm/vm.h"
60
61 #include "vm/jit/stacktrace.h"
62
63 #include "vmcore/class.h"
64
65 #if defined(ENABLE_STATISTICS)
66 # include "vmcore/options.h"
67 # include "vmcore/statistics.h"
68 #endif
69
70 #include "vmcore/utf8.h"
71
72
73 /* global variables ***********************************************************/
74
75 /* global threads list */
76 static list_t *list_threads;
77
78 /* global threads free-list */
79 static list_t *list_threads_free;
80
81 #if defined(__LINUX__)
82 /* XXX Remove for exact-GC. */
83 bool threads_pthreads_implementation_nptl;
84 #endif
85
86
87 /* threads_preinit *************************************************************
88
89    Do some early initialization of stuff required.
90
91    ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
92    is called AFTER this function!
93
94 *******************************************************************************/
95
96 void threads_preinit(void)
97 {
98         threadobject *mainthread;
99 #if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
100         char         *pathbuf;
101         size_t        len;
102 #endif
103
104 #if defined(__LINUX__)
105         /* XXX Remove for exact-GC. */
106
107         /* On Linux we need to check the pthread implementation. */
108
109         /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
110         /* If the glibc is a pre-2.3.2 version, we fall back to
111            linuxthreads. */
112
113 # if defined(_CS_GNU_LIBPTHREAD_VERSION)
114         len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
115
116         /* Some systems return as length 0 (maybe cross-compilation
117            related).  In this case we also fall back to linuxthreads. */
118
119         if (len > 0) {
120                 pathbuf = MNEW(char, len);
121
122                 (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
123
124                 if (strstr(pathbuf, "NPTL") != NULL)
125                         threads_pthreads_implementation_nptl = true;
126                 else
127                         threads_pthreads_implementation_nptl = false;
128         }
129         else
130                 threads_pthreads_implementation_nptl = false;
131 # else
132         threads_pthreads_implementation_nptl = false;
133 # endif
134 #endif
135
136         /* initialize the threads lists */
137
138         list_threads      = list_create(OFFSET(threadobject, linkage));
139         list_threads_free = list_create(OFFSET(threadobject, linkage));
140
141         /* Initialize the threads implementation (sets the thinlock on the
142            main thread). */
143
144         threads_impl_preinit();
145
146         /* create internal thread data-structure for the main thread */
147
148         mainthread = threads_thread_new();
149
150         /* thread is a Java thread and running */
151
152         mainthread->flags = THREAD_FLAG_JAVA;
153         mainthread->state = THREAD_STATE_RUNNABLE;
154
155         /* store the internal thread data-structure in the TSD */
156
157         threads_set_current_threadobject(mainthread);
158
159         /* initialize locking subsystems */
160
161         lock_init();
162
163         /* initialize the critical section */
164
165         critical_init();
166 }
167
168
169 /* threads_list_first **********************************************************
170
171    Return the first entry in the threads list.
172
173    NOTE: This function does not lock the lists.
174
175 *******************************************************************************/
176
177 threadobject *threads_list_first(void)
178 {
179         threadobject *t;
180
181         t = list_first_unsynced(list_threads);
182
183         return t;
184 }
185
186
187 /* threads_list_next ***********************************************************
188
189    Return the next entry in the threads list.
190
191    NOTE: This function does not lock the lists.
192
193 *******************************************************************************/
194
195 threadobject *threads_list_next(threadobject *t)
196 {
197         threadobject *next;
198
199         next = list_next_unsynced(list_threads, t);
200
201         return next;
202 }
203
204
205 /* threads_list_get_non_daemons ************************************************
206
207    Return the number of non-daemon threads.
208
209    NOTE: This function does a linear-search over the threads list,
210          because it's only used for joining the threads.
211
212 *******************************************************************************/
213
214 s4 threads_list_get_non_daemons(void)
215 {
216         threadobject *t;
217         s4            nondaemons;
218
219         /* lock the threads lists */
220
221         threads_list_lock();
222
223         nondaemons = 0;
224
225         for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
226                 if (!(t->flags & THREAD_FLAG_DAEMON))
227                         nondaemons++;
228         }
229
230         /* unlock the threads lists */
231
232         threads_list_unlock();
233
234         return nondaemons;
235 }
236
237
238 /* threads_thread_new **********************************************************
239
240    Allocates and initializes an internal thread data-structure and
241    adds it to the threads list.
242
243 *******************************************************************************/
244
245 threadobject *threads_thread_new(void)
246 {
247         threadobject *t;
248
249         /* lock the threads-lists */
250
251         threads_list_lock();
252
253         /* try to get a thread from the free-list */
254
255         t = list_first_unsynced(list_threads_free);
256
257         /* is a free thread available? */
258
259         if (t != NULL) {
260                 /* yes, remove it from the free list */
261
262                 list_remove_unsynced(list_threads_free, t);
263         }
264         else {
265                 /* no, allocate a new one */
266
267 #if defined(ENABLE_GC_BOEHM)
268                 t = GCNEW_UNCOLLECTABLE(threadobject, 1);
269 #else
270                 t = NEW(threadobject);
271 #endif
272
273 #if defined(ENABLE_STATISTICS)
274                 if (opt_stat)
275                         size_threadobject += sizeof(threadobject);
276 #endif
277
278                 /* clear memory */
279
280                 MZERO(t, threadobject, 1);
281
282                 /* set the threads-index */
283
284                 t->index = list_threads->size + 1;
285         }
286
287         /* pre-compute the thinlock-word */
288
289         assert(t->index != 0);
290
291         t->thinlock = lock_pre_compute_thinlock(t->index);
292         t->state    = THREAD_STATE_NEW;
293
294         /* initialize the implementation-specific bits */
295
296         threads_impl_thread_new(t);
297
298         /* add the thread to the threads-list */
299
300         list_add_last_unsynced(list_threads, t);
301
302         /* unlock the threads-lists */
303
304         threads_list_unlock();
305
306         return t;
307 }
308
309
310 /* threads_thread_free *********************************************************
311
312    Frees an internal thread data-structure by removing it from the
313    threads-list and adding it to the free-list.
314
315    NOTE: The data-structure is NOT freed, the pointer keeps valid!
316
317 *******************************************************************************/
318
319 void threads_thread_free(threadobject *t)
320 {
321         int32_t  index;
322         uint32_t state;
323
324         /* lock the threads-lists */
325
326         threads_list_lock();
327
328         /* cleanup the implementation-specific bits */
329
330         threads_impl_thread_free(t);
331
332         /* remove the thread from the threads-list */
333
334         list_remove_unsynced(list_threads, t);
335
336         /* Clear memory, but keep the thread-index and the
337            thread-state. */
338
339         /* ATTENTION: Do this after list_remove, otherwise the linkage
340            pointers are invalid. */
341
342         index = t->index;
343         state = t->state;
344
345         MZERO(t, threadobject, 1);
346
347         t->index = index;
348         t->state = state;
349
350         /* add the thread to the free list */
351
352         list_add_first_unsynced(list_threads_free, t);
353
354         /* unlock the threads-lists */
355
356         threads_list_unlock();
357 }
358
359
360 /* threads_thread_start_internal ***********************************************
361
362    Start an internal thread in the JVM.  No Java thread objects exists
363    so far.
364
365    IN:
366       name.......UTF-8 name of the thread
367       f..........function pointer to C function to start
368
369 *******************************************************************************/
370
371 bool threads_thread_start_internal(utf *name, functionptr f)
372 {
373         threadobject       *t;
374         java_lang_Thread   *object;
375 #if defined(WITH_CLASSPATH_GNU)
376         java_lang_VMThread *vmt;
377 #endif
378
379         /* Enter the join-mutex, so if the main-thread is currently
380            waiting to join all threads, the number of non-daemon threads
381            is correct. */
382
383         threads_mutex_join_lock();
384
385         /* create internal thread data-structure */
386
387         t = threads_thread_new();
388
389         t->flags = THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
390
391         /* The thread is flagged as (non-)daemon thread, we can leave the
392            mutex. */
393
394         threads_mutex_join_unlock();
395
396         /* create the java thread object */
397
398         object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
399
400         /* XXX memory leak!!! */
401         if (object == NULL)
402                 return false;
403
404 #if defined(WITH_CLASSPATH_GNU)
405         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
406
407         /* XXX memory leak!!! */
408         if (vmt == NULL)
409                 return false;
410
411         LLNI_field_set_ref(vmt, thread, object);
412         LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) t);
413
414         LLNI_field_set_ref(object, vmThread, vmt);
415 #elif defined(WITH_CLASSPATH_CLDC1_1)
416         LLNI_field_set_val(object, vm_thread, (java_lang_Object *) t);
417 #endif
418
419         t->object = object;
420
421         /* set java.lang.Thread fields */
422
423 #if defined(WITH_CLASSPATH_GNU)
424         LLNI_field_set_ref(object, name    , (java_lang_String *) javastring_new(name));
425 #elif defined(WITH_CLASSPATH_CLDC1_1)
426         /* FIXME: In cldc the name is a char[] */
427 /*      LLNI_field_set_ref(object, name    , (java_chararray *) javastring_new(name)); */
428         LLNI_field_set_ref(object, name    , NULL);
429 #endif
430
431 #if defined(ENABLE_JAVASE)
432         LLNI_field_set_val(object, daemon  , true);
433 #endif
434
435         LLNI_field_set_val(object, priority, NORM_PRIORITY);
436
437         /* start the thread */
438
439         threads_impl_thread_start(t, f);
440
441         /* everything's ok */
442
443         return true;
444 }
445
446
447 /* threads_thread_start ********************************************************
448
449    Start a Java thread in the JVM.  Only the java thread object exists
450    so far.
451
452    IN:
453       object.....the java thread object java.lang.Thread
454
455 *******************************************************************************/
456
457 void threads_thread_start(java_lang_Thread *object)
458 {
459         threadobject *thread;
460 #if defined(WITH_CLASSPATH_GNU)
461         java_lang_VMThread *vmt;
462 #endif
463
464         /* Enter the join-mutex, so if the main-thread is currently
465            waiting to join all threads, the number of non-daemon threads
466            is correct. */
467
468         threads_mutex_join_lock();
469
470         /* create internal thread data-structure */
471
472         thread = threads_thread_new();
473
474         /* this is a normal Java thread */
475
476         thread->flags = THREAD_FLAG_JAVA;
477
478 #if defined(ENABLE_JAVASE)
479         /* is this a daemon thread? */
480
481         if (LLNI_field_direct(object, daemon) == true)
482                 thread->flags |= THREAD_FLAG_DAEMON;
483 #endif
484
485         /* The thread is flagged and (non-)daemon thread, we can leave the
486            mutex. */
487
488         threads_mutex_join_unlock();
489
490         /* link the two objects together */
491
492         thread->object = object;
493
494 #if defined(WITH_CLASSPATH_GNU)
495         LLNI_field_get_ref(object, vmThread, vmt);
496
497         assert(vmt);
498         assert(LLNI_field_direct(vmt, vmdata) == NULL);
499
500         LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
501 #elif defined(WITH_CLASSPATH_CLDC1_1)
502         LLNI_field_set_val(object, vm_thread, (java_lang_Object *) thread);
503 #endif
504
505         /* Start the thread.  Don't pass a function pointer (NULL) since
506            we want Thread.run()V here. */
507
508         threads_impl_thread_start(thread, NULL);
509 }
510
511
512 /* threads_thread_print_info ***************************************************
513
514    Print information of the passed thread.
515    
516 *******************************************************************************/
517
518 void threads_thread_print_info(threadobject *t)
519 {
520         java_lang_Thread *object;
521         utf              *name;
522
523         assert(t->state != THREAD_STATE_NEW);
524
525         /* the thread may be currently in initalization, don't print it */
526
527         object = t->object;
528
529         if (object != NULL) {
530                 /* get thread name */
531
532 #if defined(WITH_CLASSPATH_GNU)
533                 name = javastring_toutf((java_handle_t *) LLNI_field_direct(object, name), false);
534 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
535                 /* FIXME: In cldc the name is a char[] */
536 /*              name = object->name; */
537                 name = utf_null;
538 #else
539 # error unknown classpath configuration
540 #endif
541
542                 printf("\"");
543                 utf_display_printable_ascii(name);
544                 printf("\"");
545
546                 if (t->flags & THREAD_FLAG_DAEMON)
547                         printf(" daemon");
548
549                 printf(" prio=%d", LLNI_field_direct(object, priority));
550
551 #if SIZEOF_VOID_P == 8
552                 printf(" t=0x%016lx tid=0x%016lx (%ld)",
553                            (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
554 #else
555                 printf(" t=0x%08x tid=0x%08x (%d)",
556                            (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
557 #endif
558
559                 printf(" index=%d", t->index);
560
561                 /* print thread state */
562
563                 switch (t->state) {
564                 case THREAD_STATE_NEW:
565                         printf(" new");
566                         break;
567                 case THREAD_STATE_RUNNABLE:
568                         printf(" runnable");
569                         break;
570                 case THREAD_STATE_BLOCKED:
571                         printf(" blocked");
572                         break;
573                 case THREAD_STATE_WAITING:
574                         printf(" waiting");
575                         break;
576                 case THREAD_STATE_TIMED_WAITING:
577                         printf(" waiting on condition");
578                         break;
579                 case THREAD_STATE_TERMINATED:
580                         printf(" terminated");
581                         break;
582                 default:
583                         vm_abort("threads_thread_print_info: unknown thread state %d",
584                                          t->state);
585                 }
586         }
587 }
588
589
590 /* threads_get_current_tid *****************************************************
591
592    Return the tid of the current thread.
593    
594    RETURN VALUE:
595        the current tid
596
597 *******************************************************************************/
598
599 ptrint threads_get_current_tid(void)
600 {
601         threadobject *thread;
602
603         thread = THREADOBJECT;
604
605         /* this may happen during bootstrap */
606
607         if (thread == NULL)
608                 return 0;
609
610         return (ptrint) thread->tid;
611 }
612
613
614 /* threads_thread_state_runnable ***********************************************
615
616    Set the current state of the given thread to THREAD_STATE_RUNNABLE.
617
618 *******************************************************************************/
619
620 void threads_thread_state_runnable(threadobject *t)
621 {
622         /* set the state inside the lock */
623
624         threads_list_lock();
625
626         t->state = THREAD_STATE_RUNNABLE;
627
628         threads_list_unlock();
629 }
630
631
632 /* threads_thread_state_waiting ************************************************
633
634    Set the current state of the given thread to THREAD_STATE_WAITING.
635
636 *******************************************************************************/
637
638 void threads_thread_state_waiting(threadobject *t)
639 {
640         /* set the state in the lock */
641
642         threads_list_lock();
643
644         t->state = THREAD_STATE_WAITING;
645
646         threads_list_unlock();
647 }
648
649
650 /* threads_thread_state_timed_waiting ******************************************
651
652    Set the current state of the given thread to
653    THREAD_STATE_TIMED_WAITING.
654
655 *******************************************************************************/
656
657 void threads_thread_state_timed_waiting(threadobject *t)
658 {
659         /* set the state in the lock */
660
661         threads_list_lock();
662
663         t->state = THREAD_STATE_TIMED_WAITING;
664
665         threads_list_unlock();
666 }
667
668
669 /* threads_thread_state_terminated *********************************************
670
671    Set the current state of the given thread to
672    THREAD_STATE_TERMINATED.
673
674 *******************************************************************************/
675
676 void threads_thread_state_terminated(threadobject *t)
677 {
678         /* set the state in the lock */
679
680         threads_list_lock();
681
682         t->state = THREAD_STATE_TERMINATED;
683
684         threads_list_unlock();
685 }
686
687
688 /* threads_thread_get_state ****************************************************
689
690    Returns the current state of the given thread.
691
692 *******************************************************************************/
693
694 utf *threads_thread_get_state(threadobject *t)
695 {
696         utf *u;
697
698         switch (t->state) {
699         case THREAD_STATE_NEW:
700                 u = utf_new_char("NEW");
701                 break;
702         case THREAD_STATE_RUNNABLE:
703                 u = utf_new_char("RUNNABLE");
704                 break;
705         case THREAD_STATE_BLOCKED:
706                 u = utf_new_char("BLOCKED");
707                 break;
708         case THREAD_STATE_WAITING:
709                 u = utf_new_char("WAITING");
710                 break;
711         case THREAD_STATE_TIMED_WAITING:
712                 u = utf_new_char("TIMED_WAITING");
713                 break;
714         case THREAD_STATE_TERMINATED:
715                 u = utf_new_char("TERMINATED");
716                 break;
717         default:
718                 vm_abort("threads_get_state: unknown thread state %d", t->state);
719
720                 /* keep compiler happy */
721
722                 u = NULL;
723         }
724
725         return u;
726 }
727
728
729 /* threads_thread_is_alive *****************************************************
730
731    Returns if the give thread is alive.
732
733 *******************************************************************************/
734
735 bool threads_thread_is_alive(threadobject *thread)
736 {
737         bool result;
738
739         switch (thread->state) {
740         case THREAD_STATE_NEW:
741         case THREAD_STATE_TERMINATED:
742                 result = false;
743                 break;
744
745         case THREAD_STATE_RUNNABLE:
746         case THREAD_STATE_BLOCKED:
747         case THREAD_STATE_WAITING:
748         case THREAD_STATE_TIMED_WAITING:
749                 result = true;
750                 break;
751
752         default:
753                 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
754
755                 /* keep compiler happy */
756
757                 result = false;
758         }
759
760         return result;
761 }
762
763
764 /* threads_dump ****************************************************************
765
766    Dumps info for all threads running in the JVM.  This function is
767    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
768
769 *******************************************************************************/
770
771 void threads_dump(void)
772 {
773         threadobject *t;
774
775         /* XXX we should stop the world here */
776
777         /* lock the threads lists */
778
779         threads_list_lock();
780
781         printf("Full thread dump CACAO "VERSION":\n");
782
783         /* iterate over all started threads */
784
785         for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
786                 /* print thread info */
787
788                 printf("\n");
789                 threads_thread_print_info(t);
790                 printf("\n");
791
792                 /* print trace of thread */
793
794                 threads_thread_print_stacktrace(t);
795         }
796
797         /* unlock the threads lists */
798
799         threads_list_unlock();
800 }
801
802
803 /* threads_thread_print_stacktrace *********************************************
804
805    Print the current stacktrace of the current thread.
806
807 *******************************************************************************/
808
809 void threads_thread_print_stacktrace(threadobject *thread)
810 {
811         stackframeinfo   *sfi;
812         stacktracebuffer *stb;
813         s4                dumpsize;
814
815         /* mark start of dump memory area */
816
817         dumpsize = dump_size();
818
819         /* create a stacktrace for the passed thread */
820
821         sfi = thread->_stackframeinfo;
822
823         stb = stacktrace_create(sfi);
824
825         /* print stacktrace */
826
827         if (stb != NULL)
828                 stacktrace_print_trace_from_buffer(stb);
829         else {
830                 puts("\t<<No stacktrace available>>");
831                 fflush(stdout);
832         }
833
834         dump_release(dumpsize);
835 }
836
837
838 /* threads_print_stacktrace ****************************************************
839
840    Print the current stacktrace of the current thread.
841
842 *******************************************************************************/
843
844 void threads_print_stacktrace(void)
845 {
846         threadobject *thread;
847
848         thread = THREADOBJECT;
849
850         threads_thread_print_stacktrace(thread);
851 }
852
853
854 /*
855  * These are local overrides for various environment variables in Emacs.
856  * Please do not remove this and leave it at the end of the file, where
857  * Emacs will automagically detect them.
858  * ---------------------------------------------------------------------
859  * Local variables:
860  * mode: c
861  * indent-tabs-mode: t
862  * c-basic-offset: 4
863  * tab-width: 4
864  * End:
865  * vim:noexpandtab:sw=4:ts=4:
866  */