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