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