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