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