Merged revisions 7642-7664 via svnmerge from
[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 7667 2007-04-05 00:16:05Z michi $
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 void threads_cast_darwinstop(void)
409 {
410         threadobject *tobj = mainthreadobj;
411         threadobject *self = THREADOBJECT;
412
413         do {
414                 if (tobj != self)
415                 {
416                         thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
417                         mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
418 #if defined(__I386__)
419                         i386_thread_state_t thread_state;
420 #else
421                         ppc_thread_state_t thread_state;
422 #endif
423                         mach_port_t thread = tobj->mach_thread;
424                         kern_return_t r;
425
426                         r = thread_suspend(thread);
427
428                         if (r != KERN_SUCCESS)
429                                 vm_abort("thread_suspend failed");
430
431                         r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
432                                                                  &thread_state_count);
433
434                         if (r != KERN_SUCCESS)
435                                 vm_abort("thread_get_state failed");
436
437                         thread_restartcriticalsection((ucontext_t *) &thread_state);
438
439                         r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
440                                                                  thread_state_count);
441
442                         if (r != KERN_SUCCESS)
443                                 vm_abort("thread_set_state failed");
444                 }
445
446                 tobj = tobj->next;
447         } while (tobj != mainthreadobj);
448 }
449
450 static void threads_cast_darwinresume(void)
451 {
452         threadobject *tobj = mainthreadobj;
453         threadobject *self = THREADOBJECT;
454
455         do {
456                 if (tobj != self)
457                 {
458                         mach_port_t thread = tobj->mach_thread;
459                         kern_return_t r;
460
461                         r = thread_resume(thread);
462
463                         if (r != KERN_SUCCESS)
464                                 vm_abort("thread_resume failed");
465                 }
466
467                 tobj = tobj->next;
468         } while (tobj != mainthreadobj);
469 }
470
471 #endif
472
473 #if defined(__MIPS__)
474 static void threads_cast_irixresume(void)
475 {
476         pthread_mutex_lock(&suspend_ack_lock);
477         pthread_cond_broadcast(&suspend_cond);
478         pthread_mutex_unlock(&suspend_ack_lock);
479 }
480 #endif
481
482 #if 0
483 #if !defined(__DARWIN__)
484 static void threads_sigsuspend_handler(ucontext_t *ctx)
485 {
486         int sig;
487         sigset_t sigs;
488
489         /* XXX TWISTI: this is just a quick hack */
490 #if defined(ENABLE_JIT)
491         thread_restartcriticalsection(ctx);
492 #endif
493
494         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
495            (not POSIX async-safe). */
496 #if defined(__IRIX__)
497         pthread_mutex_lock(&suspend_ack_lock);
498         threads_sem_post(&suspend_ack);
499         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
500         pthread_mutex_unlock(&suspend_ack_lock);
501 #elif defined(__CYGWIN__)
502         /* TODO */
503         assert(0);
504 #else
505         threads_sem_post(&suspend_ack);
506
507         sig = GC_signum2();
508         sigfillset(&sigs);
509         sigdelset(&sigs, sig);
510         sigsuspend(&sigs);
511 #endif
512 }
513 #endif
514 #endif
515
516
517 /* threads_stopworld ***********************************************************
518
519    Stops the world from turning. All threads except the calling one
520    are suspended. The function returns as soon as all threads have
521    acknowledged their suspension.
522
523 *******************************************************************************/
524
525 #if !defined(DISABLE_GC)
526 void threads_stopworld(void)
527 {
528 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
529         threadobject *tobj = mainthreadobj;
530         threadobject *self = THREADOBJECT;
531         bool result;
532         int count, i;
533 #endif
534
535         lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
536         pthread_mutex_lock(&threadlistlock);
537
538 #if defined(__DARWIN__)
539         threads_cast_darwinstop();
540 #elif defined(__CYGWIN__)
541         /* TODO */
542         assert(0);
543 #else
544         /* count how many threads we suspended */
545         count = 0;
546
547         /* suspend all running threads */
548         do {
549                 if (tobj != self) {
550                         result = threads_suspend_thread(tobj, SUSPEND_REASON_STOPWORLD);
551                         assert(result);
552                         count++;
553                 }
554                 tobj = tobj->next;
555         } while (tobj != mainthreadobj);
556
557         /* wait till all threads are suspended */
558         for (i = 0; i < count; i++)
559                 threads_sem_wait(&suspend_ack);
560 #endif
561
562         pthread_mutex_unlock(&threadlistlock);
563 }
564 #endif /* !defined(DISABLE_GC) */
565
566
567 /* threads_startworld **********************************************************
568
569    Starts the world again after it has previously been stopped. 
570
571 *******************************************************************************/
572
573 #if !defined(DISABLE_GC)
574 void threads_startworld(void)
575 {
576 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
577         threadobject *tobj = mainthreadobj;
578         threadobject *self = THREADOBJECT;
579         bool result;
580 #endif
581
582         pthread_mutex_lock(&threadlistlock);
583
584 #if defined(__DARWIN__)
585         threads_cast_darwinresume();
586 #elif defined(__MIPS__)
587         threads_cast_irixresume();
588 #elif defined(__CYGWIN__)
589         /* TODO */
590         assert(0);
591 #else
592         /* resume all thread we haltet */
593         do {
594                 if (tobj != self) {
595                         result = threads_resume_thread(tobj);
596                         assert(result);
597                 }
598                 tobj = tobj->next;
599         } while (tobj != mainthreadobj);
600 #endif
601
602         pthread_mutex_unlock(&threadlistlock);
603         unlock_stopworld();
604 }
605 #endif /* DISABLE_GC */
606
607
608 /* threads_set_current_threadobject ********************************************
609
610    Set the current thread object.
611    
612    IN:
613       thread.......the thread object to set
614
615 *******************************************************************************/
616
617 static void threads_set_current_threadobject(threadobject *thread)
618 {
619 #if !defined(HAVE___THREAD)
620         pthread_setspecific(threads_current_threadobject_key, thread);
621 #else
622         threads_current_threadobject = thread;
623 #endif
624 }
625
626
627 /* threads_init_threadobject **************************************************
628
629    Initialize implementation fields of a threadobject.
630
631    IN:
632       thread............the threadobject
633
634 ******************************************************************************/
635
636 static void threads_init_threadobject(threadobject *thread)
637 {
638         thread->tid = pthread_self();
639
640         thread->index = 0;
641
642 #if defined(ENABLE_GC_CACAO)
643         thread->flags       |= THREAD_FLAG_IN_NATIVE;
644         thread->gc_critical  = false;
645 #endif
646
647         /* TODO destroy all those things */
648         pthread_mutex_init(&(thread->joinmutex), NULL);
649         pthread_cond_init(&(thread->joincond), NULL);
650
651         pthread_mutex_init(&(thread->waitmutex), NULL);
652         pthread_cond_init(&(thread->waitcond), NULL);
653
654         thread->interrupted = false;
655         thread->signaled = false;
656         thread->sleeping = false;
657 }
658
659
660 /* threads_get_current_threadobject ********************************************
661
662    Return the threadobject of the current thread.
663    
664    RETURN VALUE:
665        the current threadobject *
666
667 *******************************************************************************/
668
669 threadobject *threads_get_current_threadobject(void)
670 {
671         return THREADOBJECT;
672 }
673
674
675 /* threads_preinit *************************************************************
676
677    Do some early initialization of stuff required.
678
679    ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
680    is called AFTER this function!
681
682 *******************************************************************************/
683
684 void threads_preinit(void)
685 {
686         pthread_mutexattr_t mutexattr;
687         pthread_mutexattr_init(&mutexattr);
688         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
689         pthread_mutex_init(&compiler_mutex, &mutexattr);
690         pthread_mutexattr_destroy(&mutexattr);
691
692         pthread_mutex_init(&threadlistlock, NULL);
693         pthread_mutex_init(&stopworldlock, NULL);
694
695         mainthreadobj = NEW(threadobject);
696
697 #if defined(ENABLE_STATISTICS)
698         if (opt_stat)
699                 size_threadobject += sizeof(threadobject);
700 #endif
701
702         mainthreadobj->object   = NULL;
703         mainthreadobj->tid      = pthread_self();
704         mainthreadobj->index    = 1;
705         mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
706         
707 #if !defined(HAVE___THREAD)
708         pthread_key_create(&threads_current_threadobject_key, NULL);
709 #endif
710         threads_set_current_threadobject(mainthreadobj);
711
712         threads_sem_init(&suspend_ack, 0, 0);
713
714         /* initialize the threads table */
715
716         threads_table_init();
717
718         /* initialize subsystems */
719
720         lock_init();
721
722         critical_init();
723 }
724
725
726 /* threads_init ****************************************************************
727
728    Initializes the threads required by the JVM: main, finalizer.
729
730 *******************************************************************************/
731
732 bool threads_init(void)
733 {
734         java_lang_String      *threadname;
735         threadobject          *tempthread;
736         java_objectheader     *o;
737
738 #if defined(ENABLE_JAVASE)
739         java_lang_ThreadGroup *threadgroup;
740         methodinfo            *m;
741         java_lang_Thread      *t;
742 #endif
743
744 #if defined(WITH_CLASSPATH_GNU)
745         java_lang_VMThread    *vmt;
746 #endif
747
748         tempthread = mainthreadobj;
749
750         /* XXX We have to find a new way to free lock records */
751         /*     with the new locking algorithm.                */
752         /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
753
754 #if 0
755         /* This is kinda tricky, we grow the java.lang.Thread object so we
756            can keep the execution environment there. No Thread object must
757            have been created at an earlier time. */
758
759         class_java_lang_Thread->instancesize = sizeof(threadobject);
760 #endif
761
762         /* get methods we need in this file */
763
764 #if defined(WITH_CLASSPATH_GNU)
765         method_thread_init =
766                 class_resolveclassmethod(class_java_lang_Thread,
767                                                                  utf_init,
768                                                                  utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
769                                                                  class_java_lang_Thread,
770                                                                  true);
771 #else
772         method_thread_init =
773                 class_resolveclassmethod(class_java_lang_Thread,
774                                                                  utf_init,
775                                                                  utf_new_char("(Ljava/lang/String;)V"),
776                                                                  class_java_lang_Thread,
777                                                                  true);
778 #endif
779
780         if (method_thread_init == NULL)
781                 return false;
782
783         /* create a vm internal thread object for the main thread */
784         /* XXX Michi: we do not need to do this here, we could use the one
785                created by threads_preinit() */
786
787 #if defined(ENABLE_GC_CACAO)
788         mainthreadobj = NEW(threadobject);
789
790 # if defined(ENABLE_STATISTICS)
791         if (opt_stat)
792                 size_threadobject += sizeof(threadobject);
793 # endif
794 #else
795         mainthreadobj = GCNEW(threadobject);
796 #endif
797
798         if (mainthreadobj == NULL)
799                 return false;
800
801         /* create a java.lang.Thread for the main thread */
802
803         mainthreadobj->object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
804
805         if (mainthreadobj->object == NULL)
806                 return false;
807
808         FREE(tempthread, threadobject);
809
810         threads_init_threadobject(mainthreadobj);
811         threads_set_current_threadobject(mainthreadobj);
812         lock_init_execution_env(mainthreadobj);
813
814         mainthreadobj->next = mainthreadobj;
815         mainthreadobj->prev = mainthreadobj;
816
817         threads_table_add(mainthreadobj);
818
819         /* mark main thread as Java thread */
820
821         mainthreadobj->flags = THREAD_FLAG_JAVA;
822
823 #if defined(ENABLE_INTRP)
824         /* create interpreter stack */
825
826         if (opt_intrp) {
827                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
828                 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
829         }
830 #endif
831
832         threadname = javastring_new(utf_new_char("main"));
833
834 #if defined(ENABLE_JAVASE)
835         /* allocate and init ThreadGroup */
836
837         threadgroup = (java_lang_ThreadGroup *)
838                 native_new_and_init(class_java_lang_ThreadGroup);
839
840         if (threadgroup == NULL)
841                 return false;
842 #endif
843
844 #if defined(WITH_CLASSPATH_GNU)
845         /* create a java.lang.VMThread for the main thread */
846
847         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
848
849         if (vmt == NULL)
850                 return false;
851
852         /* set the thread */
853
854         vmt->thread = mainthreadobj->object;
855         vmt->vmdata = (java_lang_Object *) mainthreadobj;
856
857         /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
858         o = (java_objectheader *) mainthreadobj->object;
859
860         (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
861                                                   false);
862 #elif defined(WITH_CLASSPATH_CLDC1_1)
863         /* set the thread */
864
865         mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
866
867         /* call public Thread(String name) */
868
869         o = (java_objectheader *) mainthreadobj->object;
870
871         (void) vm_call_method(method_thread_init, o, threadname);
872 #endif
873
874         if (*exceptionptr)
875                 return false;
876
877 #if defined(ENABLE_JAVASE)
878         mainthreadobj->object->group = threadgroup;
879
880         /* add main thread to java.lang.ThreadGroup */
881
882         m = class_resolveclassmethod(class_java_lang_ThreadGroup,
883                                                                  utf_addThread,
884                                                                  utf_java_lang_Thread__V,
885                                                                  class_java_lang_ThreadGroup,
886                                                                  true);
887
888         o = (java_objectheader *) threadgroup;
889         t = mainthreadobj->object;
890
891         (void) vm_call_method(m, o, t);
892
893         if (*exceptionptr)
894                 return false;
895
896 #endif
897
898         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
899
900         /* initialize the thread attribute object */
901
902         if (pthread_attr_init(&threadattr)) {
903                 log_println("pthread_attr_init failed: %s", strerror(errno));
904                 return false;
905         }
906
907         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
908
909         /* everything's ok */
910
911         return true;
912 }
913
914
915 /* threads_table_init *********************************************************
916
917    Initialize the global threads table.
918
919 ******************************************************************************/
920
921 static void threads_table_init(void)
922 {
923         s4 size;
924         s4 i;
925
926         size = THREADS_INITIAL_TABLE_SIZE;
927
928         threads_table.size = size;
929         threads_table.table = MNEW(threads_table_entry_t, size);
930
931         /* link the entries in a freelist */
932
933         for (i=0; i<size; ++i) {
934                 threads_table.table[i].nextfree = i+1;
935         }
936
937         /* terminate the freelist */
938
939         threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
940 }
941
942
943 /* threads_table_add **********************************************************
944
945    Add a thread to the global threads table. The index is entered in the
946    threadobject. The thinlock value for the thread is pre-computed.
947
948    IN:
949       thread............the thread to add
950
951    RETURN VALUE:
952       The table index for the newly added thread. This value has also been
953           entered in the threadobject.
954
955    PRE-CONDITION:
956       The caller must hold the threadlistlock!
957
958 ******************************************************************************/
959
960 static s4 threads_table_add(threadobject *thread)
961 {
962         s4 index;
963         s4 oldsize;
964         s4 newsize;
965         s4 i;
966
967         /* table[0] serves as the head of the freelist */
968
969         index = threads_table.table[0].nextfree;
970
971         /* if we got a free index, use it */
972
973         if (index) {
974 got_an_index:
975                 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
976                 threads_table.table[index].thread = thread;
977                 thread->index = index;
978                 thread->thinlock = lock_pre_compute_thinlock(index);
979                 return index;
980         }
981
982         /* we must grow the table */
983
984         oldsize = threads_table.size;
985         newsize = oldsize * 2;
986
987         threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
988                                                                    oldsize, newsize);
989         threads_table.size = newsize;
990
991         /* link the new entries to a free list */
992
993         for (i=oldsize; i<newsize; ++i) {
994                 threads_table.table[i].nextfree = i+1;
995         }
996
997         /* terminate the freelist */
998
999         threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
1000
1001         /* use the first of the new entries */
1002
1003         index = oldsize;
1004         goto got_an_index;
1005 }
1006
1007
1008 /* threads_table_remove *******************************************************
1009
1010    Remove a thread from the global threads table.
1011
1012    IN:
1013       thread............the thread to remove
1014
1015    PRE-CONDITION:
1016       The caller must hold the threadlistlock!
1017
1018 ******************************************************************************/
1019
1020 static void threads_table_remove(threadobject *thread)
1021 {
1022         s4 index;
1023
1024         index = thread->index;
1025
1026         /* put the index into the freelist */
1027
1028         threads_table.table[index] = threads_table.table[0];
1029         threads_table.table[0].nextfree = index;
1030
1031         /* delete the index in the threadobject to discover bugs */
1032 #if !defined(NDEBUG)
1033         thread->index = 0;
1034 #endif
1035 }
1036
1037
1038 /* threads_startup_thread ******************************************************
1039
1040    Thread startup function called by pthread_create.
1041
1042    Thread which have a startup.function != NULL are marked as internal
1043    threads. All other threads are threated as normal Java threads.
1044
1045    NOTE: This function is not called directly by pthread_create. The Boehm GC
1046          inserts its own GC_start_routine in between, which then calls
1047                  threads_startup.
1048
1049    IN:
1050       t............the argument passed to pthread_create, ie. a pointer to
1051                        a startupinfo struct. CAUTION: When the `psem` semaphore
1052                                    is posted, the startupinfo struct becomes invalid! (It
1053                                    is allocated on the stack of threads_start_thread.)
1054
1055 ******************************************************************************/
1056
1057 static void *threads_startup_thread(void *t)
1058 {
1059         startupinfo        *startup;
1060         threadobject       *thread;
1061 #if defined(WITH_CLASSPATH_GNU)
1062         java_lang_VMThread *vmt;
1063 #endif
1064         sem_t              *psem;
1065         threadobject       *tnext;
1066         classinfo          *c;
1067         methodinfo         *m;
1068         java_objectheader  *o;
1069         functionptr         function;
1070
1071 #if defined(ENABLE_INTRP)
1072         u1 *intrp_thread_stack;
1073
1074         /* create interpreter stack */
1075
1076         if (opt_intrp) {
1077                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1078                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1079         }
1080         else
1081                 intrp_thread_stack = NULL;
1082 #endif
1083
1084         /* get passed startupinfo structure and the values in there */
1085
1086         startup = t;
1087         t = NULL; /* make sure it's not used wrongly */
1088
1089         thread   = startup->thread;
1090         function = startup->function;
1091         psem     = startup->psem;
1092
1093         /* Seems like we've encountered a situation where thread->tid was not set by
1094          * pthread_create. We alleviate this problem by waiting for pthread_create
1095          * to return. */
1096         threads_sem_wait(startup->psem_first);
1097
1098         /* set the thread object */
1099
1100 #if defined(__DARWIN__)
1101         thread->mach_thread = mach_thread_self();
1102 #endif
1103
1104         threads_init_threadobject(thread);
1105         threads_set_current_threadobject(thread);
1106
1107         /* insert the thread into the threadlist and the threads table */
1108
1109         pthread_mutex_lock(&threadlistlock);
1110
1111         thread->prev = mainthreadobj;
1112         thread->next = tnext = mainthreadobj->next;
1113         mainthreadobj->next = thread;
1114         tnext->prev = thread;
1115
1116         threads_table_add(thread);
1117
1118         pthread_mutex_unlock(&threadlistlock);
1119
1120         /* init data structures of this thread */
1121
1122         lock_init_execution_env(thread);
1123
1124         /* tell threads_startup_thread that we registered ourselves */
1125         /* CAUTION: *startup becomes invalid with this!             */
1126
1127         startup = NULL;
1128         threads_sem_post(psem);
1129
1130         /* set our priority */
1131
1132         threads_set_thread_priority(thread->tid, thread->object->priority);
1133
1134 #if defined(ENABLE_INTRP)
1135         /* set interpreter stack */
1136
1137         if (opt_intrp)
1138                 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1139 #endif
1140
1141 #if defined(ENABLE_JVMTI)
1142         /* fire thread start event */
1143
1144         if (jvmti) 
1145                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1146 #endif
1147
1148         /* find and run the Thread.run()V method if no other function was passed */
1149
1150         if (function == NULL) {
1151                 /* this is a normal Java thread */
1152
1153                 thread->flags |= THREAD_FLAG_JAVA;
1154
1155 #if defined(WITH_CLASSPATH_GNU)
1156                 /* We need to start the run method of
1157                    java.lang.VMThread. Since this is a final class, we can use
1158                    the class object directly. */
1159
1160                 c   = class_java_lang_VMThread;
1161 #elif defined(WITH_CLASSPATH_CLDC1_1)
1162                 c   = thread->object->header.vftbl->class;
1163 #endif
1164
1165                 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1166
1167                 if (m == NULL)
1168                         vm_abort("threads_startup_thread: run() method not found in class");
1169
1170                 /* set ThreadMXBean variables */
1171
1172                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1173                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1174
1175                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1176                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1177                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1178                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1179
1180 #if defined(WITH_CLASSPATH_GNU)
1181                 /* we need to start the run method of java.lang.VMThread */
1182
1183                 vmt = (java_lang_VMThread *) thread->object->vmThread;
1184                 o   = (java_objectheader *) vmt;
1185
1186 #elif defined(WITH_CLASSPATH_CLDC1_1)
1187                 o   = (java_objectheader *) thread->object;
1188 #endif
1189
1190                 (void) vm_call_method(m, o);
1191         }
1192         else {
1193                 /* this is an internal thread */
1194
1195                 thread->flags |= THREAD_FLAG_INTERNAL;
1196
1197                 /* set ThreadMXBean variables */
1198
1199                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1200                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1201
1202                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1203                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1204                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1205                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1206
1207                 /* call passed function, e.g. finalizer_thread */
1208
1209                 (function)();
1210         }
1211
1212 #if defined(ENABLE_JVMTI)
1213         /* fire thread end event */
1214
1215         if (jvmti)
1216                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1217 #endif
1218
1219         threads_detach_thread(thread);
1220
1221         /* set ThreadMXBean variables */
1222
1223         _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1224
1225         return NULL;
1226 }
1227
1228
1229 /* threads_start_javathread ***************************************************
1230
1231    Start a thread in the JVM. Only the java thread object exists so far.
1232
1233    IN:
1234       object.....the java thread object java.lang.Thread
1235
1236 ******************************************************************************/
1237
1238 void threads_start_javathread(java_lang_Thread *object)
1239 {
1240         threadobject *thread;
1241
1242         /* create the vm internal threadobject */
1243
1244         thread = NEW(threadobject);
1245
1246 #if defined(ENABLE_STATISTICS)
1247         if (opt_stat)
1248                 size_threadobject += sizeof(threadobject);
1249 #endif
1250
1251         /* link the two objects together */
1252
1253         thread->object = object;
1254
1255 #if defined(WITH_CLASSPATH_GNU)
1256         assert(object->vmThread);
1257         assert(object->vmThread->vmdata == NULL);
1258         object->vmThread->vmdata = (java_lang_Object *) thread;
1259 #elif defined(WITH_CLASSPATH_CLDC1_1)
1260         object->vm_thread = (java_lang_Object *) thread;
1261 #endif
1262
1263         /* actually start the thread */
1264         /* don't pass a function pointer (NULL) since we want Thread.run()V here */
1265
1266         threads_start_thread(thread, NULL);
1267 }
1268
1269
1270 /* threads_start_thread ********************************************************
1271
1272    Start a thread in the JVM. Both (vm internal and java) thread objects exist.
1273
1274    IN:
1275       thread.......the thread object
1276           function.....function to run in the new thread. NULL means that the
1277                        "run" method of the object `t` should be called
1278
1279 ******************************************************************************/
1280
1281 void threads_start_thread(threadobject *thread, functionptr function)
1282 {
1283         sem_t          sem;
1284         sem_t          sem_first;
1285         pthread_attr_t attr;
1286         startupinfo    startup;
1287
1288         /* fill startupinfo structure passed by pthread_create to
1289          * threads_startup_thread */
1290
1291         startup.thread     = thread;
1292         startup.function   = function;       /* maybe we don't call Thread.run()V */
1293         startup.psem       = &sem;
1294         startup.psem_first = &sem_first;
1295
1296         threads_sem_init(&sem, 0, 0);
1297         threads_sem_init(&sem_first, 0, 0);
1298
1299         /* initialize thread attribute object */
1300
1301         if (pthread_attr_init(&attr))
1302                 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1303
1304         /* initialize thread stacksize */
1305
1306         if (pthread_attr_setstacksize(&attr, opt_stacksize))
1307                 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1308
1309         /* create the thread */
1310
1311         if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1312                 vm_abort("pthread_create failed: %s", strerror(errno));
1313
1314         /* signal that pthread_create has returned, so thread->tid is valid */
1315
1316         threads_sem_post(&sem_first);
1317
1318         /* wait here until the thread has entered itself into the thread list */
1319
1320         threads_sem_wait(&sem);
1321
1322         /* cleanup */
1323
1324         sem_destroy(&sem);
1325         sem_destroy(&sem_first);
1326 }
1327
1328
1329 /* threads_set_thread_priority *************************************************
1330
1331    Set the priority of the given thread.
1332
1333    IN:
1334       tid..........thread id
1335           priority.....priority to set
1336
1337 ******************************************************************************/
1338
1339 void threads_set_thread_priority(pthread_t tid, int priority)
1340 {
1341         struct sched_param schedp;
1342         int policy;
1343
1344         pthread_getschedparam(tid, &policy, &schedp);
1345         schedp.sched_priority = priority;
1346         pthread_setschedparam(tid, policy, &schedp);
1347 }
1348
1349
1350 /* threads_attach_current_thread ***********************************************
1351
1352    Attaches the current thread to the VM.  Used in JNI.
1353
1354 *******************************************************************************/
1355
1356 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1357 {
1358         threadobject          *thread;
1359         utf                   *u;
1360         java_lang_String      *s;
1361         java_objectheader     *o;
1362         java_lang_Thread      *t;
1363
1364 #if defined(ENABLE_JAVASE)
1365         java_lang_ThreadGroup *group;
1366         methodinfo            *m;
1367 #endif
1368
1369 #if defined(WITH_CLASSPATH_GNU)
1370         java_lang_VMThread    *vmt;
1371 #endif
1372
1373         /* create a vm internal thread object */
1374
1375         thread = NEW(threadobject);
1376
1377 #if defined(ENABLE_STATISTICS)
1378         if (opt_stat)
1379                 size_threadobject += sizeof(threadobject);
1380 #endif
1381
1382         if (thread == NULL)
1383                 return false;
1384
1385         /* create a java.lang.Thread object */
1386
1387         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1388
1389         if (t == NULL)
1390                 return false;
1391
1392         thread->object = t;
1393
1394         threads_init_threadobject(thread);
1395         threads_set_current_threadobject(thread);
1396         lock_init_execution_env(thread);
1397
1398         /* insert the thread into the threadlist and the threads table */
1399
1400         pthread_mutex_lock(&threadlistlock);
1401
1402         thread->prev        = mainthreadobj;
1403         thread->next        = mainthreadobj->next;
1404         mainthreadobj->next = thread;
1405         thread->next->prev  = thread;
1406
1407         threads_table_add(thread);
1408
1409         pthread_mutex_unlock(&threadlistlock);
1410
1411         /* mark thread as Java thread */
1412
1413         thread->flags = THREAD_FLAG_JAVA;
1414
1415         if (isdaemon)
1416                 thread->flags |= THREAD_FLAG_DAEMON;
1417
1418 #if defined(ENABLE_INTRP)
1419         /* create interpreter stack */
1420
1421         if (opt_intrp) {
1422                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1423                 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1424         }
1425 #endif
1426
1427 #if defined(WITH_CLASSPATH_GNU)
1428         /* create a java.lang.VMThread object */
1429
1430         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1431
1432         if (vmt == NULL)
1433                 return false;
1434
1435         /* set the thread */
1436
1437         vmt->thread = t;
1438         vmt->vmdata = (java_lang_Object *) thread;
1439 #elif defined(WITH_CLASSPATH_CLDC1_1)
1440         t->vm_thread = (java_lang_Object *) thread;
1441 #endif
1442
1443         if (vm_aargs != NULL) {
1444                 u     = utf_new_char(vm_aargs->name);
1445 #if defined(ENABLE_JAVASE)
1446                 group = (java_lang_ThreadGroup *) vm_aargs->group;
1447 #endif
1448         }
1449         else {
1450                 u     = utf_null;
1451 #if defined(ENABLE_JAVASE)
1452                 group = mainthreadobj->object->group;
1453 #endif
1454         }
1455
1456         s = javastring_new(u);
1457
1458         o = (java_objectheader *) thread->object;
1459
1460 #if defined(WITH_CLASSPATH_GNU)
1461         (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1462                                                   isdaemon);
1463 #elif defined(WITH_CLASSPATH_CLDC1_1)
1464         (void) vm_call_method(method_thread_init, o, s);
1465 #endif
1466
1467         if (*exceptionptr)
1468                 return false;
1469
1470 #if defined(ENABLE_JAVASE)
1471         /* store the thread group in the object */
1472
1473         thread->object->group = group;
1474
1475         /* add thread to given thread-group */
1476
1477         m = class_resolveclassmethod(group->header.vftbl->class,
1478                                                                  utf_addThread,
1479                                                                  utf_java_lang_Thread__V,
1480                                                                  class_java_lang_ThreadGroup,
1481                                                                  true);
1482
1483         o = (java_objectheader *) group;
1484
1485         (void) vm_call_method(m, o, t);
1486
1487         if (*exceptionptr)
1488                 return false;
1489 #endif
1490
1491         return true;
1492 }
1493
1494
1495 /* threads_detach_thread *******************************************************
1496
1497    Detaches the passed thread from the VM.  Used in JNI.
1498
1499 *******************************************************************************/
1500
1501 bool threads_detach_thread(threadobject *thread)
1502 {
1503 #if defined(ENABLE_JAVASE)
1504         java_lang_ThreadGroup *group;
1505         methodinfo            *m;
1506         java_objectheader     *o;
1507         java_lang_Thread      *t;
1508 #endif
1509
1510         /* Allow lock record pools to be used by other threads. They
1511            cannot be deleted so we'd better not waste them. */
1512
1513         /* XXX We have to find a new way to free lock records */
1514         /*     with the new locking algorithm.                */
1515         /* lock_record_free_pools(thread->ee.lockrecordpools); */
1516
1517         /* XXX implement uncaught exception stuff (like JamVM does) */
1518
1519 #if defined(ENABLE_JAVASE)
1520         /* remove thread from the thread group */
1521
1522         group = thread->object->group;
1523
1524         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1525
1526         if (group != NULL) {
1527                 m = class_resolveclassmethod(group->header.vftbl->class,
1528                                                                          utf_removeThread,
1529                                                                          utf_java_lang_Thread__V,
1530                                                                          class_java_lang_ThreadGroup,
1531                                                                          true);
1532
1533                 if (m == NULL)
1534                         return false;
1535
1536                 o = (java_objectheader *) group;
1537                 t = thread->object;
1538
1539                 (void) vm_call_method(m, o, t);
1540
1541                 if (*exceptionptr)
1542                         return false;
1543         }
1544 #endif
1545
1546         /* remove thread from thread list and threads table, do this
1547            inside a lock */
1548
1549         pthread_mutex_lock(&threadlistlock);
1550
1551         thread->next->prev = thread->prev;
1552         thread->prev->next = thread->next;
1553
1554         threads_table_remove(thread);
1555
1556         pthread_mutex_unlock(&threadlistlock);
1557
1558         /* reset thread id (lock on joinmutex? TWISTI) */
1559
1560         pthread_mutex_lock(&(thread->joinmutex));
1561         thread->tid = 0;
1562         pthread_mutex_unlock(&(thread->joinmutex));
1563
1564         /* tell everyone that a thread has finished */
1565
1566         pthread_cond_broadcast(&(thread->joincond));
1567
1568         /* free the vm internal thread object */
1569
1570         FREE(thread, threadobject);
1571
1572 #if defined(ENABLE_STATISTICS)
1573         if (opt_stat)
1574                 size_threadobject -= sizeof(threadobject);
1575 #endif
1576
1577         return true;
1578 }
1579
1580
1581 /* threads_suspend_thread ******************************************************
1582
1583    Suspend the passed thread. Execution stops until the thread
1584    is explicitly resumend again.
1585
1586    IN:
1587      reason.....Reason for suspending this thread.
1588
1589 *******************************************************************************/
1590
1591 bool threads_suspend_thread(threadobject *thread, s4 reason)
1592 {
1593         /* acquire the suspendmutex */
1594         pthread_mutex_lock(&(thread->suspendmutex));
1595
1596         if (thread->suspended) {
1597                 pthread_mutex_unlock(&(thread->suspendmutex));
1598                 return false;
1599         }
1600
1601         /* set the reason for the suspension */
1602         thread->suspend_reason = reason;
1603
1604         /* send the suspend signal to the thread */
1605         assert(thread != THREADOBJECT);
1606         pthread_kill(thread->tid, SIGUSR1);
1607
1608         /* REMEMBER: do not release the suspendmutex, this is done
1609            by the thread itself in threads_suspend_ack().  */
1610
1611         return true;
1612 }
1613
1614
1615 /* threads_suspend_ack *********************************************************
1616
1617    Acknowledges the suspension of the current thread.
1618
1619    IN:
1620      pc.....The PC where the thread suspended its execution.
1621      sp.....The SP before the thread suspended its execution.
1622
1623 *******************************************************************************/
1624
1625 void threads_suspend_ack(u1* pc, u1* sp)
1626 {
1627         threadobject *thread;
1628
1629         thread = THREADOBJECT;
1630
1631         assert(thread->suspend_reason != 0);
1632
1633         /* TODO: remember dump memory size */
1634
1635 #if defined(ENABLE_GC_CACAO)
1636         /* inform the GC about the suspension */
1637         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1638
1639                 /* check if the GC wants to leave the thread running */
1640                 if (!gc_suspend(thread, pc, sp)) {
1641
1642                         /* REMEMBER: we do not unlock the suspendmutex because the thread
1643                            will suspend itself again at a later time */
1644                         return;
1645
1646                 }
1647         }
1648 #endif
1649
1650         /* mark this thread as suspended and remember the PC */
1651         thread->pc        = pc;
1652         thread->suspended = true;
1653
1654         /* if we are stopping the world, we should send a global ack */
1655         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1656                 threads_sem_post(&suspend_ack);
1657         }
1658
1659         /* release the suspension mutex and wait till we are resumed */
1660         pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1661
1662         /* TODO: free dump memory */
1663
1664         /* release the suspendmutex */
1665         pthread_mutex_unlock(&(thread->suspendmutex));
1666 }
1667
1668
1669 /* threads_resume_thread *******************************************************
1670
1671    Resumes the execution of the passed thread.
1672
1673 *******************************************************************************/
1674
1675 bool threads_resume_thread(threadobject *thread)
1676 {
1677         /* acquire the suspendmutex */
1678         pthread_mutex_lock(&(thread->suspendmutex));
1679
1680         if (!thread->suspended) {
1681                 pthread_mutex_unlock(&(thread->suspendmutex));
1682                 return false;
1683         }
1684
1685         thread->suspended = false;
1686
1687         /* tell everyone that the thread should resume */
1688         assert(thread != THREADOBJECT);
1689         pthread_cond_broadcast(&(thread->suspendcond));
1690
1691         /* release the suspendmutex */
1692         pthread_mutex_unlock(&(thread->suspendmutex));
1693
1694         return true;
1695 }
1696
1697 /* threads_find_non_daemon_thread **********************************************
1698
1699    Helper function used by threads_join_all_threads for finding
1700    non-daemon threads that are still running.
1701
1702 *******************************************************************************/
1703
1704 /* At the end of the program, we wait for all running non-daemon
1705    threads to die. */
1706
1707 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1708 {
1709         while (thread != mainthreadobj) {
1710                 if (!(thread->flags & THREAD_FLAG_DAEMON))
1711                         return thread;
1712
1713                 thread = thread->prev;
1714         }
1715
1716         return NULL;
1717 }
1718
1719
1720 /* threads_join_all_threads ****************************************************
1721
1722    Join all non-daemon threads.
1723
1724 *******************************************************************************/
1725
1726 void threads_join_all_threads(void)
1727 {
1728         threadobject *thread;
1729
1730         pthread_mutex_lock(&threadlistlock);
1731
1732         while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1733                 pthread_mutex_lock(&(thread->joinmutex));
1734
1735                 pthread_mutex_unlock(&threadlistlock);
1736
1737                 while (thread->tid)
1738                         pthread_cond_wait(&(thread->joincond), &(thread->joinmutex));
1739
1740                 pthread_mutex_unlock(&(thread->joinmutex));
1741
1742                 pthread_mutex_lock(&threadlistlock);
1743         }
1744
1745         pthread_mutex_unlock(&threadlistlock);
1746 }
1747
1748
1749 /* threads_timespec_earlier ****************************************************
1750
1751    Return true if timespec tv1 is earlier than timespec tv2.
1752
1753    IN:
1754       tv1..........first timespec
1755           tv2..........second timespec
1756
1757    RETURN VALUE:
1758       true, if the first timespec is earlier
1759
1760 *******************************************************************************/
1761
1762 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1763                                                                                         const struct timespec *tv2)
1764 {
1765         return (tv1->tv_sec < tv2->tv_sec)
1766                                 ||
1767                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1768 }
1769
1770
1771 /* threads_current_time_is_earlier_than ****************************************
1772
1773    Check if the current time is earlier than the given timespec.
1774
1775    IN:
1776       tv...........the timespec to compare against
1777
1778    RETURN VALUE:
1779       true, if the current time is earlier
1780
1781 *******************************************************************************/
1782
1783 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1784 {
1785         struct timeval tvnow;
1786         struct timespec tsnow;
1787
1788         /* get current time */
1789
1790         if (gettimeofday(&tvnow, NULL) != 0)
1791                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1792
1793         /* convert it to a timespec */
1794
1795         tsnow.tv_sec = tvnow.tv_sec;
1796         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1797
1798         /* compare current time with the given timespec */
1799
1800         return threads_timespec_earlier(&tsnow, tv);
1801 }
1802
1803
1804 /* threads_wait_with_timeout ***************************************************
1805
1806    Wait until the given point in time on a monitor until either
1807    we are notified, we are interrupted, or the time is up.
1808
1809    IN:
1810       t............the current thread
1811           wakeupTime...absolute (latest) wakeup time
1812                            If both tv_sec and tv_nsec are zero, this function
1813                                            waits for an unlimited amount of time.
1814
1815    RETURN VALUE:
1816       true.........if the wait has been interrupted,
1817           false........if the wait was ended by notification or timeout
1818
1819 *******************************************************************************/
1820
1821 static bool threads_wait_with_timeout(threadobject *thread,
1822                                                                           struct timespec *wakeupTime)
1823 {
1824         bool wasinterrupted;
1825
1826         /* acquire the waitmutex */
1827
1828         pthread_mutex_lock(&thread->waitmutex);
1829
1830         /* mark us as sleeping */
1831
1832         thread->sleeping = true;
1833
1834         /* wait on waitcond */
1835
1836         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1837                 /* with timeout */
1838                 while (!thread->interrupted && !thread->signaled
1839                            && threads_current_time_is_earlier_than(wakeupTime))
1840                 {
1841                         pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1842                                                                    wakeupTime);
1843                 }
1844         }
1845         else {
1846                 /* no timeout */
1847                 while (!thread->interrupted && !thread->signaled)
1848                         pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1849         }
1850
1851         /* check if we were interrupted */
1852
1853         wasinterrupted = thread->interrupted;
1854
1855         /* reset all flags */
1856
1857         thread->interrupted = false;
1858         thread->signaled    = false;
1859         thread->sleeping    = false;
1860
1861         /* release the waitmutex */
1862
1863         pthread_mutex_unlock(&thread->waitmutex);
1864
1865         return wasinterrupted;
1866 }
1867
1868
1869 /* threads_wait_with_timeout_relative ******************************************
1870
1871    Wait for the given maximum amount of time on a monitor until either
1872    we are notified, we are interrupted, or the time is up.
1873
1874    IN:
1875       t............the current thread
1876           millis.......milliseconds to wait
1877           nanos........nanoseconds to wait
1878
1879    RETURN VALUE:
1880       true.........if the wait has been interrupted,
1881           false........if the wait was ended by notification or timeout
1882
1883 *******************************************************************************/
1884
1885 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1886                                                                                 s4 nanos)
1887 {
1888         struct timespec wakeupTime;
1889
1890         /* calculate the the (latest) wakeup time */
1891
1892         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1893
1894         /* wait */
1895
1896         return threads_wait_with_timeout(thread, &wakeupTime);
1897 }
1898
1899
1900 /* threads_calc_absolute_time **************************************************
1901
1902    Calculate the absolute point in time a given number of ms and ns from now.
1903
1904    IN:
1905       millis............milliseconds from now
1906           nanos.............nanoseconds from now
1907
1908    OUT:
1909       *tm...............receives the timespec of the absolute point in time
1910
1911 *******************************************************************************/
1912
1913 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1914 {
1915         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1916                 struct timeval tv;
1917                 long nsec;
1918                 gettimeofday(&tv, NULL);
1919                 tv.tv_sec += millis / 1000;
1920                 millis %= 1000;
1921                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1922                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1923                 tm->tv_nsec = nsec % 1000000000;
1924         }
1925         else {
1926                 tm->tv_sec = 0;
1927                 tm->tv_nsec = 0;
1928         }
1929 }
1930
1931
1932 /* threads_thread_interrupt ****************************************************
1933
1934    Interrupt the given thread.
1935
1936    The thread gets the "waitcond" signal and 
1937    its interrupted flag is set to true.
1938
1939    IN:
1940       thread............the thread to interrupt
1941
1942 *******************************************************************************/
1943
1944 void threads_thread_interrupt(threadobject *thread)
1945 {
1946         /* Signal the thread a "waitcond" and tell it that it has been
1947            interrupted. */
1948
1949         pthread_mutex_lock(&thread->waitmutex);
1950
1951         /* Interrupt blocking system call using a signal. */
1952
1953         pthread_kill(thread->tid, SIGHUP);
1954
1955         if (thread->sleeping)
1956                 pthread_cond_signal(&thread->waitcond);
1957
1958         thread->interrupted = true;
1959
1960         pthread_mutex_unlock(&thread->waitmutex);
1961 }
1962
1963
1964 /* threads_check_if_interrupted_and_reset **************************************
1965
1966    Check if the current thread has been interrupted and reset the
1967    interruption flag.
1968
1969    RETURN VALUE:
1970       true, if the current thread had been interrupted
1971
1972 *******************************************************************************/
1973
1974 bool threads_check_if_interrupted_and_reset(void)
1975 {
1976         threadobject *thread;
1977         bool intr;
1978
1979         thread = THREADOBJECT;
1980
1981         /* get interrupted flag */
1982
1983         intr = thread->interrupted;
1984
1985         /* reset interrupted flag */
1986
1987         thread->interrupted = false;
1988
1989         return intr;
1990 }
1991
1992
1993 /* threads_thread_has_been_interrupted *****************************************
1994
1995    Check if the given thread has been interrupted
1996
1997    IN:
1998       t............the thread to check
1999
2000    RETURN VALUE:
2001       true, if the given thread had been interrupted
2002
2003 *******************************************************************************/
2004
2005 bool threads_thread_has_been_interrupted(threadobject *thread)
2006 {
2007         return thread->interrupted;
2008 }
2009
2010
2011 /* threads_sleep ***************************************************************
2012
2013    Sleep the current thread for the specified amount of time.
2014
2015 *******************************************************************************/
2016
2017 void threads_sleep(s8 millis, s4 nanos)
2018 {
2019         threadobject    *thread;
2020         struct timespec  wakeupTime;
2021         bool             wasinterrupted;
2022
2023         thread = THREADOBJECT;
2024
2025         threads_calc_absolute_time(&wakeupTime, millis, nanos);
2026
2027         wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
2028
2029         if (wasinterrupted)
2030                 exceptions_throw_interruptedexception();
2031 }
2032
2033
2034 /* threads_yield ***************************************************************
2035
2036    Yield to the scheduler.
2037
2038 *******************************************************************************/
2039
2040 void threads_yield(void)
2041 {
2042         sched_yield();
2043 }
2044
2045
2046 /* threads_table_dump *********************************************************
2047
2048    Dump the threads table for debugging purposes.
2049
2050    IN:
2051       file..............stream to write to
2052
2053 ******************************************************************************/
2054
2055 #if !defined(NDEBUG) && 0
2056 static void threads_table_dump(FILE *file)
2057 {
2058         s4 i;
2059         s4 size;
2060         ptrint index;
2061
2062         pthread_mutex_lock(&threadlistlock);
2063
2064         size = threads_table.size;
2065
2066         fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
2067
2068         for (i=0; i<size; ++i) {
2069                 index = threads_table.table[i].nextfree;
2070
2071                 fprintf(file, "%4d: ", i);
2072
2073                 if (index < size) {
2074                         fprintf(file, "free, nextfree = %d\n", (int) index);
2075                 }
2076                 else {
2077                         fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
2078                 }
2079         }
2080
2081         fprintf(file, "======== END OF THREADS TABLE ========\n");
2082
2083         pthread_mutex_unlock(&threadlistlock);
2084 }
2085 #endif
2086
2087 /*
2088  * These are local overrides for various environment variables in Emacs.
2089  * Please do not remove this and leave it at the end of the file, where
2090  * Emacs will automagically detect them.
2091  * ---------------------------------------------------------------------
2092  * Local variables:
2093  * mode: c
2094  * indent-tabs-mode: t
2095  * c-basic-offset: 4
2096  * tab-width: 4
2097  * End:
2098  * vim:noexpandtab:sw=4:ts=4:
2099  */