* src/threads/native/threads.c (threads_attach_current_thread): Rename
[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 5704 2006-10-05 20:30:12Z edwin $
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 /* threads_set_current_threadobject ********************************************
647
648    Set the current thread object.
649    
650    IN:
651       thread.......the thread object to set
652
653 *******************************************************************************/
654
655 static void threads_set_current_threadobject(threadobject *thread)
656 {
657 #if !defined(HAVE___THREAD)
658         pthread_setspecific(threads_current_threadobject_key, thread);
659 #else
660         threads_current_threadobject = thread;
661 #endif
662 }
663
664
665 /* threads_get_current_threadobject ********************************************
666
667    Return the threadobject of the current thread.
668    
669    RETURN VALUE:
670        the current threadobject * (an instance of java.lang.VMThread)
671
672 *******************************************************************************/
673
674 threadobject *threads_get_current_threadobject(void)
675 {
676         return THREADOBJECT;
677 }
678
679
680 /* threads_preinit *************************************************************
681
682    Do some early initialization of stuff required.
683
684 *******************************************************************************/
685
686 void threads_preinit(void)
687 {
688 #ifndef MUTEXSIM
689         pthread_mutexattr_t mutexattr;
690         pthread_mutexattr_init(&mutexattr);
691         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
692         pthread_mutex_init(&compiler_mutex, &mutexattr);
693         pthread_mutexattr_destroy(&mutexattr);
694 #else
695         pthread_mutex_init_rec(&compiler_mutex);
696 #endif
697
698         pthread_mutex_init(&threadlistlock, NULL);
699         pthread_mutex_init(&stopworldlock, NULL);
700
701         /* Allocate something so the garbage collector's signal handlers
702            are installed. */
703         heap_allocate(1, false, NULL);
704
705         mainthreadobj = NEW(threadobject);
706         mainthreadobj->tid = pthread_self();
707         mainthreadobj->index = 1;
708         mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
709         
710 #if !defined(HAVE___THREAD)
711         pthread_key_create(&threads_current_threadobject_key, NULL);
712 #endif
713         threads_set_current_threadobject(mainthreadobj);
714
715         threads_sem_init(&suspend_ack, 0, 0);
716
717         /* initialize the threads table */
718
719         threads_table_init();
720
721         /* initialize subsystems */
722
723         lock_init();
724
725         critical_init();
726 }
727
728
729 /* threads_init ****************************************************************
730
731    Initializes the threads required by the JVM: main, finalizer.
732
733 *******************************************************************************/
734
735 bool threads_init(void)
736 {
737         java_lang_String      *threadname;
738         java_lang_Thread      *mainthread;
739         java_lang_ThreadGroup *threadgroup;
740         threadobject          *tempthread;
741
742         tempthread = mainthreadobj;
743
744         /* XXX We have to find a new way to free lock records */
745         /*     with the new locking algorithm.                */
746         /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
747
748         /* This is kinda tricky, we grow the java.lang.Thread object so we
749            can keep the execution environment there. No Thread object must
750            have been created at an earlier time. */
751
752         class_java_lang_VMThread->instancesize = sizeof(threadobject);
753
754         /* get methods we need in this file */
755
756         method_thread_init =
757                 class_resolveclassmethod(class_java_lang_Thread,
758                                                                  utf_init,
759                                                                  utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
760                                                                  class_java_lang_Thread,
761                                                                  true);
762
763         if (method_thread_init == NULL)
764                 return false;
765
766         method_threadgroup_add =
767                 class_resolveclassmethod(class_java_lang_ThreadGroup,
768                                                                  utf_new_char("addThread"),
769                                                                  utf_new_char("(Ljava/lang/Thread;)V"),
770                                                                  class_java_lang_ThreadGroup,
771                                                                  true);
772
773         if (method_threadgroup_add == NULL)
774                 return false;
775
776         /* create a VMThread */
777
778         mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
779
780         if (mainthreadobj == NULL)
781                 return false;
782
783         FREE(tempthread, threadobject);
784
785         threads_init_threadobject(&mainthreadobj->o);
786
787         threads_set_current_threadobject(mainthreadobj);
788
789         lock_init_execution_env(mainthreadobj);
790
791         mainthreadobj->next = mainthreadobj;
792         mainthreadobj->prev = mainthreadobj;
793
794         threads_table_add(mainthreadobj);
795
796         /* mark main thread as Java thread */
797
798         mainthreadobj->flags = THREAD_FLAG_JAVA;
799
800 #if defined(ENABLE_INTRP)
801         /* create interpreter stack */
802
803         if (opt_intrp) {
804                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
805                 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
806         }
807 #endif
808
809         threadname = javastring_new(utf_new_char("main"));
810
811         /* allocate and init ThreadGroup */
812
813         threadgroup = (java_lang_ThreadGroup *)
814                 native_new_and_init(class_java_lang_ThreadGroup);
815
816         if (!threadgroup)
817                 throw_exception_exit();
818
819         /* create a Thread */
820
821         mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
822
823         if (mainthread == NULL)
824                 throw_exception_exit();
825
826         mainthreadobj->o.thread = mainthread;
827
828         /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
829
830         (void) vm_call_method(method_thread_init, (java_objectheader *) mainthread,
831                                                   mainthreadobj, threadname, NORM_PRIORITY, false);
832
833         if (*exceptionptr)
834                 return false;
835
836         mainthread->group = threadgroup;
837
838         /* add mainthread to ThreadGroup */
839
840         (void) vm_call_method(method_threadgroup_add, 
841                                                   (java_objectheader *) threadgroup,
842                                                   mainthread);
843
844         if (*exceptionptr)
845                 return false;
846
847         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
848
849         /* initialize the thread attribute object */
850
851         if (pthread_attr_init(&threadattr)) {
852                 log_println("pthread_attr_init failed: %s", strerror(errno));
853                 return false;
854         }
855
856         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
857
858         /* everything's ok */
859
860         return true;
861 }
862
863
864 /* threads_table_init *********************************************************
865
866    Initialize the global threads table.
867
868 ******************************************************************************/
869
870 static void threads_table_init(void)
871 {
872         s4 size;
873         s4 i;
874
875         size = THREADS_INITIAL_TABLE_SIZE;
876
877         threads_table.size = size;
878         threads_table.table = MNEW(threads_table_entry_t, size);
879
880         /* link the entries in a freelist */
881
882         for (i=0; i<size; ++i) {
883                 threads_table.table[i].nextfree = i+1;
884         }
885
886         /* terminate the freelist */
887
888         threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
889 }
890
891
892 /* threads_table_add **********************************************************
893
894    Add a thread to the global threads table. The index is entered in the
895    threadobject. The thinlock value for the thread is pre-computed.
896
897    IN:
898       thread............the thread to add
899
900    RETURN VALUE:
901       The table index for the newly added thread. This value has also been
902           entered in the threadobject.
903
904    PRE-CONDITION:
905       The caller must hold the threadlistlock!
906
907 ******************************************************************************/
908
909 static s4 threads_table_add(threadobject *thread)
910 {
911         s4 index;
912         s4 oldsize;
913         s4 newsize;
914         s4 i;
915
916         /* table[0] serves as the head of the freelist */
917
918         index = threads_table.table[0].nextfree;
919
920         /* if we got a free index, use it */
921
922         if (index) {
923 got_an_index:
924                 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
925                 threads_table.table[index].thread = thread;
926                 thread->index = index;
927                 thread->thinlock = lock_pre_compute_thinlock(index);
928                 return index;
929         }
930
931         /* we must grow the table */
932
933         oldsize = threads_table.size;
934         newsize = oldsize * 2;
935
936         threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
937                                                                    oldsize, newsize);
938         threads_table.size = newsize;
939
940         /* link the new entries to a free list */
941
942         for (i=oldsize; i<newsize; ++i) {
943                 threads_table.table[i].nextfree = i+1;
944         }
945
946         /* terminate the freelist */
947
948         threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
949
950         /* use the first of the new entries */
951
952         index = oldsize;
953         goto got_an_index;
954 }
955
956
957 /* threads_table_remove *******************************************************
958
959    Remove a thread from the global threads table.
960
961    IN:
962       thread............the thread to remove
963
964    PRE-CONDITION:
965       The caller must hold the threadlistlock!
966
967 ******************************************************************************/
968
969 static void threads_table_remove(threadobject *thread)
970 {
971         s4 index;
972
973         index = thread->index;
974
975         /* put the index into the freelist */
976
977         threads_table.table[index] = threads_table.table[0];
978         threads_table.table[0].nextfree = index;
979
980         /* delete the index in the threadobject to discover bugs */
981 #if !defined(NDEBUG)
982         thread->index = 0;
983 #endif
984 }
985
986 /* threads_init_threadobject **************************************************
987
988    Initialize implementation fields of a java.lang.VMThread.
989
990    IN:
991       t............the java.lang.VMThread
992
993 ******************************************************************************/
994
995 void threads_init_threadobject(java_lang_VMThread *t)
996 {
997         threadobject *thread = (threadobject*) t;
998
999         thread->tid = pthread_self();
1000
1001         thread->index = 0;
1002
1003         /* TODO destroy all those things */
1004         pthread_mutex_init(&(thread->joinmutex), NULL);
1005         pthread_cond_init(&(thread->joincond), NULL);
1006
1007         pthread_mutex_init(&(thread->waitmutex), NULL);
1008         pthread_cond_init(&(thread->waitcond), NULL);
1009
1010         thread->interrupted = false;
1011         thread->signaled = false;
1012         thread->sleeping = false;
1013 }
1014
1015
1016 /* threads_startup_thread ******************************************************
1017
1018    Thread startup function called by pthread_create.
1019
1020    Thread which have a startup.function != NULL are marked as internal
1021    threads. All other threads are threated as normal Java threads.
1022
1023    NOTE: This function is not called directly by pthread_create. The Boehm GC
1024          inserts its own GC_start_routine in between, which then calls
1025                  threads_startup.
1026
1027    IN:
1028       t............the argument passed to pthread_create, ie. a pointer to
1029                        a startupinfo struct. CAUTION: When the `psem` semaphore
1030                                    is posted, the startupinfo struct becomes invalid! (It
1031                                    is allocated on the stack of threads_start_thread.)
1032
1033 ******************************************************************************/
1034
1035 static void *threads_startup_thread(void *t)
1036 {
1037         startupinfo  *startup;
1038         threadobject *thread;
1039         sem_t        *psem;
1040         threadobject *tnext;
1041         methodinfo   *method;
1042         functionptr   function;
1043
1044 #if defined(ENABLE_INTRP)
1045         u1 *intrp_thread_stack;
1046
1047         /* create interpreter stack */
1048
1049         if (opt_intrp) {
1050                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1051                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1052         }
1053         else
1054                 intrp_thread_stack = NULL;
1055 #endif
1056
1057         /* get passed startupinfo structure and the values in there */
1058
1059         startup = t;
1060         t = NULL; /* make sure it's not used wrongly */
1061
1062         thread   = startup->thread;
1063         function = startup->function;
1064         psem     = startup->psem;
1065
1066         /* Seems like we've encountered a situation where thread->tid was not set by
1067          * pthread_create. We alleviate this problem by waiting for pthread_create
1068          * to return. */
1069         threads_sem_wait(startup->psem_first);
1070
1071         /* set the thread object */
1072
1073 #if defined(__DARWIN__)
1074         thread->mach_thread = mach_thread_self();
1075 #endif
1076         threads_set_current_threadobject(thread);
1077
1078         /* insert the thread into the threadlist and the threads table */
1079
1080         pthread_mutex_lock(&threadlistlock);
1081
1082         thread->prev = mainthreadobj;
1083         thread->next = tnext = mainthreadobj->next;
1084         mainthreadobj->next = thread;
1085         tnext->prev = thread;
1086
1087         threads_table_add(thread);
1088
1089         pthread_mutex_unlock(&threadlistlock);
1090
1091         /* init data structures of this thread */
1092
1093         lock_init_execution_env(thread);
1094
1095         /* tell threads_startup_thread that we registered ourselves */
1096         /* CAUTION: *startup becomes invalid with this!             */
1097
1098         startup = NULL;
1099         threads_sem_post(psem);
1100
1101         /* set our priority */
1102
1103         threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1104
1105 #if defined(ENABLE_INTRP)
1106         /* set interpreter stack */
1107
1108         if (opt_intrp)
1109                 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1110 #endif
1111
1112 #if defined(ENABLE_JVMTI)
1113         /* fire thread start event */
1114
1115         if (jvmti) 
1116                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1117 #endif
1118
1119         /* find and run the Thread.run()V method if no other function was passed */
1120
1121         if (function == NULL) {
1122                 /* this is a normal Java thread */
1123
1124                 thread->flags |= THREAD_FLAG_JAVA;
1125
1126                 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1127                                                                                   utf_run,
1128                                                                                   utf_void__void,
1129                                                                                   thread->o.header.vftbl->class,
1130                                                                                   true);
1131
1132                 if (method == NULL)
1133                         throw_exception();
1134
1135                 /* increase total started thread count */
1136
1137                 _Jv_jvm->total_started_thread_count++;
1138
1139                 (void) vm_call_method(method, (java_objectheader *) thread);
1140         }
1141         else {
1142                 /* this is an internal thread */
1143
1144                 thread->flags |= THREAD_FLAG_INTERNAL;
1145
1146                 /* increase total started thread count */
1147
1148                 _Jv_jvm->total_started_thread_count++;
1149
1150                 /* call passed function, e.g. finalizer_thread */
1151
1152                 (function)();
1153         }
1154
1155 #if defined(ENABLE_JVMTI)
1156         /* fire thread end event */
1157
1158         if (jvmti)
1159                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1160 #endif
1161
1162         threads_detach_thread(thread);
1163
1164         return NULL;
1165 }
1166
1167
1168 /* threads_start_thread ********************************************************
1169
1170    Start a thread in the JVM.
1171
1172    IN:
1173       t............the java.lang.Thread object
1174           function.....function to run in the new thread. NULL means that the
1175                        "run" method of the object `t` should be called
1176
1177 ******************************************************************************/
1178
1179 void threads_start_thread(java_lang_Thread *t, functionptr function)
1180 {
1181         sem_t          sem;
1182         sem_t          sem_first;
1183         pthread_attr_t attr;
1184         startupinfo    startup;
1185         threadobject  *thread;
1186
1187         thread = (threadobject *) t->vmThread;
1188
1189         /* fill startupinfo structure passed by pthread_create to
1190          * threads_startup_thread */
1191
1192         startup.thread     = thread;
1193         startup.function   = function;       /* maybe we don't call Thread.run()V */
1194         startup.psem       = &sem;
1195         startup.psem_first = &sem_first;
1196
1197         threads_sem_init(&sem, 0, 0);
1198         threads_sem_init(&sem_first, 0, 0);
1199
1200         /* initialize thread attribute object */
1201
1202         if (pthread_attr_init(&attr))
1203                 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1204
1205         /* initialize thread stacksize */
1206
1207         if (pthread_attr_setstacksize(&attr, opt_stacksize))
1208                 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1209
1210         /* create the thread */
1211
1212         if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1213                 vm_abort("pthread_create failed: %s", strerror(errno));
1214
1215         /* signal that pthread_create has returned, so thread->tid is valid */
1216
1217         threads_sem_post(&sem_first);
1218
1219         /* wait here until the thread has entered itself into the thread list */
1220
1221         threads_sem_wait(&sem);
1222
1223         /* cleanup */
1224
1225         sem_destroy(&sem);
1226         sem_destroy(&sem_first);
1227 }
1228
1229
1230 /* threads_attach_current_thread ***********************************************
1231
1232    Attaches the current thread to the VM.  Used in JNI.
1233
1234 *******************************************************************************/
1235
1236 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1237 {
1238         threadobject          *thread;
1239         java_lang_Thread      *t;
1240         utf                   *u;
1241         java_lang_String      *s;
1242         java_lang_ThreadGroup *group;
1243         java_objectheader     *o;
1244
1245         /* create a java.lang.VMThread object */
1246
1247         thread = (threadobject *) builtin_new(class_java_lang_VMThread);
1248
1249         if (thread == NULL)
1250                 return false;
1251
1252         threads_init_threadobject(&thread->o);
1253         threads_set_current_threadobject(thread);
1254         lock_init_execution_env(thread);
1255
1256         /* insert the thread into the threadlist and the threads table */
1257
1258         pthread_mutex_lock(&threadlistlock);
1259
1260         thread->prev        = mainthreadobj;
1261         thread->next        = mainthreadobj->next;
1262         mainthreadobj->next = thread;
1263         thread->next->prev  = thread;
1264
1265         threads_table_add(thread);
1266
1267         pthread_mutex_unlock(&threadlistlock);
1268
1269         /* mark main thread as Java thread */
1270
1271         thread->flags = THREAD_FLAG_JAVA;
1272
1273 #if defined(ENABLE_INTRP)
1274         /* create interpreter stack */
1275
1276         if (opt_intrp) {
1277                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1278                 thread->_global_sp = intrp_main_stack + opt_stacksize;
1279         }
1280 #endif
1281
1282         /* create a java.lang.Thread object */
1283
1284         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1285
1286         if (t == NULL)
1287                 return false;
1288
1289         thread->o.thread = t;
1290
1291         if (vm_aargs != NULL) {
1292                 u     = utf_new_char(vm_aargs->name);
1293                 group = (java_lang_ThreadGroup *) vm_aargs->group;
1294         }
1295         else {
1296                 u     = utf_null;
1297                 group = mainthreadobj->o.thread->group;
1298         }
1299
1300         s = javastring_new(u);
1301
1302         o = (java_objectheader *) t;
1303
1304         (void) vm_call_method(method_thread_init, o, thread, s, NORM_PRIORITY,
1305                                                   isdaemon);
1306
1307         if (*exceptionptr)
1308                 return false;
1309
1310         /* store the thread group in the object */
1311
1312         t->group = group;
1313
1314         o = (java_objectheader *) group;
1315
1316         (void) vm_call_method(method_threadgroup_add, o, t);
1317
1318         if (*exceptionptr)
1319                 return false;
1320
1321         return true;
1322 }
1323
1324
1325 /* threads_detach_thread *******************************************************
1326
1327    Detaches the passed thread from the VM.  Used in JNI.
1328
1329 *******************************************************************************/
1330
1331 bool threads_detach_thread(threadobject *thread)
1332 {
1333         java_lang_Thread      *t;
1334         java_lang_ThreadGroup *group;
1335         methodinfo            *m;
1336         java_objectheader     *o;
1337
1338         /* Allow lock record pools to be used by other threads. They
1339            cannot be deleted so we'd better not waste them. */
1340
1341         /* XXX We have to find a new way to free lock records */
1342         /*     with the new locking algorithm.                */
1343         /* lock_record_free_pools(thread->ee.lockrecordpools); */
1344
1345         /* XXX implement uncaught exception stuff (like JamVM does) */
1346
1347         /* remove thread from the thread group */
1348
1349         t     = thread->o.thread;
1350         group = t->group;
1351
1352         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1353
1354         if (group != NULL) {
1355                 m = class_resolveclassmethod(group->header.vftbl->class,
1356                                                                          utf_removeThread,
1357                                                                          utf_java_lang_Thread__V,
1358                                                                          class_java_lang_ThreadGroup,
1359                                                                          true);
1360
1361                 if (m == NULL)
1362                         return false;
1363
1364                 o = (java_objectheader *) group;
1365
1366                 (void) vm_call_method(m, o, t);
1367
1368                 if (*exceptionptr)
1369                         return false;
1370         }
1371
1372         /* remove thread from thread list and threads table, do this
1373            inside a lock */
1374
1375         pthread_mutex_lock(&threadlistlock);
1376
1377         thread->next->prev = thread->prev;
1378         thread->prev->next = thread->next;
1379
1380         threads_table_remove(thread);
1381
1382         pthread_mutex_unlock(&threadlistlock);
1383
1384         /* reset thread id (lock on joinmutex? TWISTI) */
1385
1386         pthread_mutex_lock(&thread->joinmutex);
1387         thread->tid = 0;
1388         pthread_mutex_unlock(&thread->joinmutex);
1389
1390         /* tell everyone that a thread has finished */
1391
1392         pthread_cond_broadcast(&thread->joincond);
1393
1394         return true;
1395 }
1396
1397
1398 /* threads_find_non_daemon_thread **********************************************
1399
1400    Helper function used by threads_join_all_threads for finding
1401    non-daemon threads that are still running.
1402
1403 *******************************************************************************/
1404
1405 /* At the end of the program, we wait for all running non-daemon
1406    threads to die. */
1407
1408 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1409 {
1410         while (thread != mainthreadobj) {
1411                 if (!thread->o.thread->daemon)
1412                         return thread;
1413                 thread = thread->prev;
1414         }
1415
1416         return NULL;
1417 }
1418
1419
1420 /* threads_join_all_threads ****************************************************
1421
1422    Join all non-daemon threads.
1423
1424 *******************************************************************************/
1425
1426 void threads_join_all_threads(void)
1427 {
1428         threadobject *thread;
1429
1430         pthread_mutex_lock(&threadlistlock);
1431
1432         while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1433
1434                 pthread_mutex_lock(&thread->joinmutex);
1435
1436                 pthread_mutex_unlock(&threadlistlock);
1437
1438                 while (thread->tid)
1439                         pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1440
1441                 pthread_mutex_unlock(&thread->joinmutex);
1442
1443                 pthread_mutex_lock(&threadlistlock);
1444         }
1445
1446         pthread_mutex_unlock(&threadlistlock);
1447 }
1448
1449
1450 /* threads_timespec_earlier ****************************************************
1451
1452    Return true if timespec tv1 is earlier than timespec tv2.
1453
1454    IN:
1455       tv1..........first timespec
1456           tv2..........second timespec
1457
1458    RETURN VALUE:
1459       true, if the first timespec is earlier
1460
1461 *******************************************************************************/
1462
1463 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1464                                                                                         const struct timespec *tv2)
1465 {
1466         return (tv1->tv_sec < tv2->tv_sec)
1467                                 ||
1468                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1469 }
1470
1471
1472 /* threads_current_time_is_earlier_than ****************************************
1473
1474    Check if the current time is earlier than the given timespec.
1475
1476    IN:
1477       tv...........the timespec to compare against
1478
1479    RETURN VALUE:
1480       true, if the current time is earlier
1481
1482 *******************************************************************************/
1483
1484 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1485 {
1486         struct timeval tvnow;
1487         struct timespec tsnow;
1488
1489         /* get current time */
1490
1491         if (gettimeofday(&tvnow, NULL) != 0)
1492                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1493
1494         /* convert it to a timespec */
1495
1496         tsnow.tv_sec = tvnow.tv_sec;
1497         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1498
1499         /* compare current time with the given timespec */
1500
1501         return threads_timespec_earlier(&tsnow, tv);
1502 }
1503
1504
1505 /* threads_wait_with_timeout ***************************************************
1506
1507    Wait until the given point in time on a monitor until either
1508    we are notified, we are interrupted, or the time is up.
1509
1510    IN:
1511       t............the current thread
1512           wakeupTime...absolute (latest) wakeup time
1513                            If both tv_sec and tv_nsec are zero, this function
1514                                            waits for an unlimited amount of time.
1515
1516    RETURN VALUE:
1517       true.........if the wait has been interrupted,
1518           false........if the wait was ended by notification or timeout
1519
1520 *******************************************************************************/
1521
1522 static bool threads_wait_with_timeout(threadobject *t,
1523                                                                           struct timespec *wakeupTime)
1524 {
1525         bool wasinterrupted;
1526
1527         /* acquire the waitmutex */
1528
1529         pthread_mutex_lock(&t->waitmutex);
1530
1531         /* mark us as sleeping */
1532
1533         t->sleeping = true;
1534
1535         /* wait on waitcond */
1536
1537         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1538                 /* with timeout */
1539                 while (!t->interrupted && !t->signaled
1540                            && threads_current_time_is_earlier_than(wakeupTime))
1541                 {
1542                         pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1543                 }
1544         }
1545         else {
1546                 /* no timeout */
1547                 while (!t->interrupted && !t->signaled)
1548                         pthread_cond_wait(&t->waitcond, &t->waitmutex);
1549         }
1550
1551         /* check if we were interrupted */
1552
1553         wasinterrupted = t->interrupted;
1554
1555         /* reset all flags */
1556
1557         t->interrupted = false;
1558         t->signaled = false;
1559         t->sleeping = false;
1560
1561         /* release the waitmutex */
1562
1563         pthread_mutex_unlock(&t->waitmutex);
1564
1565         return wasinterrupted;
1566 }
1567
1568
1569 /* threads_wait_with_timeout_relative ******************************************
1570
1571    Wait for the given maximum amount of time on a monitor until either
1572    we are notified, we are interrupted, or the time is up.
1573
1574    IN:
1575       t............the current thread
1576           millis.......milliseconds to wait
1577           nanos........nanoseconds to wait
1578
1579    RETURN VALUE:
1580       true.........if the wait has been interrupted,
1581           false........if the wait was ended by notification or timeout
1582
1583 *******************************************************************************/
1584
1585 bool threads_wait_with_timeout_relative(threadobject *t,
1586                                                                                 s8 millis,
1587                                                                                 s4 nanos)
1588 {
1589         struct timespec wakeupTime;
1590
1591         /* calculate the the (latest) wakeup time */
1592
1593         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1594
1595         /* wait */
1596
1597         return threads_wait_with_timeout(t, &wakeupTime);
1598 }
1599
1600
1601 /* threads_calc_absolute_time **************************************************
1602
1603    Calculate the absolute point in time a given number of ms and ns from now.
1604
1605    IN:
1606       millis............milliseconds from now
1607           nanos.............nanoseconds from now
1608
1609    OUT:
1610       *tm...............receives the timespec of the absolute point in time
1611
1612 *******************************************************************************/
1613
1614 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1615 {
1616         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1617                 struct timeval tv;
1618                 long nsec;
1619                 gettimeofday(&tv, NULL);
1620                 tv.tv_sec += millis / 1000;
1621                 millis %= 1000;
1622                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1623                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1624                 tm->tv_nsec = nsec % 1000000000;
1625         }
1626         else {
1627                 tm->tv_sec = 0;
1628                 tm->tv_nsec = 0;
1629         }
1630 }
1631
1632
1633 /* threads_interrupt_thread ****************************************************
1634
1635    Interrupt the given thread.
1636
1637    The thread gets the "waitcond" signal and 
1638    its interrupted flag is set to true.
1639
1640    IN:
1641       thread............the thread to interrupt
1642
1643 *******************************************************************************/
1644
1645 void threads_interrupt_thread(java_lang_VMThread *thread)
1646 {
1647         threadobject *t = (threadobject*) thread;
1648
1649         /* signal the thread a "waitcond" and tell it that it has been */
1650         /* interrupted                                                 */
1651
1652         pthread_mutex_lock(&t->waitmutex);
1653         if (t->sleeping)
1654                 pthread_cond_signal(&t->waitcond);
1655         t->interrupted = true;
1656         pthread_mutex_unlock(&t->waitmutex);
1657 }
1658
1659
1660 /* threads_check_if_interrupted_and_reset **************************************
1661
1662    Check if the current thread has been interrupted and reset the
1663    interruption flag.
1664
1665    RETURN VALUE:
1666       true, if the current thread had been interrupted
1667
1668 *******************************************************************************/
1669
1670 bool threads_check_if_interrupted_and_reset(void)
1671 {
1672         threadobject *t;
1673         bool intr;
1674
1675         t = (threadobject*) THREADOBJECT;
1676
1677         intr = t->interrupted;
1678
1679         t->interrupted = false;
1680
1681         return intr;
1682 }
1683
1684
1685 /* threads_thread_has_been_interrupted *********************************************************
1686
1687    Check if the given thread has been interrupted
1688
1689    IN:
1690       t............the thread to check
1691
1692    RETURN VALUE:
1693       true, if the given thread had been interrupted
1694
1695 *******************************************************************************/
1696
1697 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1698 {
1699         threadobject *t;
1700
1701         t = (threadobject*) thread;
1702
1703         return t->interrupted;
1704 }
1705
1706
1707 /* threads_sleep ***************************************************************
1708
1709    Sleep the current thread for the specified amount of time.
1710
1711 *******************************************************************************/
1712
1713 void threads_sleep(s8 millis, s4 nanos)
1714 {
1715         threadobject       *t;
1716         struct timespec    wakeupTime;
1717         bool               wasinterrupted;
1718
1719         t = (threadobject *) THREADOBJECT;
1720
1721         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1722
1723         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1724
1725         if (wasinterrupted)
1726                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1727 }
1728
1729
1730 /* threads_yield *****************************************************************
1731
1732    Yield to the scheduler.
1733
1734 *******************************************************************************/
1735
1736 void threads_yield(void)
1737 {
1738         sched_yield();
1739 }
1740
1741
1742 /* threads_java_lang_Thread_set_priority ***********************************************************
1743
1744    Set the priority for the given java.lang.Thread.
1745
1746    IN:
1747       t............the java.lang.Thread
1748           priority.....the priority
1749
1750 *******************************************************************************/
1751
1752 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1753 {
1754         threadobject *thread;
1755
1756         thread = (threadobject*) t->vmThread;
1757
1758         threads_set_thread_priority(thread->tid, priority);
1759 }
1760
1761
1762 /* threads_dump ****************************************************************
1763
1764    Dumps info for all threads running in the JVM. This function is
1765    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1766
1767 *******************************************************************************/
1768
1769 void threads_dump(void)
1770 {
1771         threadobject       *tobj;
1772         java_lang_VMThread *vmt;
1773         java_lang_Thread   *t;
1774         utf                *name;
1775
1776         tobj = mainthreadobj;
1777
1778         printf("Full thread dump CACAO "VERSION":\n");
1779
1780         /* iterate over all started threads */
1781
1782         do {
1783                 /* get thread objects */
1784
1785                 vmt = &tobj->o;
1786                 t   = vmt->thread;
1787
1788                 /* the thread may be currently in initalization, don't print it */
1789
1790                 if (t) {
1791                         /* get thread name */
1792
1793                         name = javastring_toutf(t->name, false);
1794
1795                         printf("\n\"");
1796                         utf_display_printable_ascii(name);
1797                         printf("\" ");
1798
1799                         if (t->daemon)
1800                                 printf("daemon ");
1801
1802 #if SIZEOF_VOID_P == 8
1803                         printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1804 #else
1805                         printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1806 #endif
1807
1808                         /* send SIGUSR1 to thread to print stacktrace */
1809
1810                         pthread_kill(tobj->tid, SIGUSR1);
1811
1812                         /* sleep this thread a bit, so the signal can reach the thread */
1813
1814                         threads_sleep(10, 0);
1815                 }
1816
1817                 tobj = tobj->next;
1818         } while (tobj && (tobj != mainthreadobj));
1819 }
1820
1821
1822 /* threads_table_dump *********************************************************
1823
1824    Dump the threads table for debugging purposes.
1825
1826    IN:
1827       file..............stream to write to
1828
1829 ******************************************************************************/
1830
1831 #if !defined(NDEBUG)
1832 static void threads_table_dump(FILE *file)
1833 {
1834         s4 i;
1835         s4 size;
1836         ptrint index;
1837
1838         pthread_mutex_lock(&threadlistlock);
1839
1840         size = threads_table.size;
1841
1842         fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1843
1844         for (i=0; i<size; ++i) {
1845                 index = threads_table.table[i].nextfree;
1846
1847                 fprintf(file, "%4d: ", i);
1848
1849                 if (index < size) {
1850                         fprintf(file, "free, nextfree = %d\n", index);
1851                 }
1852                 else {
1853                         fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1854                 }
1855         }
1856
1857         fprintf(file, "======== END OF THREADS TABLE ========\n");
1858
1859         pthread_mutex_unlock(&threadlistlock);
1860 }
1861 #endif
1862
1863 /*
1864  * These are local overrides for various environment variables in Emacs.
1865  * Please do not remove this and leave it at the end of the file, where
1866  * Emacs will automagically detect them.
1867  * ---------------------------------------------------------------------
1868  * Local variables:
1869  * mode: c
1870  * indent-tabs-mode: t
1871  * c-basic-offset: 4
1872  * tab-width: 4
1873  * End:
1874  * vim:noexpandtab:sw=4:ts=4:
1875  */