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