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