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