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