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