Clean merge -> gc7-branch
[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_CLASSPATH_GNU)
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 # include <semaphore.h>
99 #endif
100 # if defined(__LINUX__)
101 #  define GC_LINUX_THREADS
102 # elif defined(__IRIX__)
103 #  define GC_IRIX_THREADS
104 # elif defined(__DARWIN__)
105 #  define GC_DARWIN_THREADS
106 # endif
107 # if defined(ENABLE_GC_BOEHM)
108 #  include "mm/boehm-gc/include/gc.h"
109 # endif
110
111 #if defined(ENABLE_JVMTI)
112 #include "native/jvmti/cacaodbg.h"
113 #endif
114
115 #if defined(__DARWIN__)
116 /* Darwin has no working semaphore implementation.  This one is taken
117    from Boehm-GC. */
118
119 /*
120    This is a very simple semaphore implementation for darwin. It
121    is implemented in terms of pthreads calls so it isn't async signal
122    safe. This isn't a problem because signals aren't used to
123    suspend threads on darwin.
124 */
125    
126 static int sem_init(sem_t *sem, int pshared, int value)
127 {
128         if (pshared)
129                 assert(0);
130
131         sem->value = value;
132     
133         mutex_init(&sem->mutex);
134
135         if (pthread_cond_init(&sem->cond, NULL) < 0)
136                 return -1;
137
138         return 0;
139 }
140
141 static int sem_post(sem_t *sem)
142 {
143         mutex_lock(&sem->mutex);
144
145         sem->value++;
146
147         if (pthread_cond_signal(&sem->cond) < 0) {
148                 mutex_unlock(&sem->mutex);
149                 return -1;
150         }
151
152         mutex_unlock(&sem->mutex);
153
154         return 0;
155 }
156
157 static int sem_wait(sem_t *sem)
158 {
159         mutex_lock(&sem->mutex);
160
161         while (sem->value == 0) {
162                 pthread_cond_wait(&sem->cond, &sem->mutex);
163         }
164
165         sem->value--;
166
167         mutex_unlock(&sem->mutex);
168
169         return 0;
170 }
171
172 static int sem_destroy(sem_t *sem)
173 {
174         if (pthread_cond_destroy(&sem->cond) < 0)
175                 return -1;
176
177         mutex_destroy(&sem->mutex);
178
179         return 0;
180 }
181 #endif /* defined(__DARWIN__) */
182
183
184 /* internally used constants **************************************************/
185
186 /* CAUTION: Do not change these values. Boehm GC code depends on them.        */
187 #define STOPWORLD_FROM_GC               1
188 #define STOPWORLD_FROM_CLASS_NUMBERING  2
189
190
191 /* startupinfo *****************************************************************
192
193    Struct used to pass info from threads_start_thread to 
194    threads_startup_thread.
195
196 ******************************************************************************/
197
198 typedef struct {
199         threadobject *thread;      /* threadobject for this thread             */
200         functionptr   function;    /* function to run in the new thread        */
201         sem_t        *psem;        /* signals when thread has been entered     */
202                                    /* in the thread list                       */
203         sem_t        *psem_first;  /* signals when pthread_create has returned */
204 } startupinfo;
205
206
207 /* prototypes *****************************************************************/
208
209 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
210
211
212 /******************************************************************************/
213 /* GLOBAL VARIABLES                                                           */
214 /******************************************************************************/
215
216 /* the thread object of the current thread                                    */
217 /* This is either a thread-local variable defined with __thread, or           */
218 /* a thread-specific value stored with key threads_current_threadobject_key.  */
219 #if defined(HAVE___THREAD)
220 __thread threadobject *thread_current;
221 #else
222 pthread_key_t thread_current_key;
223 #endif
224
225 /* global mutex for stop-the-world                                            */
226 static mutex_t stopworldlock;
227
228 #if defined(ENABLE_GC_CACAO)
229 /* global mutex for the GC */
230 static mutex_t mutex_gc;
231 #endif
232
233 /* global mutex and condition for joining threads on exit */
234 static mutex_t mutex_join;
235 static pthread_cond_t  cond_join;
236
237 /* XXX We disable that whole bunch of code until we have the exact-GC
238    running. */
239
240 #if 1
241
242 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
243 /* being stopped                                                              */
244 static volatile int stopworldwhere;
245
246 /* semaphore used for acknowleding thread suspension                          */
247 static sem_t suspend_ack;
248 #if defined(__IRIX__)
249 static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
250 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
251 #endif
252
253 #endif /* 0 */
254
255 /* mutexes used by the fake atomic instructions                               */
256 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
257 mutex_t _cas_lock = MUTEX_INITIALIZER;
258 mutex_t _mb_lock = MUTEX_INITIALIZER;
259 #endif
260
261
262 /* threads_sem_init ************************************************************
263  
264    Initialize a semaphore. Checks against errors and interruptions.
265
266    IN:
267        sem..............the semaphore to initialize
268            shared...........true if this semaphore will be shared between processes
269            value............the initial value for the semaphore
270    
271 *******************************************************************************/
272
273 void threads_sem_init(sem_t *sem, bool shared, int value)
274 {
275         int r;
276
277         assert(sem);
278
279         do {
280                 r = sem_init(sem, shared, value);
281                 if (r == 0)
282                         return;
283         } while (errno == EINTR);
284
285         vm_abort("sem_init failed: %s", strerror(errno));
286 }
287
288
289 /* threads_sem_wait ************************************************************
290  
291    Wait for a semaphore, non-interruptible.
292
293    IMPORTANT: Always use this function instead of `sem_wait` directly, as
294               `sem_wait` may be interrupted by signals!
295   
296    IN:
297        sem..............the semaphore to wait on
298    
299 *******************************************************************************/
300
301 void threads_sem_wait(sem_t *sem)
302 {
303         int r;
304
305         assert(sem);
306
307         do {
308                 r = sem_wait(sem);
309                 if (r == 0)
310                         return;
311         } while (errno == EINTR);
312
313         vm_abort("sem_wait failed: %s", strerror(errno));
314 }
315
316
317 /* threads_sem_post ************************************************************
318  
319    Increase the count of a semaphore. Checks for errors.
320
321    IN:
322        sem..............the semaphore to increase the count of
323    
324 *******************************************************************************/
325
326 void threads_sem_post(sem_t *sem)
327 {
328         int r;
329
330         assert(sem);
331
332         /* unlike sem_wait, sem_post is not interruptible */
333
334         r = sem_post(sem);
335         if (r == 0)
336                 return;
337
338         vm_abort("sem_post failed: %s", strerror(errno));
339 }
340
341
342 /* lock_stopworld **************************************************************
343
344    Enter the stopworld lock, specifying why the world shall be stopped.
345
346    IN:
347       where........ STOPWORLD_FROM_GC              (1) from within GC
348                     STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
349
350 ******************************************************************************/
351
352 void lock_stopworld(int where)
353 {
354         mutex_lock(&stopworldlock);
355 /*      stopworldwhere = where; */
356 }
357
358
359 /* unlock_stopworld ************************************************************
360
361    Release the stopworld lock.
362
363 ******************************************************************************/
364
365 void unlock_stopworld(void)
366 {
367 /*      stopworldwhere = 0; */
368         mutex_unlock(&stopworldlock);
369 }
370
371 /* XXX We disable that whole bunch of code until we have the exact-GC
372    running. */
373
374 #if 0
375
376 #if !defined(__DARWIN__)
377 /* Caller must hold threadlistlock */
378 static s4 threads_cast_sendsignals(s4 sig)
379 {
380         threadobject *t;
381         threadobject *self;
382         s4            count;
383
384         self = THREADOBJECT;
385
386         /* iterate over all started threads */
387
388         count = 0;
389
390         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
391                 /* don't send the signal to ourself */
392
393                 if (t == self)
394                         continue;
395
396                 /* don't send the signal to NEW threads (because they are not
397                    completely initialized) */
398
399                 if (t->state == THREAD_STATE_NEW)
400                         continue;
401
402                 /* send the signal */
403
404                 pthread_kill(t->tid, sig);
405
406                 /* increase threads count */
407
408                 count++;
409         }
410
411         return count;
412 }
413
414 #else
415
416 static void threads_cast_darwinstop(void)
417 {
418         threadobject *tobj = mainthreadobj;
419         threadobject *self = THREADOBJECT;
420
421         do {
422                 if (tobj != self)
423                 {
424                         thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
425                         mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
426 #if defined(__I386__)
427                         i386_thread_state_t thread_state;
428 #else
429                         ppc_thread_state_t thread_state;
430 #endif
431                         mach_port_t thread = tobj->mach_thread;
432                         kern_return_t r;
433
434                         r = thread_suspend(thread);
435
436                         if (r != KERN_SUCCESS)
437                                 vm_abort("thread_suspend failed");
438
439                         r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
440                                                                  &thread_state_count);
441
442                         if (r != KERN_SUCCESS)
443                                 vm_abort("thread_get_state failed");
444
445                         md_critical_section_restart((ucontext_t *) &thread_state);
446
447                         r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
448                                                                  thread_state_count);
449
450                         if (r != KERN_SUCCESS)
451                                 vm_abort("thread_set_state failed");
452                 }
453
454                 tobj = tobj->next;
455         } while (tobj != mainthreadobj);
456 }
457
458 static void threads_cast_darwinresume(void)
459 {
460         threadobject *tobj = mainthreadobj;
461         threadobject *self = THREADOBJECT;
462
463         do {
464                 if (tobj != self)
465                 {
466                         mach_port_t thread = tobj->mach_thread;
467                         kern_return_t r;
468
469                         r = thread_resume(thread);
470
471                         if (r != KERN_SUCCESS)
472                                 vm_abort("thread_resume failed");
473                 }
474
475                 tobj = tobj->next;
476         } while (tobj != mainthreadobj);
477 }
478
479 #endif
480
481 #if defined(__IRIX__)
482 static void threads_cast_irixresume(void)
483 {
484         mutex_lock(&suspend_ack_lock);
485         pthread_cond_broadcast(&suspend_cond);
486         mutex_unlock(&suspend_ack_lock);
487 }
488 #endif
489
490 #if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
491 static void threads_sigsuspend_handler(ucontext_t *_uc)
492 {
493         int sig;
494         sigset_t sigs;
495
496         /* XXX TWISTI: this is just a quick hack */
497 #if defined(ENABLE_JIT)
498         md_critical_section_restart(_uc);
499 #endif
500
501         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
502            (not POSIX async-safe). */
503 #if defined(__IRIX__)
504         mutex_lock(&suspend_ack_lock);
505         threads_sem_post(&suspend_ack);
506         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
507         mutex_unlock(&suspend_ack_lock);
508 #elif defined(__CYGWIN__)
509         /* TODO */
510         assert(0);
511 #else
512
513         sig = GC_signum2();
514         sigfillset(&sigs);
515         sigdelset(&sigs, sig);
516         sigsuspend(&sigs);
517 #endif
518 }
519 #endif
520
521 #endif
522
523
524 /* threads_stopworld ***********************************************************
525
526    Stops the world from turning. All threads except the calling one
527    are suspended. The function returns as soon as all threads have
528    acknowledged their suspension.
529
530 *******************************************************************************/
531
532 #if !defined(DISABLE_GC)
533 void threads_stopworld(void)
534 {
535 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
536         threadobject *t;
537         threadobject *self;
538         bool result;
539         s4 count, i;
540 #endif
541
542         lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
543
544         /* lock the threads lists */
545
546         threadlist_lock();
547
548 #if defined(__DARWIN__)
549         /*threads_cast_darwinstop();*/
550         assert(0);
551 #elif defined(__CYGWIN__)
552         /* TODO */
553         assert(0);
554 #else
555         self = THREADOBJECT;
556
557         DEBUGTHREADS("stops World", self);
558
559         count = 0;
560
561         /* suspend all running threads */
562         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
563                 /* don't send the signal to ourself */
564
565                 if (t == self)
566                         continue;
567
568                 /* don't send the signal to NEW threads (because they are not
569                    completely initialized) */
570
571                 if (t->state == THREAD_STATE_NEW)
572                         continue;
573
574                 /* send the signal */
575
576                 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
577                 assert(result);
578
579                 /* increase threads count */
580
581                 count++;
582         }
583
584         /* wait for all threads signaled to suspend */
585         for (i = 0; i < count; i++)
586                 threads_sem_wait(&suspend_ack);
587 #endif
588
589         /* ATTENTION: Don't unlock the threads-lists here so that
590            non-signaled NEW threads can't change their state and execute
591            code. */
592 }
593 #endif /* !defined(DISABLE_GC) */
594
595
596 /* threads_startworld **********************************************************
597
598    Starts the world again after it has previously been stopped. 
599
600 *******************************************************************************/
601
602 #if !defined(DISABLE_GC)
603 void threads_startworld(void)
604 {
605 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
606         threadobject *t;
607         threadobject *self;
608         bool result;
609         s4 count, i;
610 #endif
611
612 #if defined(__DARWIN__)
613         /*threads_cast_darwinresume();*/
614         assert(0);
615 #elif defined(__IRIX__)
616         threads_cast_irixresume();
617 #elif defined(__CYGWIN__)
618         /* TODO */
619         assert(0);
620 #else
621         self = THREADOBJECT;
622
623         DEBUGTHREADS("starts World", self);
624
625         count = 0;
626
627         /* resume all thread we haltet */
628         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
629                 /* don't send the signal to ourself */
630
631                 if (t == self)
632                         continue;
633
634                 /* don't send the signal to NEW threads (because they are not
635                    completely initialized) */
636
637                 if (t->state == THREAD_STATE_NEW)
638                         continue;
639
640                 /* send the signal */
641
642                 result = threads_resume_thread(t);
643                 assert(result);
644
645                 /* increase threads count */
646
647                 count++;
648         }
649
650         /* wait for all threads signaled to suspend */
651         for (i = 0; i < count; i++)
652                 threads_sem_wait(&suspend_ack);
653
654 #endif
655
656         /* unlock the threads lists */
657
658         threadlist_unlock();
659
660         unlock_stopworld();
661 }
662 #endif
663
664
665 /* threads_impl_thread_init ****************************************************
666
667    Initialize OS-level locking constructs in threadobject.
668
669    IN:
670       t....the threadobject
671
672 *******************************************************************************/
673
674 void threads_impl_thread_init(threadobject *t)
675 {
676         int result;
677
678         /* initialize the mutex and the condition */
679
680         mutex_init(&t->flc_lock);
681
682         result = pthread_cond_init(&t->flc_cond, NULL);
683         if (result != 0)
684                 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
685
686         mutex_init(&(t->waitmutex));
687
688         result = pthread_cond_init(&(t->waitcond), NULL);
689         if (result != 0)
690                 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
691
692         mutex_init(&(t->suspendmutex));
693
694         result = pthread_cond_init(&(t->suspendcond), NULL);
695         if (result != 0)
696                 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
697 }
698
699 /* threads_impl_thread_clear ***************************************************
700
701    Clears all fields in threadobject the way an MZERO would have
702    done. MZERO cannot be used anymore because it would mess up the
703    pthread_* bits.
704
705    IN:
706       t....the threadobject
707
708 *******************************************************************************/
709
710 void threads_impl_thread_clear(threadobject *t)
711 {
712         t->object = NULL;
713
714         t->thinlock = 0;
715
716         t->index = 0;
717         t->flags = 0;
718         t->state = 0;
719
720         t->tid = 0;
721
722 #if defined(__DARWIN__)
723         t->mach_thread = 0;
724 #endif
725
726         t->interrupted = false;
727         t->signaled = false;
728         t->sleeping = false;
729
730         t->suspended = false;
731         t->suspend_reason = 0;
732
733         t->pc = NULL;
734
735         t->_exceptionptr = NULL;
736         t->_stackframeinfo = NULL;
737         t->_localref_table = NULL;
738
739 #if defined(ENABLE_INTRP)
740         t->_global_sp = NULL;
741 #endif
742
743 #if defined(ENABLE_GC_CACAO)
744         t->gc_critical = false;
745
746         t->ss = NULL;
747         t->es = NULL;
748 #endif
749
750         MZERO(&t->dumpinfo, dumpinfo_t, 1);
751 }
752
753 /* threads_impl_thread_reuse ***************************************************
754
755    Resets some implementation fields in threadobject. This was
756    previously done in threads_impl_thread_new.
757
758    IN:
759       t....the threadobject
760
761 *******************************************************************************/
762
763 void threads_impl_thread_reuse(threadobject *t)
764 {
765         /* get the pthread id */
766
767         t->tid = pthread_self();
768
769 #if defined(ENABLE_DEBUG_FILTER)
770         /* Initialize filter counters */
771         t->filterverbosecallctr[0] = 0;
772         t->filterverbosecallctr[1] = 0;
773 #endif
774
775 #if !defined(NDEBUG)
776         t->tracejavacallindent = 0;
777         t->tracejavacallcount = 0;
778 #endif
779
780         t->flc_bit = false;
781         t->flc_next = NULL;
782         t->flc_list = NULL;
783
784 /*      not really needed */
785         t->flc_object = NULL;
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 mutext */
856
857         mutex_init(&mutex_gc);
858 #endif
859
860 #if !defined(HAVE___THREAD)
861         result = pthread_key_create(&thread_current_key, NULL);
862         if (result != 0)
863                 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
864 #endif
865
866         threads_sem_init(&suspend_ack, 0, 0);
867 }
868
869
870 /* threads_mutex_gc_lock *******************************************************
871
872    Enter the global GC mutex.
873
874 *******************************************************************************/
875
876 #if defined(ENABLE_GC_CACAO)
877 void threads_mutex_gc_lock(void)
878 {
879         mutex_lock(&mutex_gc);
880 }
881 #endif
882
883
884 /* threads_mutex_gc_unlock *****************************************************
885
886    Leave the global GC mutex.
887
888 *******************************************************************************/
889
890 #if defined(ENABLE_GC_CACAO)
891 void threads_mutex_gc_unlock(void)
892 {
893         mutex_unlock(&mutex_gc);
894 }
895 #endif
896
897 /* threads_mutex_join_lock *****************************************************
898
899    Enter the join mutex.
900
901 *******************************************************************************/
902
903 void threads_mutex_join_lock(void)
904 {
905         mutex_lock(&mutex_join);
906 }
907
908
909 /* threads_mutex_join_unlock ***************************************************
910
911    Leave the join mutex.
912
913 *******************************************************************************/
914
915 void threads_mutex_join_unlock(void)
916 {
917         mutex_unlock(&mutex_join);
918 }
919
920
921 /* threads_impl_init ***********************************************************
922
923    Initializes the implementation specific bits.
924
925 *******************************************************************************/
926
927 void threads_impl_init(void)
928 {
929         pthread_attr_t attr;
930         int            result;
931
932         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
933
934         /* Initialize the thread attribute object. */
935
936         result = pthread_attr_init(&attr);
937
938         if (result != 0)
939                 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
940
941         result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
942
943         if (result != 0)
944                 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
945 }
946
947
948 /* threads_startup_thread ******************************************************
949
950    Thread startup function called by pthread_create.
951
952    Thread which have a startup.function != NULL are marked as internal
953    threads. All other threads are threated as normal Java threads.
954
955    NOTE: This function is not called directly by pthread_create. The Boehm GC
956          inserts its own GC_start_routine in between, which then calls
957                  threads_startup.
958
959    IN:
960       arg..........the argument passed to pthread_create, ie. a pointer to
961                        a startupinfo struct. CAUTION: When the `psem` semaphore
962                                    is posted, the startupinfo struct becomes invalid! (It
963                                    is allocated on the stack of threads_start_thread.)
964
965 ******************************************************************************/
966
967 static void *threads_startup_thread(void *arg)
968 {
969         startupinfo        *startup;
970         threadobject       *t;
971         java_lang_Thread   *object;
972 #if defined(WITH_CLASSPATH_GNU)
973         java_lang_VMThread *vmt;
974 #endif
975         sem_t              *psem;
976         classinfo          *c;
977         methodinfo         *m;
978         java_handle_t      *o;
979         functionptr         function;
980
981 #if defined(ENABLE_INTRP)
982         u1 *intrp_thread_stack;
983
984         /* create interpreter stack */
985
986         if (opt_intrp) {
987                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
988                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
989         }
990         else
991                 intrp_thread_stack = NULL;
992 #endif
993
994         /* get passed startupinfo structure and the values in there */
995
996         startup = arg;
997
998         t        = startup->thread;
999         function = startup->function;
1000         psem     = startup->psem;
1001
1002         /* Seems like we've encountered a situation where thread->tid was
1003            not set by pthread_create. We alleviate this problem by waiting
1004            for pthread_create to return. */
1005
1006         threads_sem_wait(startup->psem_first);
1007
1008 #if defined(__DARWIN__)
1009         t->mach_thread = mach_thread_self();
1010 #endif
1011
1012         /* Now that we are in the new thread, we can store the internal
1013            thread data-structure in the TSD. */
1014
1015         thread_set_current(t);
1016
1017         /* get the java.lang.Thread object for this thread */
1018
1019         object = (java_lang_Thread *) thread_get_object(t);
1020
1021         /* set our priority */
1022
1023         threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
1024
1025         /* Thread is completely initialized. */
1026
1027         thread_set_state_runnable(t);
1028
1029         /* tell threads_startup_thread that we registered ourselves */
1030         /* CAUTION: *startup becomes invalid with this!             */
1031
1032         startup = NULL;
1033         threads_sem_post(psem);
1034
1035 #if defined(ENABLE_INTRP)
1036         /* set interpreter stack */
1037
1038         if (opt_intrp)
1039                 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1040 #endif
1041
1042 #if defined(ENABLE_JVMTI)
1043         /* fire thread start event */
1044
1045         if (jvmti) 
1046                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1047 #endif
1048
1049         DEBUGTHREADS("starting", t);
1050
1051         /* find and run the Thread.run()V method if no other function was passed */
1052
1053         if (function == NULL) {
1054 #if defined(WITH_CLASSPATH_GNU)
1055                 /* We need to start the run method of
1056                    java.lang.VMThread. Since this is a final class, we can use
1057                    the class object directly. */
1058
1059                 c = class_java_lang_VMThread;
1060 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1061                 LLNI_class_get(object, c);
1062 #else
1063 # error unknown classpath configuration
1064 #endif
1065
1066                 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1067
1068                 if (m == NULL)
1069                         vm_abort("threads_startup_thread: run() method not found in class");
1070
1071                 /* set ThreadMXBean variables */
1072
1073                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1074                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1075
1076                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1077                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1078                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1079                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1080
1081 #if defined(WITH_CLASSPATH_GNU)
1082                 /* we need to start the run method of java.lang.VMThread */
1083
1084                 LLNI_field_get_ref(object, vmThread, vmt);
1085                 o = (java_handle_t *) vmt;
1086
1087 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1088                 o = (java_handle_t *) object;
1089 #else
1090 # error unknown classpath configuration
1091 #endif
1092
1093                 /* Run the thread. */
1094
1095                 (void) vm_call_method(m, o);
1096         }
1097         else {
1098                 /* set ThreadMXBean variables */
1099
1100                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1101                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1102
1103                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1104                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1105                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1106                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1107
1108                 /* call passed function, e.g. finalizer_thread */
1109
1110                 (function)();
1111         }
1112
1113         DEBUGTHREADS("stopping", t);
1114
1115 #if defined(ENABLE_JVMTI)
1116         /* fire thread end event */
1117
1118         if (jvmti)
1119                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1120 #endif
1121
1122         /* We ignore the return value. */
1123
1124         (void) threads_detach_thread(t);
1125
1126         /* set ThreadMXBean variables */
1127
1128         _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1129
1130         return NULL;
1131 }
1132
1133
1134 /* threads_impl_thread_start ***************************************************
1135
1136    Start a thread in the JVM.  Both (vm internal and java) thread
1137    objects exist.
1138
1139    IN:
1140       thread....the thread object
1141           f.........function to run in the new thread. NULL means that the
1142                     "run" method of the object `t` should be called
1143
1144 ******************************************************************************/
1145
1146 void threads_impl_thread_start(threadobject *thread, functionptr f)
1147 {
1148         sem_t          sem;
1149         sem_t          sem_first;
1150         pthread_attr_t attr;
1151         startupinfo    startup;
1152         int            result;
1153
1154         /* fill startupinfo structure passed by pthread_create to
1155          * threads_startup_thread */
1156
1157         startup.thread     = thread;
1158         startup.function   = f;              /* maybe we don't call Thread.run()V */
1159         startup.psem       = &sem;
1160         startup.psem_first = &sem_first;
1161
1162         threads_sem_init(&sem, 0, 0);
1163         threads_sem_init(&sem_first, 0, 0);
1164
1165         /* Initialize thread attributes. */
1166
1167         result = pthread_attr_init(&attr);
1168
1169         if (result != 0)
1170                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
1171
1172     result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1173
1174     if (result != 0)
1175                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
1176
1177         /* initialize thread stacksize */
1178
1179         result = pthread_attr_setstacksize(&attr, opt_stacksize);
1180
1181         if (result != 0)
1182                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
1183
1184         /* create the thread */
1185
1186         result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1187
1188         if (result != 0)
1189                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1190
1191         /* destroy the thread attributes */
1192
1193         result = pthread_attr_destroy(&attr);
1194
1195         if (result != 0)
1196                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1197
1198         /* signal that pthread_create has returned, so thread->tid is valid */
1199
1200         threads_sem_post(&sem_first);
1201
1202         /* wait here until the thread has entered itself into the thread list */
1203
1204         threads_sem_wait(&sem);
1205
1206         /* cleanup */
1207
1208         sem_destroy(&sem);
1209         sem_destroy(&sem_first);
1210 }
1211
1212
1213 /* threads_set_thread_priority *************************************************
1214
1215    Set the priority of the given thread.
1216
1217    IN:
1218       tid..........thread id
1219           priority.....priority to set
1220
1221 ******************************************************************************/
1222
1223 void threads_set_thread_priority(pthread_t tid, int priority)
1224 {
1225         struct sched_param schedp;
1226         int policy;
1227
1228         pthread_getschedparam(tid, &policy, &schedp);
1229         schedp.sched_priority = priority;
1230         pthread_setschedparam(tid, policy, &schedp);
1231 }
1232
1233
1234 /* threads_detach_thread *******************************************************
1235
1236    Detaches the passed thread from the VM.  Used in JNI.
1237
1238 *******************************************************************************/
1239
1240 bool threads_detach_thread(threadobject *t)
1241 {
1242         bool                   result;
1243         java_lang_Thread      *object;
1244         java_handle_t         *o;
1245 #if defined(ENABLE_JAVASE)
1246         java_lang_ThreadGroup *group;
1247         java_handle_t         *e;
1248         void                  *handler;
1249         classinfo             *c;
1250         methodinfo            *m;
1251 #endif
1252
1253     /* If the given thread has already been detached, this operation
1254            is a no-op. */
1255
1256         result = thread_is_attached(t);
1257
1258         if (result == false)
1259                 return true;
1260
1261         DEBUGTHREADS("detaching", t);
1262
1263         object = (java_lang_Thread *) thread_get_object(t);
1264
1265 #if defined(ENABLE_JAVASE)
1266         LLNI_field_get_ref(object, group, group);
1267
1268     /* If there's an uncaught exception, call uncaughtException on the
1269        thread's exception handler, or the thread's group if this is
1270        unset. */
1271
1272         e = exceptions_get_and_clear_exception();
1273
1274     if (e != NULL) {
1275                 /* We use the type void* for handler here, as it's not trivial
1276                    to build the java_lang_Thread_UncaughtExceptionHandler
1277                    header file with cacaoh. */
1278
1279 # if defined(WITH_CLASSPATH_GNU)
1280                 LLNI_field_get_ref(object, exceptionHandler, handler);
1281 # elif defined(WITH_CLASSPATH_SUN)
1282                 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1283 # endif
1284
1285                 if (handler != NULL) {
1286                         LLNI_class_get(handler, c);
1287                         o = (java_handle_t *) handler;
1288                 }
1289                 else {
1290                         LLNI_class_get(group, c);
1291                         o = (java_handle_t *) group;
1292                 }
1293
1294                 m = class_resolveclassmethod(c,
1295                                                                          utf_uncaughtException,
1296                                                                          utf_java_lang_Thread_java_lang_Throwable__V,
1297                                                                          NULL,
1298                                                                          true);
1299
1300                 if (m == NULL)
1301                         return false;
1302
1303                 (void) vm_call_method(m, o, object, e);
1304
1305                 if (exceptions_get_exception())
1306                         return false;
1307     }
1308
1309         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1310
1311         /* Remove thread from the thread group. */
1312
1313         if (group != NULL) {
1314                 LLNI_class_get(group, c);
1315
1316 # if defined(WITH_CLASSPATH_GNU)
1317                 m = class_resolveclassmethod(c,
1318                                                                          utf_removeThread,
1319                                                                          utf_java_lang_Thread__V,
1320                                                                          class_java_lang_ThreadGroup,
1321                                                                          true);
1322 # elif defined(WITH_CLASSPATH_SUN)
1323                 m = class_resolveclassmethod(c,
1324                                                                          utf_remove,
1325                                                                          utf_java_lang_Thread__V,
1326                                                                          class_java_lang_ThreadGroup,
1327                                                                          true);
1328 # else
1329 #  error unknown classpath configuration
1330 # endif
1331
1332                 if (m == NULL)
1333                         return false;
1334
1335                 o = (java_handle_t *) group;
1336
1337                 (void) vm_call_method(m, o, object);
1338
1339                 if (exceptions_get_exception())
1340                         return false;
1341
1342                 /* Reset the threadgroup in the Java thread object (Mauve
1343                    test: gnu/testlet/java/lang/Thread/getThreadGroup). */
1344
1345                 LLNI_field_set_ref(object, group, NULL);
1346         }
1347 #endif
1348
1349         /* Thread has terminated. */
1350
1351         thread_set_state_terminated(t);
1352
1353         /* Notify all threads waiting on this thread.  These are joining
1354            this thread. */
1355
1356         o = (java_handle_t *) object;
1357
1358         /* XXX Care about exceptions? */
1359         (void) lock_monitor_enter(o);
1360         
1361         lock_notify_all_object(o);
1362
1363         /* XXX Care about exceptions? */
1364         (void) lock_monitor_exit(o);
1365
1366         /* Enter the join-mutex before calling thread_free, so
1367            threads_join_all_threads gets the correct number of non-daemon
1368            threads. */
1369
1370         threads_mutex_join_lock();
1371
1372         /* Free the internal thread data-structure. */
1373
1374         thread_free(t);
1375
1376         /* Signal that this thread has finished and leave the mutex. */
1377
1378         pthread_cond_signal(&cond_join);
1379         threads_mutex_join_unlock();
1380
1381         return true;
1382 }
1383
1384
1385 /* threads_suspend_thread ******************************************************
1386
1387    Suspend the passed thread. Execution stops until the thread
1388    is explicitly resumend again.
1389
1390    IN:
1391      reason.....Reason for suspending this thread.
1392
1393 *******************************************************************************/
1394
1395 bool threads_suspend_thread(threadobject *thread, s4 reason)
1396 {
1397         /* acquire the suspendmutex */
1398         mutex_lock(&(thread->suspendmutex));
1399
1400         if (thread->suspended) {
1401                 mutex_unlock(&(thread->suspendmutex));
1402                 return false;
1403         }
1404
1405         /* set the reason for the suspension */
1406         thread->suspend_reason = reason;
1407
1408         /* send the suspend signal to the thread */
1409         assert(thread != THREADOBJECT);
1410         if (pthread_kill(thread->tid, SIGUSR1) != 0)
1411                 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1412                                  strerror(errno));
1413
1414         /* REMEMBER: do not release the suspendmutex, this is done
1415            by the thread itself in threads_suspend_ack().  */
1416
1417         return true;
1418 }
1419
1420
1421 /* threads_suspend_ack *********************************************************
1422
1423    Acknowledges the suspension of the current thread.
1424
1425    IN:
1426      pc.....The PC where the thread suspended its execution.
1427      sp.....The SP before the thread suspended its execution.
1428
1429 *******************************************************************************/
1430
1431 void threads_suspend_ack(u1* pc, u1* sp)
1432 {
1433         threadobject *thread;
1434
1435         thread = THREADOBJECT;
1436
1437         assert(thread->suspend_reason != 0);
1438
1439         /* TODO: remember dump memory size */
1440
1441 #if defined(ENABLE_GC_CACAO)
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 #endif
1455
1456         /* mark this thread as suspended and remember the PC */
1457         thread->pc        = pc;
1458         thread->suspended = true;
1459
1460         /* if we are stopping the world, we should send a global ack */
1461         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1462                 threads_sem_post(&suspend_ack);
1463         }
1464
1465         DEBUGTHREADS("suspending", thread);
1466
1467         /* release the suspension mutex and wait till we are resumed */
1468         pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1469
1470         DEBUGTHREADS("resuming", thread);
1471
1472         /* if we are stopping the world, we should send a global ack */
1473         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1474                 threads_sem_post(&suspend_ack);
1475         }
1476
1477         /* TODO: free dump memory */
1478
1479         /* release the suspendmutex */
1480         mutex_unlock(&(thread->suspendmutex));
1481 }
1482
1483
1484 /* threads_resume_thread *******************************************************
1485
1486    Resumes the execution of the passed thread.
1487
1488 *******************************************************************************/
1489
1490 bool threads_resume_thread(threadobject *thread)
1491 {
1492         /* acquire the suspendmutex */
1493         mutex_lock(&(thread->suspendmutex));
1494
1495         if (!thread->suspended) {
1496                 mutex_unlock(&(thread->suspendmutex));
1497                 return false;
1498         }
1499
1500         thread->suspended = false;
1501
1502         /* tell everyone that the thread should resume */
1503         assert(thread != THREADOBJECT);
1504         pthread_cond_broadcast(&(thread->suspendcond));
1505
1506         /* release the suspendmutex */
1507         mutex_unlock(&(thread->suspendmutex));
1508
1509         return true;
1510 }
1511
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  */