* src/vm/jit/stacktrace.c (stacktrace_dump_trace): Changed signature.
[cacao.git] / src / threads / native / threads.c
1 /* src/threads/native/threads.c - native threads support
2
3    Copyright (C) 1996-2005, 2006 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    Contact: cacao@cacaojvm.org
26
27    Authors: Stefan Ring
28
29    Changes: Christian Thalinger
30                         Edwin Steiner
31
32    $Id: threads.c 5805 2006-10-19 09:32:29Z twisti $
33
34 */
35
36
37 #include "config.h"
38
39 /* XXX cleanup these includes */
40
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <signal.h>
47 #include <sys/time.h>
48 #include <time.h>
49 #include <errno.h>
50
51 #include <pthread.h>
52
53 #include "vm/types.h"
54
55 #include "arch.h"
56
57 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
58 # include "machine-instr.h"
59 #else
60 # include "threads/native/generic-primitives.h"
61 #endif
62
63 #include "mm/boehm.h"
64 #include "mm/memory.h"
65 #include "native/native.h"
66 #include "native/include/java_lang_Object.h"
67 #include "native/include/java_lang_Throwable.h"
68 #include "native/include/java_lang_Thread.h"
69 #include "native/include/java_lang_ThreadGroup.h"
70 #include "native/include/java_lang_VMThread.h"
71 #include "threads/native/threads.h"
72 #include "toolbox/avl.h"
73 #include "toolbox/logging.h"
74 #include "vm/builtin.h"
75 #include "vm/exceptions.h"
76 #include "vm/global.h"
77 #include "vm/loader.h"
78 #include "vm/options.h"
79 #include "vm/stringlocal.h"
80 #include "vm/vm.h"
81 #include "vm/jit/asmpart.h"
82
83 #if !defined(__DARWIN__)
84 # if defined(__LINUX__)
85 #  define GC_LINUX_THREADS
86 # elif defined(__MIPS__)
87 #  define GC_IRIX_THREADS
88 # endif
89 # include <semaphore.h>
90 # include "boehm-gc/include/gc.h"
91 #endif
92
93 #if defined(ENABLE_JVMTI)
94 #include "native/jvmti/cacaodbg.h"
95 #endif
96
97 #if defined(__DARWIN__)
98 /* Darwin has no working semaphore implementation.  This one is taken
99    from Boehm-GC. */
100
101 /*
102    This is a very simple semaphore implementation for darwin. It
103    is implemented in terms of pthreads calls so it isn't async signal
104    safe. This isn't a problem because signals aren't used to
105    suspend threads on darwin.
106 */
107    
108 static int sem_init(sem_t *sem, int pshared, int value)
109 {
110         if (pshared)
111                 assert(0);
112
113         sem->value = value;
114     
115         if (pthread_mutex_init(&sem->mutex, NULL) < 0)
116                 return -1;
117
118         if (pthread_cond_init(&sem->cond, NULL) < 0)
119                 return -1;
120
121         return 0;
122 }
123
124 static int sem_post(sem_t *sem)
125 {
126         if (pthread_mutex_lock(&sem->mutex) < 0)
127                 return -1;
128
129         sem->value++;
130
131         if (pthread_cond_signal(&sem->cond) < 0) {
132                 pthread_mutex_unlock(&sem->mutex);
133                 return -1;
134         }
135
136         if (pthread_mutex_unlock(&sem->mutex) < 0)
137                 return -1;
138
139         return 0;
140 }
141
142 static int sem_wait(sem_t *sem)
143 {
144         if (pthread_mutex_lock(&sem->mutex) < 0)
145                 return -1;
146
147         while (sem->value == 0) {
148                 pthread_cond_wait(&sem->cond, &sem->mutex);
149         }
150
151         sem->value--;
152
153         if (pthread_mutex_unlock(&sem->mutex) < 0)
154                 return -1;    
155
156         return 0;
157 }
158
159 static int sem_destroy(sem_t *sem)
160 {
161         if (pthread_cond_destroy(&sem->cond) < 0)
162                 return -1;
163
164         if (pthread_mutex_destroy(&sem->mutex) < 0)
165                 return -1;
166
167         return 0;
168 }
169 #endif /* defined(__DARWIN__) */
170
171
172 /* internally used constants **************************************************/
173
174 /* CAUTION: Do not change these values. Boehm GC code depends on them.        */
175 #define STOPWORLD_FROM_GC               1
176 #define STOPWORLD_FROM_CLASS_NUMBERING  2
177
178 #define THREADS_INITIAL_TABLE_SIZE      8
179
180
181 /* startupinfo *****************************************************************
182
183    Struct used to pass info from threads_start_thread to 
184    threads_startup_thread.
185
186 ******************************************************************************/
187
188 typedef struct {
189         threadobject *thread;      /* threadobject for this thread             */
190         functionptr   function;    /* function to run in the new thread        */
191         sem_t        *psem;        /* signals when thread has been entered     */
192                                    /* in the thread list                       */
193         sem_t        *psem_first;  /* signals when pthread_create has returned */
194 } startupinfo;
195
196
197 /* prototypes *****************************************************************/
198
199 static void threads_table_init(void);
200 static s4 threads_table_add(threadobject *thread);
201 static void threads_table_remove(threadobject *thread);
202 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
203
204 #if !defined(NDEBUG)
205 static void threads_table_dump(FILE *file);
206 #endif
207
208 /******************************************************************************/
209 /* GLOBAL VARIABLES                                                           */
210 /******************************************************************************/
211
212 /* the main thread                                                            */
213 threadobject *mainthreadobj;
214
215 static methodinfo *method_thread_init;
216 static methodinfo *method_threadgroup_add;
217
218 /* the thread object of the current thread                                    */
219 /* This is either a thread-local variable defined with __thread, or           */
220 /* a thread-specific value stored with key threads_current_threadobject_key.  */
221 #if defined(HAVE___THREAD)
222 __thread threadobject *threads_current_threadobject;
223 #else
224 pthread_key_t threads_current_threadobject_key;
225 #endif
226
227 /* global threads table                                                       */
228 static threads_table_t threads_table;
229
230 /* global compiler mutex                                                      */
231 static pthread_mutex_rec_t compiler_mutex;
232
233 /* global mutex for changing the thread list                                  */
234 static pthread_mutex_t threadlistlock;
235
236 /* global mutex for stop-the-world                                            */
237 static pthread_mutex_t stopworldlock;
238
239 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
240 /* being stopped                                                              */
241 static volatile int stopworldwhere;
242
243 /* semaphore used for acknowleding thread suspension                          */
244 static sem_t suspend_ack;
245 #if defined(__MIPS__)
246 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
247 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
248 #endif
249
250 static pthread_attr_t threadattr;
251
252 /* mutexes used by the fake atomic instructions                               */
253 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
254 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
255 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
256 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
257 #endif
258
259
260 /******************************************************************************/
261 /* Recursive Mutex Implementation for Darwin                                  */
262 /******************************************************************************/
263
264 #if defined(MUTEXSIM)
265
266 /* We need this for older MacOSX (10.1.x) */
267
268 void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
269 {
270         pthread_mutex_init(&m->mutex, NULL);
271         m->count = 0;
272 }
273
274 void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
275 {
276         pthread_mutex_destroy(&m->mutex);
277 }
278
279 void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
280 {
281         for (;;) {
282                 if (!m->count)
283                 {
284                         pthread_mutex_lock(&m->mutex);
285                         m->owner = pthread_self();
286                         m->count++;
287                         break;
288                 }
289                 else {
290                         if (m->owner != pthread_self()) {
291                                 pthread_mutex_lock(&m->mutex);
292                         }
293                         else {
294                                 m->count++;
295                                 break;
296                         }
297                 }
298         }
299 }
300
301 void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
302 {
303         if (!--m->count)
304                 pthread_mutex_unlock(&m->mutex);
305 }
306
307 #endif /* defined(MUTEXSIM) */
308
309
310 /* threads_sem_init ************************************************************
311  
312    Initialize a semaphore. Checks against errors and interruptions.
313
314    IN:
315        sem..............the semaphore to initialize
316            shared...........true if this semaphore will be shared between processes
317            value............the initial value for the semaphore
318    
319 *******************************************************************************/
320
321 void threads_sem_init(sem_t *sem, bool shared, int value)
322 {
323         int r;
324
325         assert(sem);
326
327         do {
328                 r = sem_init(sem, shared, value);
329                 if (r == 0)
330                         return;
331         } while (errno == EINTR);
332
333         vm_abort("sem_init failed: %s", strerror(errno));
334 }
335
336
337 /* threads_sem_wait ************************************************************
338  
339    Wait for a semaphore, non-interruptible.
340
341    IMPORTANT: Always use this function instead of `sem_wait` directly, as
342               `sem_wait` may be interrupted by signals!
343   
344    IN:
345        sem..............the semaphore to wait on
346    
347 *******************************************************************************/
348
349 void threads_sem_wait(sem_t *sem)
350 {
351         int r;
352
353         assert(sem);
354
355         do {
356                 r = sem_wait(sem);
357                 if (r == 0)
358                         return;
359         } while (errno == EINTR);
360
361         vm_abort("sem_wait failed: %s", strerror(errno));
362 }
363
364
365 /* threads_sem_post ************************************************************
366  
367    Increase the count of a semaphore. Checks for errors.
368
369    IN:
370        sem..............the semaphore to increase the count of
371    
372 *******************************************************************************/
373
374 void threads_sem_post(sem_t *sem)
375 {
376         int r;
377
378         assert(sem);
379
380         /* unlike sem_wait, sem_post is not interruptible */
381
382         r = sem_post(sem);
383         if (r == 0)
384                 return;
385
386         vm_abort("sem_post failed: %s", strerror(errno));
387 }
388
389
390 /* threads_set_thread_priority *************************************************
391
392    Set the priority of the given thread.
393
394    IN:
395       tid..........thread id
396           priority.....priority to set
397
398 ******************************************************************************/
399
400 static void threads_set_thread_priority(pthread_t tid, int priority)
401 {
402         struct sched_param schedp;
403         int policy;
404
405         pthread_getschedparam(tid, &policy, &schedp);
406         schedp.sched_priority = priority;
407         pthread_setschedparam(tid, policy, &schedp);
408 }
409
410
411 /* compiler_lock ***************************************************************
412
413    Enter the compiler lock.
414
415 ******************************************************************************/
416
417 void compiler_lock(void)
418 {
419         pthread_mutex_lock_rec(&compiler_mutex);
420 }
421
422
423 /* compiler_unlock *************************************************************
424
425    Release the compiler lock.
426
427 ******************************************************************************/
428
429 void compiler_unlock(void)
430 {
431         pthread_mutex_unlock_rec(&compiler_mutex);
432 }
433
434
435 /* lock_stopworld **************************************************************
436
437    Enter the stopworld lock, specifying why the world shall be stopped.
438
439    IN:
440       where........ STOPWORLD_FROM_GC              (1) from within GC
441                     STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
442
443 ******************************************************************************/
444
445 void lock_stopworld(int where)
446 {
447         pthread_mutex_lock(&stopworldlock);
448         stopworldwhere = where;
449 }
450
451
452 /* unlock_stopworld ************************************************************
453
454    Release the stopworld lock.
455
456 ******************************************************************************/
457
458 void unlock_stopworld(void)
459 {
460         stopworldwhere = 0;
461         pthread_mutex_unlock(&stopworldlock);
462 }
463
464 #if !defined(__DARWIN__)
465 /* Caller must hold threadlistlock */
466 static int threads_cast_sendsignals(int sig, int count)
467 {
468         /* Count threads */
469         threadobject *tobj = mainthreadobj;
470         threadobject *self = THREADOBJECT;
471
472         if (count == 0) {
473                 do {
474                         count++;
475                         tobj = tobj->next;
476                 } while (tobj != mainthreadobj);
477         }
478
479         assert(tobj == mainthreadobj);
480
481         do {
482                 if (tobj != self)
483                         pthread_kill(tobj->tid, sig);
484                 tobj = tobj->next;
485         } while (tobj != mainthreadobj);
486
487         return count - 1;
488 }
489
490 #else
491
492 static void threads_cast_darwinstop(void)
493 {
494         threadobject *tobj = mainthreadobj;
495         threadobject *self = THREADOBJECT;
496
497         do {
498                 if (tobj != self)
499                 {
500                         thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
501                         mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
502 #if defined(__I386__)
503                         i386_thread_state_t thread_state;
504 #else
505                         ppc_thread_state_t thread_state;
506 #endif
507                         mach_port_t thread = tobj->mach_thread;
508                         kern_return_t r;
509
510                         r = thread_suspend(thread);
511                         if (r != KERN_SUCCESS) {
512                                 log_text("thread_suspend failed");
513                                 assert(0);
514                         }
515
516                         r = thread_get_state(thread, flavor,
517                                 (natural_t*)&thread_state, &thread_state_count);
518                         if (r != KERN_SUCCESS) {
519                                 log_text("thread_get_state failed");
520                                 assert(0);
521                         }
522
523                         thread_restartcriticalsection(&thread_state);
524
525                         r = thread_set_state(thread, flavor,
526                                 (natural_t*)&thread_state, thread_state_count);
527                         if (r != KERN_SUCCESS) {
528                                 log_text("thread_set_state failed");
529                                 assert(0);
530                         }
531                 }
532                 tobj = tobj->next;
533         } while (tobj != mainthreadobj);
534 }
535
536 static void threads_cast_darwinresume(void)
537 {
538         threadobject *tobj = mainthreadobj;
539         threadobject *self = THREADOBJECT;
540
541         do {
542                 if (tobj != self)
543                 {
544                         mach_port_t thread = tobj->mach_thread;
545                         kern_return_t r;
546
547                         r = thread_resume(thread);
548                         if (r != KERN_SUCCESS) {
549                                 log_text("thread_resume failed");
550                                 assert(0);
551                         }
552                 }
553                 tobj = tobj->next;
554         } while (tobj != mainthreadobj);
555 }
556
557 #endif
558
559 #if defined(__MIPS__)
560 static void threads_cast_irixresume(void)
561 {
562         pthread_mutex_lock(&suspend_ack_lock);
563         pthread_cond_broadcast(&suspend_cond);
564         pthread_mutex_unlock(&suspend_ack_lock);
565 }
566 #endif
567
568 void threads_cast_stopworld(void)
569 {
570         int count, i;
571         lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
572         pthread_mutex_lock(&threadlistlock);
573 #if defined(__DARWIN__)
574         threads_cast_darwinstop();
575 #elif defined(__CYGWIN__)
576         /* TODO */
577         assert(0);
578 #else
579         count = threads_cast_sendsignals(GC_signum1(), 0);
580         for (i=0; i<count; i++)
581                 threads_sem_wait(&suspend_ack);
582 #endif
583         pthread_mutex_unlock(&threadlistlock);
584 }
585
586 void threads_cast_startworld(void)
587 {
588         pthread_mutex_lock(&threadlistlock);
589 #if defined(__DARWIN__)
590         threads_cast_darwinresume();
591 #elif defined(__MIPS__)
592         threads_cast_irixresume();
593 #elif defined(__CYGWIN__)
594         /* TODO */
595         assert(0);
596 #else
597         threads_cast_sendsignals(GC_signum2(), -1);
598 #endif
599         pthread_mutex_unlock(&threadlistlock);
600         unlock_stopworld();
601 }
602
603 #if !defined(__DARWIN__)
604 static void threads_sigsuspend_handler(ucontext_t *ctx)
605 {
606         int sig;
607         sigset_t sigs;
608
609         /* XXX TWISTI: this is just a quick hack */
610 #if defined(ENABLE_JIT)
611         thread_restartcriticalsection(ctx);
612 #endif
613
614         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
615            (not POSIX async-safe). */
616 #if defined(__IRIX__)
617         pthread_mutex_lock(&suspend_ack_lock);
618         threads_sem_post(&suspend_ack);
619         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
620         pthread_mutex_unlock(&suspend_ack_lock);
621 #elif defined(__CYGWIN__)
622         /* TODO */
623         assert(0);
624 #else
625         threads_sem_post(&suspend_ack);
626
627         sig = GC_signum2();
628         sigfillset(&sigs);
629         sigdelset(&sigs, sig);
630         sigsuspend(&sigs);
631 #endif
632 }
633
634 /* This function is called from Boehm GC code. */
635
636 int cacao_suspendhandler(ucontext_t *ctx)
637 {
638         if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
639                 return 0;
640
641         threads_sigsuspend_handler(ctx);
642         return 1;
643 }
644 #endif
645
646
647 /* threads_set_current_threadobject ********************************************
648
649    Set the current thread object.
650    
651    IN:
652       thread.......the thread object to set
653
654 *******************************************************************************/
655
656 static void threads_set_current_threadobject(threadobject *thread)
657 {
658 #if !defined(HAVE___THREAD)
659         pthread_setspecific(threads_current_threadobject_key, thread);
660 #else
661         threads_current_threadobject = thread;
662 #endif
663 }
664
665
666 /* threads_get_current_threadobject ********************************************
667
668    Return the threadobject of the current thread.
669    
670    RETURN VALUE:
671        the current threadobject * (an instance of java.lang.VMThread)
672
673 *******************************************************************************/
674
675 threadobject *threads_get_current_threadobject(void)
676 {
677         return THREADOBJECT;
678 }
679
680
681 /* threads_preinit *************************************************************
682
683    Do some early initialization of stuff required.
684
685 *******************************************************************************/
686
687 void threads_preinit(void)
688 {
689 #ifndef MUTEXSIM
690         pthread_mutexattr_t mutexattr;
691         pthread_mutexattr_init(&mutexattr);
692         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
693         pthread_mutex_init(&compiler_mutex, &mutexattr);
694         pthread_mutexattr_destroy(&mutexattr);
695 #else
696         pthread_mutex_init_rec(&compiler_mutex);
697 #endif
698
699         pthread_mutex_init(&threadlistlock, NULL);
700         pthread_mutex_init(&stopworldlock, NULL);
701
702         /* Allocate something so the garbage collector's signal handlers
703            are installed. */
704         heap_allocate(1, false, NULL);
705
706         mainthreadobj = NEW(threadobject);
707         mainthreadobj->tid = pthread_self();
708         mainthreadobj->index = 1;
709         mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
710         
711 #if !defined(HAVE___THREAD)
712         pthread_key_create(&threads_current_threadobject_key, NULL);
713 #endif
714         threads_set_current_threadobject(mainthreadobj);
715
716         threads_sem_init(&suspend_ack, 0, 0);
717
718         /* initialize the threads table */
719
720         threads_table_init();
721
722         /* initialize subsystems */
723
724         lock_init();
725
726         critical_init();
727 }
728
729
730 /* threads_init ****************************************************************
731
732    Initializes the threads required by the JVM: main, finalizer.
733
734 *******************************************************************************/
735
736 bool threads_init(void)
737 {
738         java_lang_String      *threadname;
739         java_lang_Thread      *mainthread;
740         java_lang_ThreadGroup *threadgroup;
741         threadobject          *tempthread;
742
743         tempthread = mainthreadobj;
744
745         /* XXX We have to find a new way to free lock records */
746         /*     with the new locking algorithm.                */
747         /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
748
749         /* This is kinda tricky, we grow the java.lang.Thread object so we
750            can keep the execution environment there. No Thread object must
751            have been created at an earlier time. */
752
753         class_java_lang_VMThread->instancesize = sizeof(threadobject);
754
755         /* get methods we need in this file */
756
757         method_thread_init =
758                 class_resolveclassmethod(class_java_lang_Thread,
759                                                                  utf_init,
760                                                                  utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
761                                                                  class_java_lang_Thread,
762                                                                  true);
763
764         if (method_thread_init == NULL)
765                 return false;
766
767         method_threadgroup_add =
768                 class_resolveclassmethod(class_java_lang_ThreadGroup,
769                                                                  utf_new_char("addThread"),
770                                                                  utf_new_char("(Ljava/lang/Thread;)V"),
771                                                                  class_java_lang_ThreadGroup,
772                                                                  true);
773
774         if (method_threadgroup_add == NULL)
775                 return false;
776
777         /* create a VMThread */
778
779         mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
780
781         if (mainthreadobj == NULL)
782                 return false;
783
784         FREE(tempthread, threadobject);
785
786         threads_init_threadobject(&mainthreadobj->o);
787
788         threads_set_current_threadobject(mainthreadobj);
789
790         lock_init_execution_env(mainthreadobj);
791
792         mainthreadobj->next = mainthreadobj;
793         mainthreadobj->prev = mainthreadobj;
794
795         threads_table_add(mainthreadobj);
796
797         /* mark main thread as Java thread */
798
799         mainthreadobj->flags = THREAD_FLAG_JAVA;
800
801 #if defined(ENABLE_INTRP)
802         /* create interpreter stack */
803
804         if (opt_intrp) {
805                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
806                 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
807         }
808 #endif
809
810         threadname = javastring_new(utf_new_char("main"));
811
812         /* allocate and init ThreadGroup */
813
814         threadgroup = (java_lang_ThreadGroup *)
815                 native_new_and_init(class_java_lang_ThreadGroup);
816
817         if (!threadgroup)
818                 throw_exception_exit();
819
820         /* create a Thread */
821
822         mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
823
824         if (mainthread == NULL)
825                 throw_exception_exit();
826
827         mainthreadobj->o.thread = mainthread;
828
829         /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
830
831         (void) vm_call_method(method_thread_init, (java_objectheader *) mainthread,
832                                                   mainthreadobj, threadname, NORM_PRIORITY, false);
833
834         if (*exceptionptr)
835                 return false;
836
837         mainthread->group = threadgroup;
838
839         /* add mainthread to ThreadGroup */
840
841         (void) vm_call_method(method_threadgroup_add, 
842                                                   (java_objectheader *) threadgroup,
843                                                   mainthread);
844
845         if (*exceptionptr)
846                 return false;
847
848         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
849
850         /* initialize the thread attribute object */
851
852         if (pthread_attr_init(&threadattr)) {
853                 log_println("pthread_attr_init failed: %s", strerror(errno));
854                 return false;
855         }
856
857         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
858
859         /* everything's ok */
860
861         return true;
862 }
863
864
865 /* threads_table_init *********************************************************
866
867    Initialize the global threads table.
868
869 ******************************************************************************/
870
871 static void threads_table_init(void)
872 {
873         s4 size;
874         s4 i;
875
876         size = THREADS_INITIAL_TABLE_SIZE;
877
878         threads_table.size = size;
879         threads_table.table = MNEW(threads_table_entry_t, size);
880
881         /* link the entries in a freelist */
882
883         for (i=0; i<size; ++i) {
884                 threads_table.table[i].nextfree = i+1;
885         }
886
887         /* terminate the freelist */
888
889         threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
890 }
891
892
893 /* threads_table_add **********************************************************
894
895    Add a thread to the global threads table. The index is entered in the
896    threadobject. The thinlock value for the thread is pre-computed.
897
898    IN:
899       thread............the thread to add
900
901    RETURN VALUE:
902       The table index for the newly added thread. This value has also been
903           entered in the threadobject.
904
905    PRE-CONDITION:
906       The caller must hold the threadlistlock!
907
908 ******************************************************************************/
909
910 static s4 threads_table_add(threadobject *thread)
911 {
912         s4 index;
913         s4 oldsize;
914         s4 newsize;
915         s4 i;
916
917         /* table[0] serves as the head of the freelist */
918
919         index = threads_table.table[0].nextfree;
920
921         /* if we got a free index, use it */
922
923         if (index) {
924 got_an_index:
925                 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
926                 threads_table.table[index].thread = thread;
927                 thread->index = index;
928                 thread->thinlock = lock_pre_compute_thinlock(index);
929                 return index;
930         }
931
932         /* we must grow the table */
933
934         oldsize = threads_table.size;
935         newsize = oldsize * 2;
936
937         threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
938                                                                    oldsize, newsize);
939         threads_table.size = newsize;
940
941         /* link the new entries to a free list */
942
943         for (i=oldsize; i<newsize; ++i) {
944                 threads_table.table[i].nextfree = i+1;
945         }
946
947         /* terminate the freelist */
948
949         threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
950
951         /* use the first of the new entries */
952
953         index = oldsize;
954         goto got_an_index;
955 }
956
957
958 /* threads_table_remove *******************************************************
959
960    Remove a thread from the global threads table.
961
962    IN:
963       thread............the thread to remove
964
965    PRE-CONDITION:
966       The caller must hold the threadlistlock!
967
968 ******************************************************************************/
969
970 static void threads_table_remove(threadobject *thread)
971 {
972         s4 index;
973
974         index = thread->index;
975
976         /* put the index into the freelist */
977
978         threads_table.table[index] = threads_table.table[0];
979         threads_table.table[0].nextfree = index;
980
981         /* delete the index in the threadobject to discover bugs */
982 #if !defined(NDEBUG)
983         thread->index = 0;
984 #endif
985 }
986
987 /* threads_init_threadobject **************************************************
988
989    Initialize implementation fields of a java.lang.VMThread.
990
991    IN:
992       t............the java.lang.VMThread
993
994 ******************************************************************************/
995
996 void threads_init_threadobject(java_lang_VMThread *t)
997 {
998         threadobject *thread = (threadobject*) t;
999
1000         thread->tid = pthread_self();
1001
1002         thread->index = 0;
1003
1004         /* TODO destroy all those things */
1005         pthread_mutex_init(&(thread->joinmutex), NULL);
1006         pthread_cond_init(&(thread->joincond), NULL);
1007
1008         pthread_mutex_init(&(thread->waitmutex), NULL);
1009         pthread_cond_init(&(thread->waitcond), NULL);
1010
1011         thread->interrupted = false;
1012         thread->signaled = false;
1013         thread->sleeping = false;
1014 }
1015
1016
1017 /* threads_startup_thread ******************************************************
1018
1019    Thread startup function called by pthread_create.
1020
1021    Thread which have a startup.function != NULL are marked as internal
1022    threads. All other threads are threated as normal Java threads.
1023
1024    NOTE: This function is not called directly by pthread_create. The Boehm GC
1025          inserts its own GC_start_routine in between, which then calls
1026                  threads_startup.
1027
1028    IN:
1029       t............the argument passed to pthread_create, ie. a pointer to
1030                        a startupinfo struct. CAUTION: When the `psem` semaphore
1031                                    is posted, the startupinfo struct becomes invalid! (It
1032                                    is allocated on the stack of threads_start_thread.)
1033
1034 ******************************************************************************/
1035
1036 static void *threads_startup_thread(void *t)
1037 {
1038         startupinfo  *startup;
1039         threadobject *thread;
1040         sem_t        *psem;
1041         threadobject *tnext;
1042         methodinfo   *method;
1043         functionptr   function;
1044
1045 #if defined(ENABLE_INTRP)
1046         u1 *intrp_thread_stack;
1047
1048         /* create interpreter stack */
1049
1050         if (opt_intrp) {
1051                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1052                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1053         }
1054         else
1055                 intrp_thread_stack = NULL;
1056 #endif
1057
1058         /* get passed startupinfo structure and the values in there */
1059
1060         startup = t;
1061         t = NULL; /* make sure it's not used wrongly */
1062
1063         thread   = startup->thread;
1064         function = startup->function;
1065         psem     = startup->psem;
1066
1067         /* Seems like we've encountered a situation where thread->tid was not set by
1068          * pthread_create. We alleviate this problem by waiting for pthread_create
1069          * to return. */
1070         threads_sem_wait(startup->psem_first);
1071
1072         /* set the thread object */
1073
1074 #if defined(__DARWIN__)
1075         thread->mach_thread = mach_thread_self();
1076 #endif
1077         threads_set_current_threadobject(thread);
1078
1079         /* insert the thread into the threadlist and the threads table */
1080
1081         pthread_mutex_lock(&threadlistlock);
1082
1083         thread->prev = mainthreadobj;
1084         thread->next = tnext = mainthreadobj->next;
1085         mainthreadobj->next = thread;
1086         tnext->prev = thread;
1087
1088         threads_table_add(thread);
1089
1090         pthread_mutex_unlock(&threadlistlock);
1091
1092         /* init data structures of this thread */
1093
1094         lock_init_execution_env(thread);
1095
1096         /* tell threads_startup_thread that we registered ourselves */
1097         /* CAUTION: *startup becomes invalid with this!             */
1098
1099         startup = NULL;
1100         threads_sem_post(psem);
1101
1102         /* set our priority */
1103
1104         threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1105
1106 #if defined(ENABLE_INTRP)
1107         /* set interpreter stack */
1108
1109         if (opt_intrp)
1110                 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1111 #endif
1112
1113 #if defined(ENABLE_JVMTI)
1114         /* fire thread start event */
1115
1116         if (jvmti) 
1117                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1118 #endif
1119
1120         /* find and run the Thread.run()V method if no other function was passed */
1121
1122         if (function == NULL) {
1123                 /* this is a normal Java thread */
1124
1125                 thread->flags |= THREAD_FLAG_JAVA;
1126
1127                 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1128                                                                                   utf_run,
1129                                                                                   utf_void__void,
1130                                                                                   thread->o.header.vftbl->class,
1131                                                                                   true);
1132
1133                 if (method == NULL)
1134                         throw_exception();
1135
1136                 /* increase total started thread count */
1137
1138                 _Jv_jvm->total_started_thread_count++;
1139
1140                 (void) vm_call_method(method, (java_objectheader *) thread);
1141         }
1142         else {
1143                 /* this is an internal thread */
1144
1145                 thread->flags |= THREAD_FLAG_INTERNAL;
1146
1147                 /* increase total started thread count */
1148
1149                 _Jv_jvm->total_started_thread_count++;
1150
1151                 /* call passed function, e.g. finalizer_thread */
1152
1153                 (function)();
1154         }
1155
1156 #if defined(ENABLE_JVMTI)
1157         /* fire thread end event */
1158
1159         if (jvmti)
1160                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1161 #endif
1162
1163         threads_detach_thread(thread);
1164
1165         return NULL;
1166 }
1167
1168
1169 /* threads_start_thread ********************************************************
1170
1171    Start a thread in the JVM.
1172
1173    IN:
1174       t............the java.lang.Thread object
1175           function.....function to run in the new thread. NULL means that the
1176                        "run" method of the object `t` should be called
1177
1178 ******************************************************************************/
1179
1180 void threads_start_thread(java_lang_Thread *t, functionptr function)
1181 {
1182         sem_t          sem;
1183         sem_t          sem_first;
1184         pthread_attr_t attr;
1185         startupinfo    startup;
1186         threadobject  *thread;
1187
1188         thread = (threadobject *) t->vmThread;
1189
1190         /* fill startupinfo structure passed by pthread_create to
1191          * threads_startup_thread */
1192
1193         startup.thread     = thread;
1194         startup.function   = function;       /* maybe we don't call Thread.run()V */
1195         startup.psem       = &sem;
1196         startup.psem_first = &sem_first;
1197
1198         threads_sem_init(&sem, 0, 0);
1199         threads_sem_init(&sem_first, 0, 0);
1200
1201         /* initialize thread attribute object */
1202
1203         if (pthread_attr_init(&attr))
1204                 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1205
1206         /* initialize thread stacksize */
1207
1208         if (pthread_attr_setstacksize(&attr, opt_stacksize))
1209                 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1210
1211         /* create the thread */
1212
1213         if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1214                 vm_abort("pthread_create failed: %s", strerror(errno));
1215
1216         /* signal that pthread_create has returned, so thread->tid is valid */
1217
1218         threads_sem_post(&sem_first);
1219
1220         /* wait here until the thread has entered itself into the thread list */
1221
1222         threads_sem_wait(&sem);
1223
1224         /* cleanup */
1225
1226         sem_destroy(&sem);
1227         sem_destroy(&sem_first);
1228 }
1229
1230
1231 /* threads_attach_current_thread ***********************************************
1232
1233    Attaches the current thread to the VM.  Used in JNI.
1234
1235 *******************************************************************************/
1236
1237 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1238 {
1239         threadobject          *thread;
1240         java_lang_Thread      *t;
1241         utf                   *u;
1242         java_lang_String      *s;
1243         java_lang_ThreadGroup *group;
1244         java_objectheader     *o;
1245
1246         /* create a java.lang.VMThread object */
1247
1248         thread = (threadobject *) builtin_new(class_java_lang_VMThread);
1249
1250         if (thread == NULL)
1251                 return false;
1252
1253         threads_init_threadobject(&thread->o);
1254         threads_set_current_threadobject(thread);
1255         lock_init_execution_env(thread);
1256
1257         /* insert the thread into the threadlist and the threads table */
1258
1259         pthread_mutex_lock(&threadlistlock);
1260
1261         thread->prev        = mainthreadobj;
1262         thread->next        = mainthreadobj->next;
1263         mainthreadobj->next = thread;
1264         thread->next->prev  = thread;
1265
1266         threads_table_add(thread);
1267
1268         pthread_mutex_unlock(&threadlistlock);
1269
1270         /* mark main thread as Java thread */
1271
1272         thread->flags = THREAD_FLAG_JAVA;
1273
1274 #if defined(ENABLE_INTRP)
1275         /* create interpreter stack */
1276
1277         if (opt_intrp) {
1278                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1279                 thread->_global_sp = intrp_main_stack + opt_stacksize;
1280         }
1281 #endif
1282
1283         /* create a java.lang.Thread object */
1284
1285         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1286
1287         if (t == NULL)
1288                 return false;
1289
1290         thread->o.thread = t;
1291
1292         if (vm_aargs != NULL) {
1293                 u     = utf_new_char(vm_aargs->name);
1294                 group = (java_lang_ThreadGroup *) vm_aargs->group;
1295         }
1296         else {
1297                 u     = utf_null;
1298                 group = mainthreadobj->o.thread->group;
1299         }
1300
1301         s = javastring_new(u);
1302
1303         o = (java_objectheader *) t;
1304
1305         (void) vm_call_method(method_thread_init, o, thread, s, NORM_PRIORITY,
1306                                                   isdaemon);
1307
1308         if (*exceptionptr)
1309                 return false;
1310
1311         /* store the thread group in the object */
1312
1313         t->group = group;
1314
1315         o = (java_objectheader *) group;
1316
1317         (void) vm_call_method(method_threadgroup_add, o, t);
1318
1319         if (*exceptionptr)
1320                 return false;
1321
1322         return true;
1323 }
1324
1325
1326 /* threads_detach_thread *******************************************************
1327
1328    Detaches the passed thread from the VM.  Used in JNI.
1329
1330 *******************************************************************************/
1331
1332 bool threads_detach_thread(threadobject *thread)
1333 {
1334         java_lang_Thread      *t;
1335         java_lang_ThreadGroup *group;
1336         methodinfo            *m;
1337         java_objectheader     *o;
1338
1339         /* Allow lock record pools to be used by other threads. They
1340            cannot be deleted so we'd better not waste them. */
1341
1342         /* XXX We have to find a new way to free lock records */
1343         /*     with the new locking algorithm.                */
1344         /* lock_record_free_pools(thread->ee.lockrecordpools); */
1345
1346         /* XXX implement uncaught exception stuff (like JamVM does) */
1347
1348         /* remove thread from the thread group */
1349
1350         t     = thread->o.thread;
1351         group = t->group;
1352
1353         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1354
1355         if (group != NULL) {
1356                 m = class_resolveclassmethod(group->header.vftbl->class,
1357                                                                          utf_removeThread,
1358                                                                          utf_java_lang_Thread__V,
1359                                                                          class_java_lang_ThreadGroup,
1360                                                                          true);
1361
1362                 if (m == NULL)
1363                         return false;
1364
1365                 o = (java_objectheader *) group;
1366
1367                 (void) vm_call_method(m, o, t);
1368
1369                 if (*exceptionptr)
1370                         return false;
1371         }
1372
1373         /* remove thread from thread list and threads table, do this
1374            inside a lock */
1375
1376         pthread_mutex_lock(&threadlistlock);
1377
1378         thread->next->prev = thread->prev;
1379         thread->prev->next = thread->next;
1380
1381         threads_table_remove(thread);
1382
1383         pthread_mutex_unlock(&threadlistlock);
1384
1385         /* reset thread id (lock on joinmutex? TWISTI) */
1386
1387         pthread_mutex_lock(&thread->joinmutex);
1388         thread->tid = 0;
1389         pthread_mutex_unlock(&thread->joinmutex);
1390
1391         /* tell everyone that a thread has finished */
1392
1393         pthread_cond_broadcast(&thread->joincond);
1394
1395         return true;
1396 }
1397
1398
1399 /* threads_find_non_daemon_thread **********************************************
1400
1401    Helper function used by threads_join_all_threads for finding
1402    non-daemon threads that are still running.
1403
1404 *******************************************************************************/
1405
1406 /* At the end of the program, we wait for all running non-daemon
1407    threads to die. */
1408
1409 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1410 {
1411         while (thread != mainthreadobj) {
1412                 if (!thread->o.thread->daemon)
1413                         return thread;
1414                 thread = thread->prev;
1415         }
1416
1417         return NULL;
1418 }
1419
1420
1421 /* threads_join_all_threads ****************************************************
1422
1423    Join all non-daemon threads.
1424
1425 *******************************************************************************/
1426
1427 void threads_join_all_threads(void)
1428 {
1429         threadobject *thread;
1430
1431         pthread_mutex_lock(&threadlistlock);
1432
1433         while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1434
1435                 pthread_mutex_lock(&thread->joinmutex);
1436
1437                 pthread_mutex_unlock(&threadlistlock);
1438
1439                 while (thread->tid)
1440                         pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1441
1442                 pthread_mutex_unlock(&thread->joinmutex);
1443
1444                 pthread_mutex_lock(&threadlistlock);
1445         }
1446
1447         pthread_mutex_unlock(&threadlistlock);
1448 }
1449
1450
1451 /* threads_timespec_earlier ****************************************************
1452
1453    Return true if timespec tv1 is earlier than timespec tv2.
1454
1455    IN:
1456       tv1..........first timespec
1457           tv2..........second timespec
1458
1459    RETURN VALUE:
1460       true, if the first timespec is earlier
1461
1462 *******************************************************************************/
1463
1464 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1465                                                                                         const struct timespec *tv2)
1466 {
1467         return (tv1->tv_sec < tv2->tv_sec)
1468                                 ||
1469                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1470 }
1471
1472
1473 /* threads_current_time_is_earlier_than ****************************************
1474
1475    Check if the current time is earlier than the given timespec.
1476
1477    IN:
1478       tv...........the timespec to compare against
1479
1480    RETURN VALUE:
1481       true, if the current time is earlier
1482
1483 *******************************************************************************/
1484
1485 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1486 {
1487         struct timeval tvnow;
1488         struct timespec tsnow;
1489
1490         /* get current time */
1491
1492         if (gettimeofday(&tvnow, NULL) != 0)
1493                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1494
1495         /* convert it to a timespec */
1496
1497         tsnow.tv_sec = tvnow.tv_sec;
1498         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1499
1500         /* compare current time with the given timespec */
1501
1502         return threads_timespec_earlier(&tsnow, tv);
1503 }
1504
1505
1506 /* threads_wait_with_timeout ***************************************************
1507
1508    Wait until the given point in time on a monitor until either
1509    we are notified, we are interrupted, or the time is up.
1510
1511    IN:
1512       t............the current thread
1513           wakeupTime...absolute (latest) wakeup time
1514                            If both tv_sec and tv_nsec are zero, this function
1515                                            waits for an unlimited amount of time.
1516
1517    RETURN VALUE:
1518       true.........if the wait has been interrupted,
1519           false........if the wait was ended by notification or timeout
1520
1521 *******************************************************************************/
1522
1523 static bool threads_wait_with_timeout(threadobject *t,
1524                                                                           struct timespec *wakeupTime)
1525 {
1526         bool wasinterrupted;
1527
1528         /* acquire the waitmutex */
1529
1530         pthread_mutex_lock(&t->waitmutex);
1531
1532         /* mark us as sleeping */
1533
1534         t->sleeping = true;
1535
1536         /* wait on waitcond */
1537
1538         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1539                 /* with timeout */
1540                 while (!t->interrupted && !t->signaled
1541                            && threads_current_time_is_earlier_than(wakeupTime))
1542                 {
1543                         pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1544                 }
1545         }
1546         else {
1547                 /* no timeout */
1548                 while (!t->interrupted && !t->signaled)
1549                         pthread_cond_wait(&t->waitcond, &t->waitmutex);
1550         }
1551
1552         /* check if we were interrupted */
1553
1554         wasinterrupted = t->interrupted;
1555
1556         /* reset all flags */
1557
1558         t->interrupted = false;
1559         t->signaled = false;
1560         t->sleeping = false;
1561
1562         /* release the waitmutex */
1563
1564         pthread_mutex_unlock(&t->waitmutex);
1565
1566         return wasinterrupted;
1567 }
1568
1569
1570 /* threads_wait_with_timeout_relative ******************************************
1571
1572    Wait for the given maximum amount of time on a monitor until either
1573    we are notified, we are interrupted, or the time is up.
1574
1575    IN:
1576       t............the current thread
1577           millis.......milliseconds to wait
1578           nanos........nanoseconds to wait
1579
1580    RETURN VALUE:
1581       true.........if the wait has been interrupted,
1582           false........if the wait was ended by notification or timeout
1583
1584 *******************************************************************************/
1585
1586 bool threads_wait_with_timeout_relative(threadobject *t,
1587                                                                                 s8 millis,
1588                                                                                 s4 nanos)
1589 {
1590         struct timespec wakeupTime;
1591
1592         /* calculate the the (latest) wakeup time */
1593
1594         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1595
1596         /* wait */
1597
1598         return threads_wait_with_timeout(t, &wakeupTime);
1599 }
1600
1601
1602 /* threads_calc_absolute_time **************************************************
1603
1604    Calculate the absolute point in time a given number of ms and ns from now.
1605
1606    IN:
1607       millis............milliseconds from now
1608           nanos.............nanoseconds from now
1609
1610    OUT:
1611       *tm...............receives the timespec of the absolute point in time
1612
1613 *******************************************************************************/
1614
1615 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1616 {
1617         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1618                 struct timeval tv;
1619                 long nsec;
1620                 gettimeofday(&tv, NULL);
1621                 tv.tv_sec += millis / 1000;
1622                 millis %= 1000;
1623                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1624                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1625                 tm->tv_nsec = nsec % 1000000000;
1626         }
1627         else {
1628                 tm->tv_sec = 0;
1629                 tm->tv_nsec = 0;
1630         }
1631 }
1632
1633
1634 /* threads_interrupt_thread ****************************************************
1635
1636    Interrupt the given thread.
1637
1638    The thread gets the "waitcond" signal and 
1639    its interrupted flag is set to true.
1640
1641    IN:
1642       thread............the thread to interrupt
1643
1644 *******************************************************************************/
1645
1646 void threads_interrupt_thread(java_lang_VMThread *thread)
1647 {
1648         threadobject *t = (threadobject*) thread;
1649
1650         /* signal the thread a "waitcond" and tell it that it has been */
1651         /* interrupted                                                 */
1652
1653         pthread_mutex_lock(&t->waitmutex);
1654         if (t->sleeping)
1655                 pthread_cond_signal(&t->waitcond);
1656         t->interrupted = true;
1657         pthread_mutex_unlock(&t->waitmutex);
1658 }
1659
1660
1661 /* threads_check_if_interrupted_and_reset **************************************
1662
1663    Check if the current thread has been interrupted and reset the
1664    interruption flag.
1665
1666    RETURN VALUE:
1667       true, if the current thread had been interrupted
1668
1669 *******************************************************************************/
1670
1671 bool threads_check_if_interrupted_and_reset(void)
1672 {
1673         threadobject *t;
1674         bool intr;
1675
1676         t = (threadobject*) THREADOBJECT;
1677
1678         intr = t->interrupted;
1679
1680         t->interrupted = false;
1681
1682         return intr;
1683 }
1684
1685
1686 /* threads_thread_has_been_interrupted *********************************************************
1687
1688    Check if the given thread has been interrupted
1689
1690    IN:
1691       t............the thread to check
1692
1693    RETURN VALUE:
1694       true, if the given thread had been interrupted
1695
1696 *******************************************************************************/
1697
1698 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1699 {
1700         threadobject *t;
1701
1702         t = (threadobject*) thread;
1703
1704         return t->interrupted;
1705 }
1706
1707
1708 /* threads_sleep ***************************************************************
1709
1710    Sleep the current thread for the specified amount of time.
1711
1712 *******************************************************************************/
1713
1714 void threads_sleep(s8 millis, s4 nanos)
1715 {
1716         threadobject       *t;
1717         struct timespec    wakeupTime;
1718         bool               wasinterrupted;
1719
1720         t = (threadobject *) THREADOBJECT;
1721
1722         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1723
1724         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1725
1726         if (wasinterrupted)
1727                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1728 }
1729
1730
1731 /* threads_yield *****************************************************************
1732
1733    Yield to the scheduler.
1734
1735 *******************************************************************************/
1736
1737 void threads_yield(void)
1738 {
1739         sched_yield();
1740 }
1741
1742
1743 /* threads_java_lang_Thread_set_priority ***********************************************************
1744
1745    Set the priority for the given java.lang.Thread.
1746
1747    IN:
1748       t............the java.lang.Thread
1749           priority.....the priority
1750
1751 *******************************************************************************/
1752
1753 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1754 {
1755         threadobject *thread;
1756
1757         thread = (threadobject*) t->vmThread;
1758
1759         threads_set_thread_priority(thread->tid, priority);
1760 }
1761
1762
1763 /* threads_dump ****************************************************************
1764
1765    Dumps info for all threads running in the JVM. This function is
1766    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1767
1768 *******************************************************************************/
1769
1770 void threads_dump(void)
1771 {
1772         threadobject       *thread;
1773         java_lang_VMThread *vmt;
1774         java_lang_Thread   *t;
1775         utf                *name;
1776
1777         thread = mainthreadobj;
1778
1779         /* XXX we should stop the world here */
1780
1781         printf("Full thread dump CACAO "VERSION":\n");
1782
1783         /* iterate over all started threads */
1784
1785         do {
1786                 /* get thread objects */
1787
1788                 vmt = &thread->o;
1789                 t   = vmt->thread;
1790
1791                 /* the thread may be currently in initalization, don't print it */
1792
1793                 if (t != NULL) {
1794                         /* get thread name */
1795
1796                         name = javastring_toutf(t->name, false);
1797
1798                         printf("\n\"");
1799                         utf_display_printable_ascii(name);
1800                         printf("\" ");
1801
1802                         if (t->daemon)
1803                                 printf("daemon ");
1804
1805 #if SIZEOF_VOID_P == 8
1806                         printf("prio=%d tid=0x%016lx\n", t->priority, thread->tid);
1807 #else
1808                         printf("prio=%d tid=0x%08lx\n", t->priority, thread->tid);
1809 #endif
1810
1811                         /* send SIGUSR1 to thread to print stacktrace */
1812
1813 /*                      pthread_kill(thread->tid, SIGUSR1); */
1814                         stacktrace_dump_trace(thread);
1815
1816                         /* sleep this thread a bit, so the signal can reach the thread */
1817
1818                         threads_sleep(10, 0);
1819                 }
1820
1821                 thread = thread->next;
1822         } while ((thread != NULL) && (thread != mainthreadobj));
1823 }
1824
1825
1826 /* threads_table_dump *********************************************************
1827
1828    Dump the threads table for debugging purposes.
1829
1830    IN:
1831       file..............stream to write to
1832
1833 ******************************************************************************/
1834
1835 #if !defined(NDEBUG)
1836 static void threads_table_dump(FILE *file)
1837 {
1838         s4 i;
1839         s4 size;
1840         ptrint index;
1841
1842         pthread_mutex_lock(&threadlistlock);
1843
1844         size = threads_table.size;
1845
1846         fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1847
1848         for (i=0; i<size; ++i) {
1849                 index = threads_table.table[i].nextfree;
1850
1851                 fprintf(file, "%4d: ", i);
1852
1853                 if (index < size) {
1854                         fprintf(file, "free, nextfree = %d\n", index);
1855                 }
1856                 else {
1857                         fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1858                 }
1859         }
1860
1861         fprintf(file, "======== END OF THREADS TABLE ========\n");
1862
1863         pthread_mutex_unlock(&threadlistlock);
1864 }
1865 #endif
1866
1867 /*
1868  * These are local overrides for various environment variables in Emacs.
1869  * Please do not remove this and leave it at the end of the file, where
1870  * Emacs will automagically detect them.
1871  * ---------------------------------------------------------------------
1872  * Local variables:
1873  * mode: c
1874  * indent-tabs-mode: t
1875  * c-basic-offset: 4
1876  * tab-width: 4
1877  * End:
1878  * vim:noexpandtab:sw=4:ts=4:
1879  */