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