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