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