e5f4ceb052fe1960885b021abdac65a94866b81e
[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 7674 2007-04-05 13:27:11Z 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         /* thread is running */
815
816         mainthreadobj->state = THREAD_STATE_RUNNABLE;
817
818         mainthreadobj->next = mainthreadobj;
819         mainthreadobj->prev = mainthreadobj;
820
821         threads_table_add(mainthreadobj);
822
823         /* mark main thread as Java thread */
824
825         mainthreadobj->flags = THREAD_FLAG_JAVA;
826
827 #if defined(ENABLE_INTRP)
828         /* create interpreter stack */
829
830         if (opt_intrp) {
831                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
832                 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
833         }
834 #endif
835
836         threadname = javastring_new(utf_new_char("main"));
837
838 #if defined(ENABLE_JAVASE)
839         /* allocate and init ThreadGroup */
840
841         threadgroup = (java_lang_ThreadGroup *)
842                 native_new_and_init(class_java_lang_ThreadGroup);
843
844         if (threadgroup == NULL)
845                 return false;
846 #endif
847
848 #if defined(WITH_CLASSPATH_GNU)
849         /* create a java.lang.VMThread for the main thread */
850
851         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
852
853         if (vmt == NULL)
854                 return false;
855
856         /* set the thread */
857
858         vmt->thread = mainthreadobj->object;
859         vmt->vmdata = (java_lang_Object *) mainthreadobj;
860
861         /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
862         o = (java_objectheader *) mainthreadobj->object;
863
864         (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
865                                                   false);
866 #elif defined(WITH_CLASSPATH_CLDC1_1)
867         /* set the thread */
868
869         mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
870
871         /* call public Thread(String name) */
872
873         o = (java_objectheader *) mainthreadobj->object;
874
875         (void) vm_call_method(method_thread_init, o, threadname);
876 #endif
877
878         if (*exceptionptr)
879                 return false;
880
881 #if defined(ENABLE_JAVASE)
882         mainthreadobj->object->group = threadgroup;
883
884         /* add main thread to java.lang.ThreadGroup */
885
886         m = class_resolveclassmethod(class_java_lang_ThreadGroup,
887                                                                  utf_addThread,
888                                                                  utf_java_lang_Thread__V,
889                                                                  class_java_lang_ThreadGroup,
890                                                                  true);
891
892         o = (java_objectheader *) threadgroup;
893         t = mainthreadobj->object;
894
895         (void) vm_call_method(m, o, t);
896
897         if (*exceptionptr)
898                 return false;
899
900 #endif
901
902         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
903
904         /* initialize the thread attribute object */
905
906         if (pthread_attr_init(&threadattr)) {
907                 log_println("pthread_attr_init failed: %s", strerror(errno));
908                 return false;
909         }
910
911         pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
912
913         /* everything's ok */
914
915         return true;
916 }
917
918
919 /* threads_table_init *********************************************************
920
921    Initialize the global threads table.
922
923 ******************************************************************************/
924
925 static void threads_table_init(void)
926 {
927         s4 size;
928         s4 i;
929
930         size = THREADS_INITIAL_TABLE_SIZE;
931
932         threads_table.size = size;
933         threads_table.table = MNEW(threads_table_entry_t, size);
934
935         /* link the entries in a freelist */
936
937         for (i=0; i<size; ++i) {
938                 threads_table.table[i].nextfree = i+1;
939         }
940
941         /* terminate the freelist */
942
943         threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
944 }
945
946
947 /* threads_table_add **********************************************************
948
949    Add a thread to the global threads table. The index is entered in the
950    threadobject. The thinlock value for the thread is pre-computed.
951
952    IN:
953       thread............the thread to add
954
955    RETURN VALUE:
956       The table index for the newly added thread. This value has also been
957           entered in the threadobject.
958
959    PRE-CONDITION:
960       The caller must hold the threadlistlock!
961
962 ******************************************************************************/
963
964 static s4 threads_table_add(threadobject *thread)
965 {
966         s4 index;
967         s4 oldsize;
968         s4 newsize;
969         s4 i;
970
971         /* table[0] serves as the head of the freelist */
972
973         index = threads_table.table[0].nextfree;
974
975         /* if we got a free index, use it */
976
977         if (index) {
978 got_an_index:
979                 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
980                 threads_table.table[index].thread = thread;
981                 thread->index = index;
982                 thread->thinlock = lock_pre_compute_thinlock(index);
983                 return index;
984         }
985
986         /* we must grow the table */
987
988         oldsize = threads_table.size;
989         newsize = oldsize * 2;
990
991         threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
992                                                                    oldsize, newsize);
993         threads_table.size = newsize;
994
995         /* link the new entries to a free list */
996
997         for (i=oldsize; i<newsize; ++i) {
998                 threads_table.table[i].nextfree = i+1;
999         }
1000
1001         /* terminate the freelist */
1002
1003         threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
1004
1005         /* use the first of the new entries */
1006
1007         index = oldsize;
1008         goto got_an_index;
1009 }
1010
1011
1012 /* threads_table_remove *******************************************************
1013
1014    Remove a thread from the global threads table.
1015
1016    IN:
1017       thread............the thread to remove
1018
1019    PRE-CONDITION:
1020       The caller must hold the threadlistlock!
1021
1022 ******************************************************************************/
1023
1024 static void threads_table_remove(threadobject *thread)
1025 {
1026         s4 index;
1027
1028         index = thread->index;
1029
1030         /* put the index into the freelist */
1031
1032         threads_table.table[index] = threads_table.table[0];
1033         threads_table.table[0].nextfree = index;
1034
1035         /* delete the index in the threadobject to discover bugs */
1036 #if !defined(NDEBUG)
1037         thread->index = 0;
1038 #endif
1039 }
1040
1041
1042 /* threads_startup_thread ******************************************************
1043
1044    Thread startup function called by pthread_create.
1045
1046    Thread which have a startup.function != NULL are marked as internal
1047    threads. All other threads are threated as normal Java threads.
1048
1049    NOTE: This function is not called directly by pthread_create. The Boehm GC
1050          inserts its own GC_start_routine in between, which then calls
1051                  threads_startup.
1052
1053    IN:
1054       t............the argument passed to pthread_create, ie. a pointer to
1055                        a startupinfo struct. CAUTION: When the `psem` semaphore
1056                                    is posted, the startupinfo struct becomes invalid! (It
1057                                    is allocated on the stack of threads_start_thread.)
1058
1059 ******************************************************************************/
1060
1061 static void *threads_startup_thread(void *t)
1062 {
1063         startupinfo        *startup;
1064         threadobject       *thread;
1065 #if defined(WITH_CLASSPATH_GNU)
1066         java_lang_VMThread *vmt;
1067 #endif
1068         sem_t              *psem;
1069         threadobject       *tnext;
1070         classinfo          *c;
1071         methodinfo         *m;
1072         java_objectheader  *o;
1073         functionptr         function;
1074
1075 #if defined(ENABLE_INTRP)
1076         u1 *intrp_thread_stack;
1077
1078         /* create interpreter stack */
1079
1080         if (opt_intrp) {
1081                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1082                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1083         }
1084         else
1085                 intrp_thread_stack = NULL;
1086 #endif
1087
1088         /* get passed startupinfo structure and the values in there */
1089
1090         startup = t;
1091         t = NULL; /* make sure it's not used wrongly */
1092
1093         thread   = startup->thread;
1094         function = startup->function;
1095         psem     = startup->psem;
1096
1097         /* Seems like we've encountered a situation where thread->tid was not set by
1098          * pthread_create. We alleviate this problem by waiting for pthread_create
1099          * to return. */
1100         threads_sem_wait(startup->psem_first);
1101
1102         /* set the thread object */
1103
1104 #if defined(__DARWIN__)
1105         thread->mach_thread = mach_thread_self();
1106 #endif
1107
1108         threads_init_threadobject(thread);
1109         threads_set_current_threadobject(thread);
1110
1111         /* thread is running */
1112
1113         thread->state = THREAD_STATE_RUNNABLE;
1114
1115         /* insert the thread into the threadlist and the threads table */
1116
1117         pthread_mutex_lock(&threadlistlock);
1118
1119         thread->prev = mainthreadobj;
1120         thread->next = tnext = mainthreadobj->next;
1121         mainthreadobj->next = thread;
1122         tnext->prev = thread;
1123
1124         threads_table_add(thread);
1125
1126         pthread_mutex_unlock(&threadlistlock);
1127
1128         /* init data structures of this thread */
1129
1130         lock_init_execution_env(thread);
1131
1132         /* tell threads_startup_thread that we registered ourselves */
1133         /* CAUTION: *startup becomes invalid with this!             */
1134
1135         startup = NULL;
1136         threads_sem_post(psem);
1137
1138         /* set our priority */
1139
1140         threads_set_thread_priority(thread->tid, thread->object->priority);
1141
1142 #if defined(ENABLE_INTRP)
1143         /* set interpreter stack */
1144
1145         if (opt_intrp)
1146                 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1147 #endif
1148
1149 #if defined(ENABLE_JVMTI)
1150         /* fire thread start event */
1151
1152         if (jvmti) 
1153                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1154 #endif
1155
1156         /* find and run the Thread.run()V method if no other function was passed */
1157
1158         if (function == NULL) {
1159                 /* this is a normal Java thread */
1160
1161                 thread->flags |= THREAD_FLAG_JAVA;
1162
1163 #if defined(WITH_CLASSPATH_GNU)
1164                 /* We need to start the run method of
1165                    java.lang.VMThread. Since this is a final class, we can use
1166                    the class object directly. */
1167
1168                 c   = class_java_lang_VMThread;
1169 #elif defined(WITH_CLASSPATH_CLDC1_1)
1170                 c   = thread->object->header.vftbl->class;
1171 #endif
1172
1173                 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1174
1175                 if (m == NULL)
1176                         vm_abort("threads_startup_thread: run() method not found in class");
1177
1178                 /* set ThreadMXBean variables */
1179
1180                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1181                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1182
1183                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1184                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1185                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1186                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1187
1188 #if defined(WITH_CLASSPATH_GNU)
1189                 /* we need to start the run method of java.lang.VMThread */
1190
1191                 vmt = (java_lang_VMThread *) thread->object->vmThread;
1192                 o   = (java_objectheader *) vmt;
1193
1194 #elif defined(WITH_CLASSPATH_CLDC1_1)
1195                 o   = (java_objectheader *) thread->object;
1196 #endif
1197
1198                 /* run the thread */
1199
1200                 (void) vm_call_method(m, o);
1201         }
1202         else {
1203                 /* this is an internal thread */
1204
1205                 thread->flags |= THREAD_FLAG_INTERNAL;
1206
1207                 /* set ThreadMXBean variables */
1208
1209                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1210                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1211
1212                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1213                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1214                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1215                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1216
1217                 /* call passed function, e.g. finalizer_thread */
1218
1219                 (function)();
1220         }
1221
1222 #if defined(ENABLE_JVMTI)
1223         /* fire thread end event */
1224
1225         if (jvmti)
1226                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1227 #endif
1228
1229         threads_detach_thread(thread);
1230
1231         /* set ThreadMXBean variables */
1232
1233         _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1234
1235         return NULL;
1236 }
1237
1238
1239 /* threads_start_javathread ***************************************************
1240
1241    Start a thread in the JVM. Only the java thread object exists so far.
1242
1243    IN:
1244       object.....the java thread object java.lang.Thread
1245
1246 ******************************************************************************/
1247
1248 void threads_start_javathread(java_lang_Thread *object)
1249 {
1250         threadobject *thread;
1251
1252         /* create the vm internal threadobject */
1253
1254         thread = NEW(threadobject);
1255
1256 #if defined(ENABLE_STATISTICS)
1257         if (opt_stat)
1258                 size_threadobject += sizeof(threadobject);
1259 #endif
1260
1261         /* link the two objects together */
1262
1263         thread->object = object;
1264
1265 #if defined(WITH_CLASSPATH_GNU)
1266         assert(object->vmThread);
1267         assert(object->vmThread->vmdata == NULL);
1268         object->vmThread->vmdata = (java_lang_Object *) thread;
1269 #elif defined(WITH_CLASSPATH_CLDC1_1)
1270         object->vm_thread = (java_lang_Object *) thread;
1271 #endif
1272
1273         /* actually start the thread */
1274         /* don't pass a function pointer (NULL) since we want Thread.run()V here */
1275
1276         threads_start_thread(thread, NULL);
1277 }
1278
1279
1280 /* threads_start_thread ********************************************************
1281
1282    Start a thread in the JVM. Both (vm internal and java) thread objects exist.
1283
1284    IN:
1285       thread.......the thread object
1286           function.....function to run in the new thread. NULL means that the
1287                        "run" method of the object `t` should be called
1288
1289 ******************************************************************************/
1290
1291 void threads_start_thread(threadobject *thread, functionptr function)
1292 {
1293         sem_t          sem;
1294         sem_t          sem_first;
1295         pthread_attr_t attr;
1296         startupinfo    startup;
1297
1298         /* fill startupinfo structure passed by pthread_create to
1299          * threads_startup_thread */
1300
1301         startup.thread     = thread;
1302         startup.function   = function;       /* maybe we don't call Thread.run()V */
1303         startup.psem       = &sem;
1304         startup.psem_first = &sem_first;
1305
1306         threads_sem_init(&sem, 0, 0);
1307         threads_sem_init(&sem_first, 0, 0);
1308
1309         /* initialize thread attribute object */
1310
1311         if (pthread_attr_init(&attr))
1312                 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1313
1314         /* initialize thread stacksize */
1315
1316         if (pthread_attr_setstacksize(&attr, opt_stacksize))
1317                 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1318
1319         /* create the thread */
1320
1321         if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1322                 vm_abort("pthread_create failed: %s", strerror(errno));
1323
1324         /* signal that pthread_create has returned, so thread->tid is valid */
1325
1326         threads_sem_post(&sem_first);
1327
1328         /* wait here until the thread has entered itself into the thread list */
1329
1330         threads_sem_wait(&sem);
1331
1332         /* cleanup */
1333
1334         sem_destroy(&sem);
1335         sem_destroy(&sem_first);
1336 }
1337
1338
1339 /* threads_set_thread_priority *************************************************
1340
1341    Set the priority of the given thread.
1342
1343    IN:
1344       tid..........thread id
1345           priority.....priority to set
1346
1347 ******************************************************************************/
1348
1349 void threads_set_thread_priority(pthread_t tid, int priority)
1350 {
1351         struct sched_param schedp;
1352         int policy;
1353
1354         pthread_getschedparam(tid, &policy, &schedp);
1355         schedp.sched_priority = priority;
1356         pthread_setschedparam(tid, policy, &schedp);
1357 }
1358
1359
1360 /* threads_attach_current_thread ***********************************************
1361
1362    Attaches the current thread to the VM.  Used in JNI.
1363
1364 *******************************************************************************/
1365
1366 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1367 {
1368         threadobject          *thread;
1369         utf                   *u;
1370         java_lang_String      *s;
1371         java_objectheader     *o;
1372         java_lang_Thread      *t;
1373
1374 #if defined(ENABLE_JAVASE)
1375         java_lang_ThreadGroup *group;
1376         methodinfo            *m;
1377 #endif
1378
1379 #if defined(WITH_CLASSPATH_GNU)
1380         java_lang_VMThread    *vmt;
1381 #endif
1382
1383         /* create a vm internal thread object */
1384
1385         thread = NEW(threadobject);
1386
1387 #if defined(ENABLE_STATISTICS)
1388         if (opt_stat)
1389                 size_threadobject += sizeof(threadobject);
1390 #endif
1391
1392         if (thread == NULL)
1393                 return false;
1394
1395         /* create a java.lang.Thread object */
1396
1397         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1398
1399         if (t == NULL)
1400                 return false;
1401
1402         thread->object = t;
1403
1404         threads_init_threadobject(thread);
1405         threads_set_current_threadobject(thread);
1406         lock_init_execution_env(thread);
1407
1408         /* thread is running */
1409
1410         thread->state = THREAD_STATE_RUNNABLE;
1411
1412         /* insert the thread into the threadlist and the threads table */
1413
1414         pthread_mutex_lock(&threadlistlock);
1415
1416         thread->prev        = mainthreadobj;
1417         thread->next        = mainthreadobj->next;
1418         mainthreadobj->next = thread;
1419         thread->next->prev  = thread;
1420
1421         threads_table_add(thread);
1422
1423         pthread_mutex_unlock(&threadlistlock);
1424
1425         /* mark thread as Java thread */
1426
1427         thread->flags = THREAD_FLAG_JAVA;
1428
1429         if (isdaemon)
1430                 thread->flags |= THREAD_FLAG_DAEMON;
1431
1432 #if defined(ENABLE_INTRP)
1433         /* create interpreter stack */
1434
1435         if (opt_intrp) {
1436                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1437                 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1438         }
1439 #endif
1440
1441 #if defined(WITH_CLASSPATH_GNU)
1442         /* create a java.lang.VMThread object */
1443
1444         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1445
1446         if (vmt == NULL)
1447                 return false;
1448
1449         /* set the thread */
1450
1451         vmt->thread = t;
1452         vmt->vmdata = (java_lang_Object *) thread;
1453 #elif defined(WITH_CLASSPATH_CLDC1_1)
1454         t->vm_thread = (java_lang_Object *) thread;
1455 #endif
1456
1457         if (vm_aargs != NULL) {
1458                 u     = utf_new_char(vm_aargs->name);
1459 #if defined(ENABLE_JAVASE)
1460                 group = (java_lang_ThreadGroup *) vm_aargs->group;
1461 #endif
1462         }
1463         else {
1464                 u     = utf_null;
1465 #if defined(ENABLE_JAVASE)
1466                 group = mainthreadobj->object->group;
1467 #endif
1468         }
1469
1470         s = javastring_new(u);
1471
1472         o = (java_objectheader *) thread->object;
1473
1474 #if defined(WITH_CLASSPATH_GNU)
1475         (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1476                                                   isdaemon);
1477 #elif defined(WITH_CLASSPATH_CLDC1_1)
1478         (void) vm_call_method(method_thread_init, o, s);
1479 #endif
1480
1481         if (*exceptionptr)
1482                 return false;
1483
1484 #if defined(ENABLE_JAVASE)
1485         /* store the thread group in the object */
1486
1487         thread->object->group = group;
1488
1489         /* add thread to given thread-group */
1490
1491         m = class_resolveclassmethod(group->header.vftbl->class,
1492                                                                  utf_addThread,
1493                                                                  utf_java_lang_Thread__V,
1494                                                                  class_java_lang_ThreadGroup,
1495                                                                  true);
1496
1497         o = (java_objectheader *) group;
1498
1499         (void) vm_call_method(m, o, t);
1500
1501         if (*exceptionptr)
1502                 return false;
1503 #endif
1504
1505         return true;
1506 }
1507
1508
1509 /* threads_detach_thread *******************************************************
1510
1511    Detaches the passed thread from the VM.  Used in JNI.
1512
1513 *******************************************************************************/
1514
1515 bool threads_detach_thread(threadobject *thread)
1516 {
1517 #if defined(ENABLE_JAVASE)
1518         java_lang_ThreadGroup *group;
1519         methodinfo            *m;
1520         java_objectheader     *o;
1521         java_lang_Thread      *t;
1522 #endif
1523
1524         /* Allow lock record pools to be used by other threads. They
1525            cannot be deleted so we'd better not waste them. */
1526
1527         /* XXX We have to find a new way to free lock records */
1528         /*     with the new locking algorithm.                */
1529         /* lock_record_free_pools(thread->ee.lockrecordpools); */
1530
1531         /* XXX implement uncaught exception stuff (like JamVM does) */
1532
1533 #if defined(ENABLE_JAVASE)
1534         /* remove thread from the thread group */
1535
1536         group = thread->object->group;
1537
1538         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1539
1540         if (group != NULL) {
1541                 m = class_resolveclassmethod(group->header.vftbl->class,
1542                                                                          utf_removeThread,
1543                                                                          utf_java_lang_Thread__V,
1544                                                                          class_java_lang_ThreadGroup,
1545                                                                          true);
1546
1547                 if (m == NULL)
1548                         return false;
1549
1550                 o = (java_objectheader *) group;
1551                 t = thread->object;
1552
1553                 (void) vm_call_method(m, o, t);
1554
1555                 if (*exceptionptr)
1556                         return false;
1557         }
1558 #endif
1559
1560         /* thread is terminated */
1561
1562         thread->state = THREAD_STATE_TERMINATED;
1563
1564         /* remove thread from thread list and threads table, do this
1565            inside a lock */
1566
1567         pthread_mutex_lock(&threadlistlock);
1568
1569         thread->next->prev = thread->prev;
1570         thread->prev->next = thread->next;
1571
1572         threads_table_remove(thread);
1573
1574         pthread_mutex_unlock(&threadlistlock);
1575
1576         /* reset thread id (lock on joinmutex? TWISTI) */
1577
1578         pthread_mutex_lock(&(thread->joinmutex));
1579         thread->tid = 0;
1580         pthread_mutex_unlock(&(thread->joinmutex));
1581
1582         /* tell everyone that a thread has finished */
1583
1584         pthread_cond_broadcast(&(thread->joincond));
1585
1586         /* free the vm internal thread object */
1587
1588         FREE(thread, threadobject);
1589
1590 #if defined(ENABLE_STATISTICS)
1591         if (opt_stat)
1592                 size_threadobject -= sizeof(threadobject);
1593 #endif
1594
1595         return true;
1596 }
1597
1598
1599 /* threads_suspend_thread ******************************************************
1600
1601    Suspend the passed thread. Execution stops until the thread
1602    is explicitly resumend again.
1603
1604    IN:
1605      reason.....Reason for suspending this thread.
1606
1607 *******************************************************************************/
1608
1609 bool threads_suspend_thread(threadobject *thread, s4 reason)
1610 {
1611         /* acquire the suspendmutex */
1612         pthread_mutex_lock(&(thread->suspendmutex));
1613
1614         if (thread->suspended) {
1615                 pthread_mutex_unlock(&(thread->suspendmutex));
1616                 return false;
1617         }
1618
1619         /* set the reason for the suspension */
1620         thread->suspend_reason = reason;
1621
1622         /* send the suspend signal to the thread */
1623         assert(thread != THREADOBJECT);
1624         pthread_kill(thread->tid, SIGUSR1);
1625
1626         /* REMEMBER: do not release the suspendmutex, this is done
1627            by the thread itself in threads_suspend_ack().  */
1628
1629         return true;
1630 }
1631
1632
1633 /* threads_suspend_ack *********************************************************
1634
1635    Acknowledges the suspension of the current thread.
1636
1637    IN:
1638      pc.....The PC where the thread suspended its execution.
1639      sp.....The SP before the thread suspended its execution.
1640
1641 *******************************************************************************/
1642
1643 void threads_suspend_ack(u1* pc, u1* sp)
1644 {
1645         threadobject *thread;
1646
1647         thread = THREADOBJECT;
1648
1649         assert(thread->suspend_reason != 0);
1650
1651         /* TODO: remember dump memory size */
1652
1653 #if defined(ENABLE_GC_CACAO)
1654         /* inform the GC about the suspension */
1655         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1656
1657                 /* check if the GC wants to leave the thread running */
1658                 if (!gc_suspend(thread, pc, sp)) {
1659
1660                         /* REMEMBER: we do not unlock the suspendmutex because the thread
1661                            will suspend itself again at a later time */
1662                         return;
1663
1664                 }
1665         }
1666 #endif
1667
1668         /* mark this thread as suspended and remember the PC */
1669         thread->pc        = pc;
1670         thread->suspended = true;
1671
1672         /* if we are stopping the world, we should send a global ack */
1673         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1674                 threads_sem_post(&suspend_ack);
1675         }
1676
1677         /* release the suspension mutex and wait till we are resumed */
1678         pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1679
1680         /* TODO: free dump memory */
1681
1682         /* release the suspendmutex */
1683         pthread_mutex_unlock(&(thread->suspendmutex));
1684 }
1685
1686
1687 /* threads_resume_thread *******************************************************
1688
1689    Resumes the execution of the passed thread.
1690
1691 *******************************************************************************/
1692
1693 bool threads_resume_thread(threadobject *thread)
1694 {
1695         /* acquire the suspendmutex */
1696         pthread_mutex_lock(&(thread->suspendmutex));
1697
1698         if (!thread->suspended) {
1699                 pthread_mutex_unlock(&(thread->suspendmutex));
1700                 return false;
1701         }
1702
1703         thread->suspended = false;
1704
1705         /* tell everyone that the thread should resume */
1706         assert(thread != THREADOBJECT);
1707         pthread_cond_broadcast(&(thread->suspendcond));
1708
1709         /* release the suspendmutex */
1710         pthread_mutex_unlock(&(thread->suspendmutex));
1711
1712         return true;
1713 }
1714
1715 /* threads_find_non_daemon_thread **********************************************
1716
1717    Helper function used by threads_join_all_threads for finding
1718    non-daemon threads that are still running.
1719
1720 *******************************************************************************/
1721
1722 /* At the end of the program, we wait for all running non-daemon
1723    threads to die. */
1724
1725 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1726 {
1727         while (thread != mainthreadobj) {
1728                 if (!(thread->flags & THREAD_FLAG_DAEMON))
1729                         return thread;
1730
1731                 thread = thread->prev;
1732         }
1733
1734         return NULL;
1735 }
1736
1737
1738 /* threads_join_all_threads ****************************************************
1739
1740    Join all non-daemon threads.
1741
1742 *******************************************************************************/
1743
1744 void threads_join_all_threads(void)
1745 {
1746         threadobject *thread;
1747
1748         pthread_mutex_lock(&threadlistlock);
1749
1750         while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1751                 pthread_mutex_lock(&(thread->joinmutex));
1752
1753                 pthread_mutex_unlock(&threadlistlock);
1754
1755                 while (thread->tid)
1756                         pthread_cond_wait(&(thread->joincond), &(thread->joinmutex));
1757
1758                 pthread_mutex_unlock(&(thread->joinmutex));
1759
1760                 pthread_mutex_lock(&threadlistlock);
1761         }
1762
1763         pthread_mutex_unlock(&threadlistlock);
1764 }
1765
1766
1767 /* threads_timespec_earlier ****************************************************
1768
1769    Return true if timespec tv1 is earlier than timespec tv2.
1770
1771    IN:
1772       tv1..........first timespec
1773           tv2..........second timespec
1774
1775    RETURN VALUE:
1776       true, if the first timespec is earlier
1777
1778 *******************************************************************************/
1779
1780 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1781                                                                                         const struct timespec *tv2)
1782 {
1783         return (tv1->tv_sec < tv2->tv_sec)
1784                                 ||
1785                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1786 }
1787
1788
1789 /* threads_current_time_is_earlier_than ****************************************
1790
1791    Check if the current time is earlier than the given timespec.
1792
1793    IN:
1794       tv...........the timespec to compare against
1795
1796    RETURN VALUE:
1797       true, if the current time is earlier
1798
1799 *******************************************************************************/
1800
1801 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1802 {
1803         struct timeval tvnow;
1804         struct timespec tsnow;
1805
1806         /* get current time */
1807
1808         if (gettimeofday(&tvnow, NULL) != 0)
1809                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1810
1811         /* convert it to a timespec */
1812
1813         tsnow.tv_sec = tvnow.tv_sec;
1814         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1815
1816         /* compare current time with the given timespec */
1817
1818         return threads_timespec_earlier(&tsnow, tv);
1819 }
1820
1821
1822 /* threads_wait_with_timeout ***************************************************
1823
1824    Wait until the given point in time on a monitor until either
1825    we are notified, we are interrupted, or the time is up.
1826
1827    IN:
1828       t............the current thread
1829           wakeupTime...absolute (latest) wakeup time
1830                            If both tv_sec and tv_nsec are zero, this function
1831                                            waits for an unlimited amount of time.
1832
1833    RETURN VALUE:
1834       true.........if the wait has been interrupted,
1835           false........if the wait was ended by notification or timeout
1836
1837 *******************************************************************************/
1838
1839 static bool threads_wait_with_timeout(threadobject *thread,
1840                                                                           struct timespec *wakeupTime)
1841 {
1842         bool wasinterrupted;
1843
1844         /* acquire the waitmutex */
1845
1846         pthread_mutex_lock(&thread->waitmutex);
1847
1848         /* mark us as sleeping */
1849
1850         thread->sleeping = true;
1851
1852         /* wait on waitcond */
1853
1854         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1855                 /* with timeout */
1856                 while (!thread->interrupted && !thread->signaled
1857                            && threads_current_time_is_earlier_than(wakeupTime))
1858                 {
1859                         thread->state = THREAD_STATE_TIMED_WAITING;
1860
1861                         pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1862                                                                    wakeupTime);
1863
1864                         thread->state = THREAD_STATE_RUNNABLE;
1865                 }
1866         }
1867         else {
1868                 /* no timeout */
1869                 while (!thread->interrupted && !thread->signaled) {
1870                         thread->state = THREAD_STATE_WAITING;
1871
1872                         pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1873
1874                         thread->state = THREAD_STATE_RUNNABLE;
1875                 }
1876         }
1877
1878         /* check if we were interrupted */
1879
1880         wasinterrupted = thread->interrupted;
1881
1882         /* reset all flags */
1883
1884         thread->interrupted = false;
1885         thread->signaled    = false;
1886         thread->sleeping    = false;
1887
1888         /* release the waitmutex */
1889
1890         pthread_mutex_unlock(&thread->waitmutex);
1891
1892         return wasinterrupted;
1893 }
1894
1895
1896 /* threads_wait_with_timeout_relative ******************************************
1897
1898    Wait for the given maximum amount of time on a monitor until either
1899    we are notified, we are interrupted, or the time is up.
1900
1901    IN:
1902       t............the current thread
1903           millis.......milliseconds to wait
1904           nanos........nanoseconds to wait
1905
1906    RETURN VALUE:
1907       true.........if the wait has been interrupted,
1908           false........if the wait was ended by notification or timeout
1909
1910 *******************************************************************************/
1911
1912 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1913                                                                                 s4 nanos)
1914 {
1915         struct timespec wakeupTime;
1916
1917         /* calculate the the (latest) wakeup time */
1918
1919         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1920
1921         /* wait */
1922
1923         return threads_wait_with_timeout(thread, &wakeupTime);
1924 }
1925
1926
1927 /* threads_calc_absolute_time **************************************************
1928
1929    Calculate the absolute point in time a given number of ms and ns from now.
1930
1931    IN:
1932       millis............milliseconds from now
1933           nanos.............nanoseconds from now
1934
1935    OUT:
1936       *tm...............receives the timespec of the absolute point in time
1937
1938 *******************************************************************************/
1939
1940 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1941 {
1942         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1943                 struct timeval tv;
1944                 long nsec;
1945                 gettimeofday(&tv, NULL);
1946                 tv.tv_sec += millis / 1000;
1947                 millis %= 1000;
1948                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1949                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1950                 tm->tv_nsec = nsec % 1000000000;
1951         }
1952         else {
1953                 tm->tv_sec = 0;
1954                 tm->tv_nsec = 0;
1955         }
1956 }
1957
1958
1959 /* threads_thread_interrupt ****************************************************
1960
1961    Interrupt the given thread.
1962
1963    The thread gets the "waitcond" signal and 
1964    its interrupted flag is set to true.
1965
1966    IN:
1967       thread............the thread to interrupt
1968
1969 *******************************************************************************/
1970
1971 void threads_thread_interrupt(threadobject *thread)
1972 {
1973         /* Signal the thread a "waitcond" and tell it that it has been
1974            interrupted. */
1975
1976         pthread_mutex_lock(&thread->waitmutex);
1977
1978         /* Interrupt blocking system call using a signal. */
1979
1980         pthread_kill(thread->tid, SIGHUP);
1981
1982         if (thread->sleeping)
1983                 pthread_cond_signal(&thread->waitcond);
1984
1985         thread->interrupted = true;
1986
1987         pthread_mutex_unlock(&thread->waitmutex);
1988 }
1989
1990
1991 /* threads_check_if_interrupted_and_reset **************************************
1992
1993    Check if the current thread has been interrupted and reset the
1994    interruption flag.
1995
1996    RETURN VALUE:
1997       true, if the current thread had been interrupted
1998
1999 *******************************************************************************/
2000
2001 bool threads_check_if_interrupted_and_reset(void)
2002 {
2003         threadobject *thread;
2004         bool intr;
2005
2006         thread = THREADOBJECT;
2007
2008         /* get interrupted flag */
2009
2010         intr = thread->interrupted;
2011
2012         /* reset interrupted flag */
2013
2014         thread->interrupted = false;
2015
2016         return intr;
2017 }
2018
2019
2020 /* threads_thread_has_been_interrupted *****************************************
2021
2022    Check if the given thread has been interrupted
2023
2024    IN:
2025       t............the thread to check
2026
2027    RETURN VALUE:
2028       true, if the given thread had been interrupted
2029
2030 *******************************************************************************/
2031
2032 bool threads_thread_has_been_interrupted(threadobject *thread)
2033 {
2034         return thread->interrupted;
2035 }
2036
2037
2038 /* threads_sleep ***************************************************************
2039
2040    Sleep the current thread for the specified amount of time.
2041
2042 *******************************************************************************/
2043
2044 void threads_sleep(s8 millis, s4 nanos)
2045 {
2046         threadobject    *thread;
2047         struct timespec  wakeupTime;
2048         bool             wasinterrupted;
2049
2050         thread = THREADOBJECT;
2051
2052         threads_calc_absolute_time(&wakeupTime, millis, nanos);
2053
2054         wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
2055
2056         if (wasinterrupted)
2057                 exceptions_throw_interruptedexception();
2058 }
2059
2060
2061 /* threads_yield ***************************************************************
2062
2063    Yield to the scheduler.
2064
2065 *******************************************************************************/
2066
2067 void threads_yield(void)
2068 {
2069         sched_yield();
2070 }
2071
2072
2073 /* threads_table_dump *********************************************************
2074
2075    Dump the threads table for debugging purposes.
2076
2077    IN:
2078       file..............stream to write to
2079
2080 ******************************************************************************/
2081
2082 #if !defined(NDEBUG) && 0
2083 static void threads_table_dump(FILE *file)
2084 {
2085         s4 i;
2086         s4 size;
2087         ptrint index;
2088
2089         pthread_mutex_lock(&threadlistlock);
2090
2091         size = threads_table.size;
2092
2093         fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
2094
2095         for (i=0; i<size; ++i) {
2096                 index = threads_table.table[i].nextfree;
2097
2098                 fprintf(file, "%4d: ", i);
2099
2100                 if (index < size) {
2101                         fprintf(file, "free, nextfree = %d\n", (int) index);
2102                 }
2103                 else {
2104                         fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
2105                 }
2106         }
2107
2108         fprintf(file, "======== END OF THREADS TABLE ========\n");
2109
2110         pthread_mutex_unlock(&threadlistlock);
2111 }
2112 #endif
2113
2114 /*
2115  * These are local overrides for various environment variables in Emacs.
2116  * Please do not remove this and leave it at the end of the file, where
2117  * Emacs will automagically detect them.
2118  * ---------------------------------------------------------------------
2119  * Local variables:
2120  * mode: c
2121  * indent-tabs-mode: t
2122  * c-basic-offset: 4
2123  * tab-width: 4
2124  * End:
2125  * vim:noexpandtab:sw=4:ts=4:
2126  */