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