* src/threads/critical.c (critical_compare): Renamed to
[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 7853 2007-05-02 20:40:11Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "native/jni.h"
37
38 #include "native/include/java_lang_Object.h"
39 #include "native/include/java_lang_String.h"
40 #include "native/include/java_lang_Thread.h"
41
42 #if defined(WITH_CLASSPATH_GNU)
43 # include "native/include/java_lang_VMThread.h"
44 #endif
45
46 #include "threads/critical.h"
47 #include "threads/lock-common.h"
48 #include "threads/threads-common.h"
49
50 #include "vm/builtin.h"
51 #include "vm/stringlocal.h"
52 #include "vm/vm.h"
53
54 #include "vm/jit/stacktrace.h"
55
56 #include "vmcore/class.h"
57
58 #if defined(ENABLE_STATISTICS)
59 # include "vmcore/options.h"
60 # include "vmcore/statistics.h"
61 #endif
62
63 #include "vmcore/utf8.h"
64
65
66 /* global variables ***********************************************************/
67
68 /* global threads table */
69 static threads_table_t threads_table;
70
71
72 /* prototypes *****************************************************************/
73
74 static void threads_table_init(threadobject *mainthread);
75
76
77 /* threads_preinit *************************************************************
78
79    Do some early initialization of stuff required.
80
81    ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
82    is called AFTER this function!
83
84 *******************************************************************************/
85
86 void threads_preinit(void)
87 {
88         threadobject *mainthread;
89
90         /* Initialize the threads implementation (sets the thinlock on the
91            main thread). */
92
93         threads_impl_preinit();
94
95         /* create internal thread data-structure for the main thread */
96
97         mainthread = threads_create_thread();
98
99         mainthread->object   = NULL;
100         mainthread->index    = 1;
101         mainthread->thinlock = lock_pre_compute_thinlock(mainthread->index);
102
103         /* thread is a Java thread and running */
104
105         mainthread->flags = THREAD_FLAG_JAVA;
106         mainthread->state = THREAD_STATE_RUNNABLE;
107
108         /* store the internal thread data-structure in the TSD */
109
110         threads_set_current_threadobject(mainthread);
111         
112         /* initialize the threads table with the main-thread */
113
114         threads_table_init(mainthread);
115
116         /* initialize locking subsystems */
117
118         lock_init();
119
120         /* initialize the critical section */
121
122         critical_init();
123 }
124
125
126 /* threads_table_init **********************************************************
127
128    Initialize the global threads table.  We initialize the table with
129    the main-thread, which has always the index 1.
130
131    IN:
132       mainthread....the main-thread
133
134 *******************************************************************************/
135
136 #define THREADS_INITIAL_TABLE_SIZE    8
137
138 static void threads_table_init(threadobject *mainthread)
139 {
140         threads_table_entry_t *ttemain;
141         s4                     size;
142         s4                     i;
143
144         /* initialize the threads table lock */
145
146         threads_impl_table_init();
147
148         /* initialize the table */
149
150         size = THREADS_INITIAL_TABLE_SIZE;
151
152         threads_table.table   = MNEW(threads_table_entry_t, size);
153         threads_table.size    = size;
154         threads_table.used    = 0;
155         threads_table.daemons = 0;
156
157         /* Link the entries in a freelist.  Skip 2 entries: 0 is the
158            free-list header and 1 is the main thread. */
159
160         for (i = 2; i < size; i++) {
161                 threads_table.table[i].thread = NULL;
162                 threads_table.table[i].next   = i + 1;
163         }
164
165         threads_table.table[0].next = 2;
166
167         /* terminate the freelist */
168
169         threads_table.table[size - 1].next = 0;          /* index 0 is never free */
170
171         /* insert the main-thread */
172
173         ttemain = &(threads_table.table[1]);
174
175         ttemain->thread = mainthread;
176         ttemain->next   = 0;
177
178         /* now 1 entry is used */
179
180         threads_table.used = 1;
181 }
182
183
184 /* threads_table_add ***********************************************************
185
186    Add a thread to the global threads table. The index is entered in the
187    threadobject. The thinlock value for the thread is pre-computed.
188
189    IN:
190       thread............the thread to add
191
192    RETURN VALUE:
193       The table index for the newly added thread. This value has also been
194           entered in the threadobject.
195
196 *******************************************************************************/
197
198 s4 threads_table_add(threadobject *thread)
199 {
200         threads_table_entry_t *ttefree;
201         threads_table_entry_t *ttemain;
202         threads_table_entry_t *tte;
203         s4 index;
204         s4 oldsize;
205         s4 newsize;
206         s4 i;
207
208         /* lock the threads table */
209
210         threads_table_lock();
211
212         /* get free and main entry */
213
214         ttefree = &(threads_table.table[0]);
215         ttemain = &(threads_table.table[1]);
216
217         /* get the next free index */
218
219         index = ttefree->next;
220
221         /* no entry free anymore? resize the table */
222
223         if (index == 0) {
224                 /* we must grow the table */
225
226                 oldsize = threads_table.size;
227                 newsize = oldsize * 2;
228
229                 threads_table.table = MREALLOC(threads_table.table,
230                                                                            threads_table_entry_t, oldsize, newsize);
231                 threads_table.size = newsize;
232
233                 /* the addresses have changed, get them again */
234
235                 ttefree = &(threads_table.table[0]);
236                 ttemain = &(threads_table.table[1]);
237
238                 /* link the new entries to a free list */
239
240                 for (i = oldsize; i < newsize; i++) {
241                         threads_table.table[i].thread = NULL;
242                         threads_table.table[i].next   = i + 1;
243                 }
244
245                 ttefree->next = oldsize;
246
247                 /* terminate the freelist */
248
249                 threads_table.table[newsize - 1].next = 0;   /* index 0 is never free */
250
251                 /* use the first of the new entries */
252
253                 index = ttefree->next;
254         }
255
256         /* get the entry with the assigned index */
257
258         tte = &(threads_table.table[index]);
259
260         /* store the next free index into the free-list header */
261
262         ttefree->next = tte->next;
263
264         /* store the thread in the table */
265
266         tte->thread = thread;
267
268         /* link the new entry into the used-list */
269
270         tte->next     = ttemain->next;
271         ttemain->next = index;
272
273         /* update the counters */
274
275         threads_table.used++;
276
277         if (thread->flags & THREAD_FLAG_DAEMON)
278                 threads_table.daemons++;
279
280         assert(threads_table.used < threads_table.size);
281
282         /* set the thread variables */
283
284         thread->index    = index;
285         thread->thinlock = lock_pre_compute_thinlock(index);
286
287         /* unlock the threads table */
288
289         threads_table_unlock();
290
291         return index;
292 }
293
294
295 /* threads_table_remove *******************************************************
296
297    Remove a thread from the global threads table.
298
299    IN:
300       thread............the thread to remove
301
302 ******************************************************************************/
303
304 void threads_table_remove(threadobject *thread)
305 {
306         threads_table_entry_t *ttefree;
307         threads_table_entry_t *tte;
308         s4                     index;
309         s4                     i;
310
311         /* lock the threads table */
312
313         threads_table_lock();
314
315         /* get the free entry */
316
317         ttefree = &(threads_table.table[0]);
318
319         /* get the current entry */
320
321         index = thread->index;
322         tte   = &(threads_table.table[index]);
323
324         assert(tte->thread == thread);
325
326         /* Find the entry which has the one to be removed as next entry (I
327            think it's better to do it at the removal in linear time than
328            to have a list or to do it every time we iterate over all
329            threads). */
330
331         for (i = 0; i < threads_table.size; i++) {
332                 if (threads_table.table[i].next == index) {
333                         threads_table.table[i].next = tte->next;
334                         break;
335                 }
336         }
337
338         /* clear the thread pointer in the entry */
339
340         tte->thread = NULL;
341
342         /* this entry is free now, add it to the free-list */
343
344         tte->next     = ttefree->next;
345         ttefree->next = index;
346
347         /* update the counters */
348
349         threads_table.used--;
350
351         if (thread->flags & THREAD_FLAG_DAEMON)
352                 threads_table.daemons--;
353
354         assert(threads_table.used >= 0);
355
356         /* delete the index in the threadobject to discover bugs */
357 #if !defined(NDEBUG)
358         thread->index = 0;
359 #endif
360
361         /* unlock the threads table */
362
363         threads_table_unlock();
364 }
365
366
367 /* threads_table_get ***********************************************************
368
369    Return the thread of the given table-entry index.
370
371    NOTE: It is valid to pass and index of 0, as this entry is the
372          free-list header where the thread pointer is always NULL and
373          this is thre expected behavior.
374
375 *******************************************************************************/
376
377 threadobject *threads_table_get(s4 index)
378 {
379         threadobject *thread;
380
381         /* lock the threads table */
382
383         threads_table_lock();
384
385         /* get the requested entry */
386
387         assert((index >= 0) && (index < threads_table.size));
388
389         thread = threads_table.table[index].thread;
390
391         /* unlock the threads table */
392
393         threads_table_unlock();
394
395         return thread;
396 }
397
398
399 /* threads_table_get_threads ***************************************************
400
401    Return the number of running threads.
402
403    NOTE: This function does not lock the table.
404
405 *******************************************************************************/
406
407 s4 threads_table_get_threads(void)
408 {
409         return threads_table.used;
410 }
411
412
413 /* threads_table_get_non_daemons ***********************************************
414
415    Return the number of non-daemon threads.
416
417 *******************************************************************************/
418
419 s4 threads_table_get_non_daemons(void)
420 {
421         s4 nondaemons;
422
423         /* lock the threads table */
424
425         threads_table_lock();
426
427         nondaemons = threads_table.used - threads_table.daemons;
428
429         /* unlock the threads table */
430
431         threads_table_unlock();
432
433         return nondaemons;
434 }
435
436
437 /* threads_table_first *********************************************************
438
439    Return the first thread of the threads table.
440
441    NOTE: This is always the entry with index 1 and must be the main
442          thread.
443
444 *******************************************************************************/
445
446 threadobject *threads_table_first(void)
447 {
448         threadobject *thread;
449
450         /* get the requested entry */
451
452         thread = threads_table_get(1);
453
454         return thread;
455 }
456
457
458 /* threads_table_next **********************************************************
459
460    Return the next thread of the threads table relative to the passed
461    one.
462
463 *******************************************************************************/
464
465 threadobject *threads_table_next(threadobject *thread)
466 {
467         threads_table_entry_t *tte;
468         threadobject          *next;
469         s4                     index;
470
471         index = thread->index;
472
473         /* get the passed entry */
474
475         assert((index > 0) && (index < threads_table.size));
476
477         tte = &(threads_table.table[index]);
478
479         /* get the requested entry */
480
481         next = threads_table_get(tte->next);
482
483         return next;
484 }
485
486
487 /* threads_table_dump *********************************************************
488
489    Dump the threads table for debugging purposes.
490
491 ******************************************************************************/
492
493 #if !defined(NDEBUG)
494 void threads_table_dump(void)
495 {
496         s4 i;
497         s4 size;
498         ptrint index;
499
500         size = threads_table.size;
501
502         log_println("threads table ==========");
503
504         log_println("size:    %d", size);
505         log_println("used:    %d", threads_table.used);
506         log_println("daemons: %d", threads_table.daemons);
507
508         for (i = 0; i < size; i++) {
509                 index = threads_table.table[i].next;
510
511                 if (threads_table.table[i].thread != NULL)
512                         log_println("%4d: thread=0x%08x, next=%d", i,
513                                                 threads_table.table[i].thread->tid, (int) index);
514                 else
515                         log_println("%4d: free, next=%d", i, (int) index);
516         }
517
518         log_println("end of threads table ==========");
519 }
520 #endif
521
522
523 /* threads_create_thread *******************************************************
524
525    Creates and initializes an internal thread data-structure.
526
527 *******************************************************************************/
528
529 threadobject *threads_create_thread(void)
530 {
531         threadobject *thread;
532
533         /* allocate internal thread data-structure */
534
535 #if defined(ENABLE_GC_BOEHM)
536         thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
537 #else
538         thread = NEW(threadobject);
539 #endif
540
541 #if defined(ENABLE_STATISTICS)
542         if (opt_stat)
543                 size_threadobject += sizeof(threadobject);
544 #endif
545
546         /* initialize thread data structure */
547
548         threads_init_threadobject(thread);
549         lock_init_execution_env(thread);
550
551         return thread;
552 }
553
554
555 /* threads_thread_start_internal ***********************************************
556
557    Start an internal thread in the JVM.  No Java thread objects exists
558    so far.
559
560    IN:
561       name.......UTF-8 name of the thread
562       f..........function pointer to C function to start
563
564 *******************************************************************************/
565
566 bool threads_thread_start_internal(utf *name, functionptr f)
567 {
568         threadobject       *thread;
569         java_lang_Thread   *t;
570 #if defined(WITH_CLASSPATH_GNU)
571         java_lang_VMThread *vmt;
572 #endif
573
574         /* create internal thread data-structure */
575
576         thread = threads_create_thread();
577
578         /* create the java thread object */
579
580         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
581
582         if (t == NULL)
583                 return false;
584
585 #if defined(WITH_CLASSPATH_GNU)
586         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
587
588         if (vmt == NULL)
589                 return false;
590
591         vmt->thread = t;
592         vmt->vmdata = (java_lang_Object *) thread;
593
594         t->vmThread = vmt;
595 #elif defined(WITH_CLASSPATH_CLDC1_1)
596         t->vm_thread = (java_lang_Object *) thread;
597 #endif
598
599         thread->object     = t;
600         thread->flags      = THREAD_FLAG_DAEMON;
601
602         /* set java.lang.Thread fields */
603
604         t->name     = (java_lang_String *) javastring_new(name);
605 #if defined(ENABLE_JAVASE)
606         t->daemon   = true;
607 #endif
608         t->priority = NORM_PRIORITY;
609
610         /* start the thread */
611
612         threads_impl_thread_start(thread, f);
613
614         /* everything's ok */
615
616         return true;
617 }
618
619
620 /* threads_thread_start ********************************************************
621
622    Start a Java thread in the JVM.  Only the java thread object exists
623    so far.
624
625    IN:
626       object.....the java thread object java.lang.Thread
627
628 *******************************************************************************/
629
630 void threads_thread_start(java_lang_Thread *object)
631 {
632         threadobject *thread;
633
634         /* create internal thread data-structure */
635
636         thread = threads_create_thread();
637
638         /* link the two objects together */
639
640         thread->object = object;
641
642 #if defined(ENABLE_JAVASE)
643         /* is this a daemon thread? */
644
645         if (object->daemon == true)
646                 thread->flags |= THREAD_FLAG_DAEMON;
647 #endif
648
649 #if defined(WITH_CLASSPATH_GNU)
650         assert(object->vmThread);
651         assert(object->vmThread->vmdata == NULL);
652
653         object->vmThread->vmdata = (java_lang_Object *) thread;
654 #elif defined(WITH_CLASSPATH_CLDC1_1)
655         object->vm_thread = (java_lang_Object *) thread;
656 #endif
657
658         /* Start the thread.  Don't pass a function pointer (NULL) since
659            we want Thread.run()V here. */
660
661         threads_impl_thread_start(thread, NULL);
662 }
663
664
665 /* threads_get_current_tid *****************************************************
666
667    Return the tid of the current thread.
668    
669    RETURN VALUE:
670        the current tid
671
672 *******************************************************************************/
673
674 ptrint threads_get_current_tid(void)
675 {
676         threadobject *thread;
677
678         thread = THREADOBJECT;
679
680         /* this may happen during bootstrap */
681
682         if (thread == NULL)
683                 return 0;
684
685         return (ptrint) thread->tid;
686 }
687
688
689 /* threads_thread_get_state ****************************************************
690
691    Returns the current state of the given thread.
692
693 *******************************************************************************/
694
695 utf *threads_thread_get_state(threadobject *thread)
696 {
697         utf *u;
698
699         switch (thread->state) {
700         case THREAD_STATE_NEW:
701                 u = utf_new_char("NEW");
702                 break;
703         case THREAD_STATE_RUNNABLE:
704                 u = utf_new_char("RUNNABLE");
705                 break;
706         case THREAD_STATE_BLOCKED:
707                 u = utf_new_char("BLOCKED");
708                 break;
709         case THREAD_STATE_WAITING:
710                 u = utf_new_char("WAITING");
711                 break;
712         case THREAD_STATE_TIMED_WAITING:
713                 u = utf_new_char("TIMED_WAITING");
714                 break;
715         case THREAD_STATE_TERMINATED:
716                 u = utf_new_char("TERMINATED");
717                 break;
718         default:
719                 vm_abort("threads_get_state: unknown thread state %d", thread->state);
720         }
721
722         return u;
723 }
724
725
726 /* threads_thread_is_alive *****************************************************
727
728    Returns if the give thread is alive.
729
730 *******************************************************************************/
731
732 bool threads_thread_is_alive(threadobject *thread)
733 {
734         bool result;
735
736         switch (thread->state) {
737         case THREAD_STATE_NEW:
738         case THREAD_STATE_TERMINATED:
739                 result = false;
740                 break;
741
742         case THREAD_STATE_RUNNABLE:
743         case THREAD_STATE_BLOCKED:
744         case THREAD_STATE_WAITING:
745         case THREAD_STATE_TIMED_WAITING:
746                 result = true;
747                 break;
748
749         default:
750                 vm_abort("threads_is_alive: unknown thread state %d", thread->state);
751         }
752
753         return result;
754 }
755
756
757 /* threads_dump ****************************************************************
758
759    Dumps info for all threads running in the JVM.  This function is
760    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
761
762 *******************************************************************************/
763
764 void threads_dump(void)
765 {
766         threadobject     *thread;
767         java_lang_Thread *object;
768         utf              *name;
769
770         /* XXX we should stop the world here */
771
772         printf("Full thread dump CACAO "VERSION":\n");
773
774         /* iterate over all started threads */
775
776         for (thread = threads_table_first(); thread != NULL;
777                  thread = threads_table_next(thread)) {
778                 /* get thread object */
779
780                 object = thread->object;
781
782                 /* the thread may be currently in initalization, don't print it */
783
784                 if (object != NULL) {
785                         /* get thread name */
786
787 #if defined(ENABLE_JAVASE)
788                         name = javastring_toutf((java_objectheader *) object->name, false);
789 #elif defined(ENABLE_JAVAME_CLDC1_1)
790                         name = object->name;
791 #endif
792
793                         printf("\n\"");
794                         utf_display_printable_ascii(name);
795                         printf("\"");
796
797                         if (thread->flags & THREAD_FLAG_DAEMON)
798                                 printf(" daemon");
799
800                         printf(" prio=%d", object->priority);
801
802 #if SIZEOF_VOID_P == 8
803                         printf(" tid=0x%016lx (%ld)",
804                                    (ptrint) thread->tid, (ptrint) thread->tid);
805 #else
806                         printf(" tid=0x%08x (%d)",
807                                    (ptrint) thread->tid, (ptrint) thread->tid);
808 #endif
809
810                         /* print thread state */
811
812                         switch (thread->state) {
813                         case THREAD_STATE_NEW:
814                                 printf(" new");
815                                 break;
816                         case THREAD_STATE_RUNNABLE:
817                                 printf(" runnable");
818                                 break;
819                         case THREAD_STATE_BLOCKED:
820                                 printf(" blocked");
821                                 break;
822                         case THREAD_STATE_WAITING:
823                                 printf(" waiting");
824                                 break;
825                         case THREAD_STATE_TIMED_WAITING:
826                                 printf(" waiting on condition");
827                                 break;
828                         case THREAD_STATE_TERMINATED:
829                                 printf(" terminated");
830                                 break;
831                         default:
832                                 vm_abort("threads_dump: unknown thread state %d",
833                                                  thread->state);
834                         }
835
836                         printf("\n");
837
838                         /* print trace of thread */
839
840                         threads_thread_print_stacktrace(thread);
841                 }
842         }
843 }
844
845
846 /* threads_thread_print_stacktrace *********************************************
847
848    Print the current stacktrace of the current thread.
849
850 *******************************************************************************/
851
852 void threads_thread_print_stacktrace(threadobject *thread)
853 {
854         stackframeinfo   *sfi;
855         stacktracebuffer *stb;
856         s4                dumpsize;
857
858         /* mark start of dump memory area */
859
860         dumpsize = dump_size();
861
862         /* create a stacktrace for the passed thread */
863
864         sfi = thread->_stackframeinfo;
865
866         stb = stacktrace_create(sfi);
867
868         /* print stacktrace */
869
870         if (stb != NULL)
871                 stacktrace_print_trace_from_buffer(stb);
872         else {
873                 puts("\t<<No stacktrace available>>");
874                 fflush(stdout);
875         }
876
877         dump_release(dumpsize);
878 }
879
880
881 /* threads_print_stacktrace ****************************************************
882
883    Print the current stacktrace of the current thread.
884
885 *******************************************************************************/
886
887 void threads_print_stacktrace(void)
888 {
889         threadobject *thread;
890
891         thread = THREADOBJECT;
892
893         threads_thread_print_stacktrace(thread);
894 }
895
896
897 /*
898  * These are local overrides for various environment variables in Emacs.
899  * Please do not remove this and leave it at the end of the file, where
900  * Emacs will automagically detect them.
901  * ---------------------------------------------------------------------
902  * Local variables:
903  * mode: c
904  * indent-tabs-mode: t
905  * c-basic-offset: 4
906  * tab-width: 4
907  * End:
908  * vim:noexpandtab:sw=4:ts=4:
909  */