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