9682eba010a1ab640a21692faf78c28ddec62df5
[cacao.git] / src / threads / posix / thread-posix.c
1 /* src/threads/posix/thread-posix.c - POSIX thread functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 /* XXX cleanup these includes */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <signal.h>
36 #include <sys/time.h>
37 #include <time.h>
38 #include <errno.h>
39
40 #include <pthread.h>
41
42 #include "vm/types.h"
43
44 #include "arch.h"
45
46 #include "mm/gc.hpp"
47 #include "mm/memory.h"
48
49 #if defined(ENABLE_GC_CACAO)
50 # include "mm/cacao-gc/gc.h"
51 #endif
52
53 #include "native/jni.h"
54 #include "native/llni.h"
55 #include "native/native.h"
56
57 #include "native/include/java_lang_Object.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
60 #include "native/include/java_lang_Thread.h"
61
62 #if defined(ENABLE_JAVASE)
63 # include "native/include/java_lang_ThreadGroup.h"
64 #endif
65
66 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
67 # include "native/include/java_lang_VMThread.h"
68 #endif
69
70 #include "threads/condition.hpp"
71 #include "threads/lock-common.h"
72 #include "threads/mutex.hpp"
73 #include "threads/threadlist.h"
74 #include "threads/thread.h"
75
76 #include "toolbox/logging.h"
77
78 #include "vm/builtin.h"
79 #include "vm/exceptions.h"
80 #include "vm/global.h"
81 #include "vm/stringlocal.h"
82 #include "vm/vm.hpp"
83
84 #include "vm/jit/asmpart.h"
85
86 #include "vmcore/globals.hpp"
87 #include "vmcore/options.h"
88
89 #if defined(ENABLE_STATISTICS)
90 # include "vmcore/statistics.h"
91 #endif
92
93 #if !defined(__DARWIN__)
94 # include <semaphore.h>
95 #endif
96
97 #if defined(__LINUX__)
98 # define GC_LINUX_THREADS
99 #elif defined(__IRIX__)
100 # define GC_IRIX_THREADS
101 #elif defined(__DARWIN__)
102 # define GC_DARWIN_THREADS
103 #endif
104
105 #if defined(ENABLE_GC_BOEHM)
106 /* We need to include Boehm's gc.h here because it overrides
107    pthread_create and friends. */
108 # include "mm/boehm-gc/include/gc.h"
109 #endif
110
111 #if defined(ENABLE_JVMTI)
112 #include "native/jvmti/cacaodbg.h"
113 #endif
114
115 #if defined(__DARWIN__)
116 /* Darwin has no working semaphore implementation.  This one is taken
117    from Boehm-GC. */
118
119 /*
120    This is a very simple semaphore implementation for darwin. It
121    is implemented in terms of pthreads calls so it isn't async signal
122    safe. This isn't a problem because signals aren't used to
123    suspend threads on darwin.
124 */
125    
126 static int sem_init(sem_t *sem, int pshared, int value)
127 {
128         if (pshared)
129                 assert(0);
130
131         sem->value = value;
132     
133         sem->mutex = Mutex_new();
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         Mutex_lock(sem->mutex);
144
145         sem->value++;
146
147         if (pthread_cond_signal(&sem->cond) < 0) {
148                 Mutex_unlock(sem->mutex);
149                 return -1;
150         }
151
152         Mutex_unlock(sem->mutex);
153
154         return 0;
155 }
156
157 static int sem_wait(sem_t *sem)
158 {
159         Mutex_lock(sem->mutex);
160
161         while (sem->value == 0) {
162 #error We cannot call pthread_cond_wait on a Mutex-class pointer.
163                 pthread_cond_wait(&sem->cond, &sem->mutex);
164         }
165
166         sem->value--;
167
168         Mutex_unlock(sem->mutex);
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         Mutex_destroy(sem->mutex);
179
180         return 0;
181 }
182 #endif /* defined(__DARWIN__) */
183
184
185 /* startupinfo *****************************************************************
186
187    Struct used to pass info from threads_start_thread to 
188    threads_startup_thread.
189
190 ******************************************************************************/
191
192 typedef struct {
193         threadobject *thread;      /* threadobject for this thread             */
194         functionptr   function;    /* function to run in the new thread        */
195         sem_t        *psem;        /* signals when thread has been entered     */
196                                    /* in the thread list                       */
197         sem_t        *psem_first;  /* signals when pthread_create has returned */
198 } startupinfo;
199
200
201 /* prototypes *****************************************************************/
202
203 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
204
205
206 /******************************************************************************/
207 /* GLOBAL VARIABLES                                                           */
208 /******************************************************************************/
209
210 /* the thread object of the current thread                                    */
211 /* This is either a thread-local variable defined with __thread, or           */
212 /* a thread-specific value stored with key threads_current_threadobject_key.  */
213 #if defined(HAVE___THREAD)
214 __thread threadobject *thread_current;
215 #else
216 pthread_key_t thread_current_key;
217 #endif
218
219 /* global mutex for stop-the-world                                            */
220 static Mutex* stopworldlock;
221
222 #if defined(ENABLE_GC_CACAO)
223 /* global mutex for the GC */
224 static Mutex* mutex_gc;
225 #endif
226
227 /* global mutex and condition for joining threads on exit */
228 static Mutex* mutex_join;
229 static Condition* cond_join;
230
231 #if defined(ENABLE_GC_CACAO)
232 /* semaphore used for acknowleding thread suspension                          */
233 static sem_t suspend_ack;
234 #endif
235
236
237 /* threads_sem_init ************************************************************
238  
239    Initialize a semaphore. Checks against errors and interruptions.
240
241    IN:
242        sem..............the semaphore to initialize
243            shared...........true if this semaphore will be shared between processes
244            value............the initial value for the semaphore
245    
246 *******************************************************************************/
247
248 void threads_sem_init(sem_t *sem, bool shared, int value)
249 {
250         int r;
251
252         assert(sem);
253
254         do {
255                 r = sem_init(sem, shared, value);
256                 if (r == 0)
257                         return;
258         } while (errno == EINTR);
259
260         vm_abort("sem_init failed: %s", strerror(errno));
261 }
262
263
264 /* threads_sem_wait ************************************************************
265  
266    Wait for a semaphore, non-interruptible.
267
268    IMPORTANT: Always use this function instead of `sem_wait` directly, as
269               `sem_wait` may be interrupted by signals!
270   
271    IN:
272        sem..............the semaphore to wait on
273    
274 *******************************************************************************/
275
276 void threads_sem_wait(sem_t *sem)
277 {
278         int r;
279
280         assert(sem);
281
282         do {
283                 r = sem_wait(sem);
284                 if (r == 0)
285                         return;
286         } while (errno == EINTR);
287
288         vm_abort("sem_wait failed: %s", strerror(errno));
289 }
290
291
292 /* threads_sem_post ************************************************************
293  
294    Increase the count of a semaphore. Checks for errors.
295
296    IN:
297        sem..............the semaphore to increase the count of
298    
299 *******************************************************************************/
300
301 void threads_sem_post(sem_t *sem)
302 {
303         int r;
304
305         assert(sem);
306
307         /* unlike sem_wait, sem_post is not interruptible */
308
309         r = sem_post(sem);
310         if (r == 0)
311                 return;
312
313         vm_abort("sem_post failed: %s", strerror(errno));
314 }
315
316
317 /* threads_stopworld ***********************************************************
318
319    Stops the world from turning. All threads except the calling one
320    are suspended. The function returns as soon as all threads have
321    acknowledged their suspension.
322
323 *******************************************************************************/
324
325 #if defined(ENABLE_GC_CACAO)
326 void threads_stopworld(void)
327 {
328 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
329         threadobject *t;
330         threadobject *self;
331         bool result;
332         s4 count, i;
333 #endif
334
335         Mutex_lock(stopworldlock);
336
337         /* lock the threads lists */
338
339         threadlist_lock();
340
341 #if defined(__DARWIN__)
342         /*threads_cast_darwinstop();*/
343         assert(0);
344 #elif defined(__CYGWIN__)
345         /* TODO */
346         assert(0);
347 #else
348         self = THREADOBJECT;
349
350         DEBUGTHREADS("stops World", self);
351
352         count = 0;
353
354         /* suspend all running threads */
355         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
356                 /* don't send the signal to ourself */
357
358                 if (t == self)
359                         continue;
360
361                 /* don't send the signal to NEW threads (because they are not
362                    completely initialized) */
363
364                 if (t->state == THREAD_STATE_NEW)
365                         continue;
366
367                 /* send the signal */
368
369                 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
370                 assert(result);
371
372                 /* increase threads count */
373
374                 count++;
375         }
376
377         /* wait for all threads signaled to suspend */
378         for (i = 0; i < count; i++)
379                 threads_sem_wait(&suspend_ack);
380 #endif
381
382         /* ATTENTION: Don't unlock the threads-lists here so that
383            non-signaled NEW threads can't change their state and execute
384            code. */
385 }
386 #endif
387
388
389 /* threads_startworld **********************************************************
390
391    Starts the world again after it has previously been stopped. 
392
393 *******************************************************************************/
394
395 #if defined(ENABLE_GC_CACAO)
396 void threads_startworld(void)
397 {
398 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
399         threadobject *t;
400         threadobject *self;
401         bool result;
402         s4 count, i;
403 #endif
404
405 #if defined(__DARWIN__)
406         /*threads_cast_darwinresume();*/
407         assert(0);
408 #elif defined(__IRIX__)
409         threads_cast_irixresume();
410 #elif defined(__CYGWIN__)
411         /* TODO */
412         assert(0);
413 #else
414         self = THREADOBJECT;
415
416         DEBUGTHREADS("starts World", self);
417
418         count = 0;
419
420         /* resume all thread we haltet */
421         for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
422                 /* don't send the signal to ourself */
423
424                 if (t == self)
425                         continue;
426
427                 /* don't send the signal to NEW threads (because they are not
428                    completely initialized) */
429
430                 if (t->state == THREAD_STATE_NEW)
431                         continue;
432
433                 /* send the signal */
434
435                 result = threads_resume_thread(t);
436                 assert(result);
437
438                 /* increase threads count */
439
440                 count++;
441         }
442
443         /* wait for all threads signaled to suspend */
444         for (i = 0; i < count; i++)
445                 threads_sem_wait(&suspend_ack);
446
447 #endif
448
449         /* unlock the threads lists */
450
451         threadlist_unlock();
452
453         Mutex_unlock(stopworldlock);
454 }
455 #endif
456
457
458 /* threads_impl_thread_init ****************************************************
459
460    Initialize OS-level locking constructs in threadobject.
461
462    IN:
463       t....the threadobject
464
465 *******************************************************************************/
466
467 void threads_impl_thread_init(threadobject *t)
468 {
469         /* initialize the mutex and the condition */
470
471         t->flc_lock = Mutex_new();
472         t->flc_cond = Condition_new();
473
474         t->waitmutex = Mutex_new();
475         t->waitcond = Condition_new();
476
477         t->suspendmutex = Mutex_new();
478         t->suspendcond = Condition_new();
479
480 #if defined(ENABLE_TLH)
481         tlh_init(&(t->tlh));
482 #endif
483 }
484
485 /* threads_impl_thread_clear ***************************************************
486
487    Clears all fields in threadobject the way an MZERO would have
488    done. MZERO cannot be used anymore because it would mess up the
489    pthread_* bits.
490
491    IN:
492       t....the threadobject
493
494 *******************************************************************************/
495
496 void threads_impl_thread_clear(threadobject *t)
497 {
498         t->object = NULL;
499
500         t->thinlock = 0;
501
502         t->index = 0;
503         t->flags = 0;
504         t->state = 0;
505
506         t->tid = 0;
507
508 #if defined(__DARWIN__)
509         t->mach_thread = 0;
510 #endif
511
512         t->interrupted = false;
513         t->signaled = false;
514
515         t->suspended = false;
516         t->suspend_reason = 0;
517
518         t->pc = NULL;
519
520         t->_exceptionptr = NULL;
521         t->_stackframeinfo = NULL;
522         t->_localref_table = NULL;
523
524 #if defined(ENABLE_INTRP)
525         t->_global_sp = NULL;
526 #endif
527
528 #if defined(ENABLE_GC_CACAO)
529         t->gc_critical = false;
530
531         t->ss = NULL;
532         t->es = NULL;
533 #endif
534
535         MZERO(&t->dumpinfo, dumpinfo_t, 1);
536 }
537
538 /* threads_impl_thread_reuse ***************************************************
539
540    Resets some implementation fields in threadobject. This was
541    previously done in threads_impl_thread_new.
542
543    IN:
544       t....the threadobject
545
546 *******************************************************************************/
547
548 void threads_impl_thread_reuse(threadobject *t)
549 {
550         /* get the pthread id */
551
552         t->tid = pthread_self();
553
554 #if defined(ENABLE_DEBUG_FILTER)
555         /* Initialize filter counters */
556         t->filterverbosecallctr[0] = 0;
557         t->filterverbosecallctr[1] = 0;
558 #endif
559
560 #if !defined(NDEBUG)
561         t->tracejavacallindent = 0;
562         t->tracejavacallcount = 0;
563 #endif
564
565         t->flc_bit = false;
566         t->flc_next = NULL;
567         t->flc_list = NULL;
568
569 /*      not really needed */
570         t->flc_object = NULL;
571
572 #if defined(ENABLE_TLH)
573         tlh_destroy(&(t->tlh));
574         tlh_init(&(t->tlh));
575 #endif
576 }
577
578
579 /* threads_impl_thread_free ****************************************************
580
581    Cleanup thread stuff.
582
583    IN:
584       t....the threadobject
585
586 *******************************************************************************/
587
588 #if 0
589 /* never used */
590 void threads_impl_thread_free(threadobject *t)
591 {
592         int result;
593
594         /* Destroy the mutex and the condition. */
595
596         Mutex_delete(t->flc_lock);
597
598         result = pthread_cond_destroy(&(t->flc_cond));
599
600         if (result != 0)
601                 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
602
603         Mutex_delete(t->waitmutex);
604
605         result = pthread_cond_destroy(&(t->waitcond));
606
607         if (result != 0)
608                 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
609
610         Mutex_delete(t->suspendmutex);
611
612         result = pthread_cond_destroy(&(t->suspendcond));
613
614         if (result != 0)
615                 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
616 }
617 #endif
618
619
620 /* threads_impl_preinit ********************************************************
621
622    Do some early initialization of stuff required.
623
624    ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
625    is called AFTER this function!
626
627 *******************************************************************************/
628
629 void threads_impl_preinit(void)
630 {
631         int result;
632
633         stopworldlock = Mutex_new();
634
635         /* initialize exit mutex and condition (on exit we join all
636            threads) */
637
638         mutex_join = Mutex_new();
639         cond_join = Condition_new();
640
641 #if defined(ENABLE_GC_CACAO)
642         /* initialize the GC mutex & suspend semaphore */
643
644         mutex_gc = Mutex_new();
645         threads_sem_init(&suspend_ack, 0, 0);
646 #endif
647
648 #if !defined(HAVE___THREAD)
649         result = pthread_key_create(&thread_current_key, NULL);
650         if (result != 0)
651                 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
652 #endif
653 }
654
655
656 /* threads_mutex_gc_lock *******************************************************
657
658    Enter the global GC mutex.
659
660 *******************************************************************************/
661
662 #if defined(ENABLE_GC_CACAO)
663 void threads_mutex_gc_lock(void)
664 {
665         Mutex_lock(mutex_gc);
666 }
667 #endif
668
669
670 /* threads_mutex_gc_unlock *****************************************************
671
672    Leave the global GC mutex.
673
674 *******************************************************************************/
675
676 #if defined(ENABLE_GC_CACAO)
677 void threads_mutex_gc_unlock(void)
678 {
679         Mutex_unlock(mutex_gc);
680 }
681 #endif
682
683 /* threads_mutex_join_lock *****************************************************
684
685    Enter the join mutex.
686
687 *******************************************************************************/
688
689 void threads_mutex_join_lock(void)
690 {
691         Mutex_lock(mutex_join);
692 }
693
694
695 /* threads_mutex_join_unlock ***************************************************
696
697    Leave the join mutex.
698
699 *******************************************************************************/
700
701 void threads_mutex_join_unlock(void)
702 {
703         Mutex_unlock(mutex_join);
704 }
705
706
707 /* threads_impl_init ***********************************************************
708
709    Initializes the implementation specific bits.
710
711 *******************************************************************************/
712
713 void threads_impl_init(void)
714 {
715         pthread_attr_t attr;
716         int            result;
717
718         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
719
720         /* Initialize the thread attribute object. */
721
722         result = pthread_attr_init(&attr);
723
724         if (result != 0)
725                 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
726
727         result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
728
729         if (result != 0)
730                 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
731 }
732
733
734 /* threads_startup_thread ******************************************************
735
736    Thread startup function called by pthread_create.
737
738    Thread which have a startup.function != NULL are marked as internal
739    threads. All other threads are threated as normal Java threads.
740
741    NOTE: This function is not called directly by pthread_create. The Boehm GC
742          inserts its own GC_start_routine in between, which then calls
743                  threads_startup.
744
745    IN:
746       arg..........the argument passed to pthread_create, ie. a pointer to
747                        a startupinfo struct. CAUTION: When the `psem` semaphore
748                                    is posted, the startupinfo struct becomes invalid! (It
749                                    is allocated on the stack of threads_start_thread.)
750
751 ******************************************************************************/
752
753 static void *threads_startup_thread(void *arg)
754 {
755         startupinfo        *startup;
756         threadobject       *t;
757         java_lang_Thread   *object;
758 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
759         java_lang_VMThread *vmt;
760 #endif
761         sem_t              *psem;
762         classinfo          *c;
763         methodinfo         *m;
764         java_handle_t      *o;
765         functionptr         function;
766
767 #if defined(ENABLE_GC_BOEHM)
768 # if !defined(__DARWIN__)
769         struct GC_stack_base sb;
770         int result;
771 # endif
772 #endif
773
774 #if defined(ENABLE_INTRP)
775         u1 *intrp_thread_stack;
776 #endif
777
778 #if defined(ENABLE_INTRP)
779         /* create interpreter stack */
780
781         if (opt_intrp) {
782                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
783                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
784         }
785         else
786                 intrp_thread_stack = NULL;
787 #endif
788
789         /* get passed startupinfo structure and the values in there */
790
791         startup = arg;
792
793         t        = startup->thread;
794         function = startup->function;
795         psem     = startup->psem;
796
797         /* Seems like we've encountered a situation where thread->tid was
798            not set by pthread_create. We alleviate this problem by waiting
799            for pthread_create to return. */
800
801         threads_sem_wait(startup->psem_first);
802
803 #if defined(__DARWIN__)
804         t->mach_thread = mach_thread_self();
805 #endif
806
807         /* Now that we are in the new thread, we can store the internal
808            thread data-structure in the TSD. */
809
810         thread_set_current(t);
811
812 #if defined(ENABLE_GC_BOEHM)
813 # if defined(__DARWIN__)
814         // This is currently not implemented in Boehm-GC.  Just fail silently.
815 # else
816         /* Register the thread with Boehm-GC.  This must happen before the
817            thread allocates any memory from the GC heap.*/
818
819         result = GC_get_stack_base(&sb);
820
821         if (result != 0)
822                 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
823
824         GC_register_my_thread(&sb);
825 # endif
826 #endif
827
828         /* get the java.lang.Thread object for this thread */
829
830         object = (java_lang_Thread *) thread_get_object(t);
831
832         /* set our priority */
833
834         threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
835
836         /* Thread is completely initialized. */
837
838         thread_set_state_runnable(t);
839
840         /* tell threads_startup_thread that we registered ourselves */
841         /* CAUTION: *startup becomes invalid with this!             */
842
843         startup = NULL;
844         threads_sem_post(psem);
845
846 #if defined(ENABLE_INTRP)
847         /* set interpreter stack */
848
849         if (opt_intrp)
850                 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
851 #endif
852
853 #if defined(ENABLE_JVMTI)
854         /* fire thread start event */
855
856         if (jvmti) 
857                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
858 #endif
859
860         DEBUGTHREADS("starting", t);
861
862         /* find and run the Thread.run()V method if no other function was passed */
863
864         if (function == NULL) {
865 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
866                 /* We need to start the run method of
867                    java.lang.VMThread. Since this is a final class, we can use
868                    the class object directly. */
869
870                 c = class_java_lang_VMThread;
871 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
872                 LLNI_class_get(object, c);
873 #else
874 # error unknown classpath configuration
875 #endif
876
877                 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
878
879                 if (m == NULL)
880                         vm_abort("threads_startup_thread: run() method not found in class");
881
882                 /* set ThreadMXBean variables */
883
884 /*              _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
885 /*              _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
886
887 /*              if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
888 /*                      _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
889 /*                      _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
890 /*                              _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
891 #warning Move to C++
892
893 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
894                 /* we need to start the run method of java.lang.VMThread */
895
896                 LLNI_field_get_ref(object, vmThread, vmt);
897                 o = (java_handle_t *) vmt;
898
899 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
900                 o = (java_handle_t *) object;
901 #else
902 # error unknown classpath configuration
903 #endif
904
905                 /* Run the thread. */
906
907                 (void) vm_call_method(m, o);
908         }
909         else {
910                 /* set ThreadMXBean variables */
911
912 /*              _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
913 /*              _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
914
915 /*              if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
916 /*                      _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
917 /*                      _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
918 /*                              _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
919 #warning Move to C++
920
921                 /* call passed function, e.g. finalizer_thread */
922
923                 (function)();
924         }
925
926         DEBUGTHREADS("stopping", t);
927
928 #if defined(ENABLE_JVMTI)
929         /* fire thread end event */
930
931         if (jvmti)
932                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
933 #endif
934
935         /* We ignore the return value. */
936
937         (void) thread_detach_current_thread();
938
939         /* set ThreadMXBean variables */
940
941 /*      _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
942 #warning Move to C++
943
944         return NULL;
945 }
946
947
948 /* threads_impl_thread_start ***************************************************
949
950    Start a thread in the JVM.  Both (vm internal and java) thread
951    objects exist.
952
953    IN:
954       thread....the thread object
955           f.........function to run in the new thread. NULL means that the
956                     "run" method of the object `t` should be called
957
958 ******************************************************************************/
959
960 void threads_impl_thread_start(threadobject *thread, functionptr f)
961 {
962         sem_t          sem;
963         sem_t          sem_first;
964         pthread_attr_t attr;
965         startupinfo    startup;
966         int            result;
967
968         /* fill startupinfo structure passed by pthread_create to
969          * threads_startup_thread */
970
971         startup.thread     = thread;
972         startup.function   = f;              /* maybe we don't call Thread.run()V */
973         startup.psem       = &sem;
974         startup.psem_first = &sem_first;
975
976         threads_sem_init(&sem, 0, 0);
977         threads_sem_init(&sem_first, 0, 0);
978
979         /* Initialize thread attributes. */
980
981         result = pthread_attr_init(&attr);
982
983         if (result != 0)
984                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
985
986     result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
987
988     if (result != 0)
989                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
990
991         /* initialize thread stacksize */
992
993         result = pthread_attr_setstacksize(&attr, opt_stacksize);
994
995         if (result != 0)
996                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
997
998         /* create the thread */
999
1000         result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1001
1002         if (result != 0)
1003                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1004
1005         /* destroy the thread attributes */
1006
1007         result = pthread_attr_destroy(&attr);
1008
1009         if (result != 0)
1010                 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1011
1012         /* signal that pthread_create has returned, so thread->tid is valid */
1013
1014         threads_sem_post(&sem_first);
1015
1016         /* wait here until the thread has entered itself into the thread list */
1017
1018         threads_sem_wait(&sem);
1019
1020         /* cleanup */
1021
1022         sem_destroy(&sem);
1023         sem_destroy(&sem_first);
1024 }
1025
1026
1027 /* threads_set_thread_priority *************************************************
1028
1029    Set the priority of the given thread.
1030
1031    IN:
1032       tid..........thread id
1033           priority.....priority to set
1034
1035 ******************************************************************************/
1036
1037 void threads_set_thread_priority(pthread_t tid, int priority)
1038 {
1039         struct sched_param schedp;
1040         int policy;
1041
1042         pthread_getschedparam(tid, &policy, &schedp);
1043         schedp.sched_priority = priority;
1044         pthread_setschedparam(tid, policy, &schedp);
1045 }
1046
1047
1048 /**
1049  * Detaches the current thread from the VM.
1050  *
1051  * @return true on success, false otherwise
1052  */
1053 bool thread_detach_current_thread(void)
1054 {
1055         threadobject          *t;
1056         bool                   result;
1057         java_lang_Thread      *object;
1058         java_handle_t         *o;
1059 #if defined(ENABLE_JAVASE)
1060         java_lang_ThreadGroup *group;
1061         java_handle_t         *e;
1062         void                  *handler;
1063         classinfo             *c;
1064         methodinfo            *m;
1065 #endif
1066
1067         t = thread_get_current();
1068
1069         /* Sanity check. */
1070
1071         assert(t != NULL);
1072
1073     /* If the given thread has already been detached, this operation
1074            is a no-op. */
1075
1076         result = thread_is_attached(t);
1077
1078         if (result == false)
1079                 return true;
1080
1081         DEBUGTHREADS("detaching", t);
1082
1083         object = (java_lang_Thread *) thread_get_object(t);
1084
1085 #if defined(ENABLE_JAVASE)
1086         LLNI_field_get_ref(object, group, group);
1087
1088     /* If there's an uncaught exception, call uncaughtException on the
1089        thread's exception handler, or the thread's group if this is
1090        unset. */
1091
1092         e = exceptions_get_and_clear_exception();
1093
1094     if (e != NULL) {
1095                 /* We use the type void* for handler here, as it's not trivial
1096                    to build the java_lang_Thread_UncaughtExceptionHandler
1097                    header file with cacaoh. */
1098
1099 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1100                 LLNI_field_get_ref(object, exceptionHandler, handler);
1101 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1102                 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1103 # endif
1104
1105                 if (handler != NULL) {
1106                         LLNI_class_get(handler, c);
1107                         o = (java_handle_t *) handler;
1108                 }
1109                 else {
1110                         LLNI_class_get(group, c);
1111                         o = (java_handle_t *) group;
1112                 }
1113
1114                 m = class_resolveclassmethod(c,
1115                                                                          utf_uncaughtException,
1116                                                                          utf_java_lang_Thread_java_lang_Throwable__V,
1117                                                                          NULL,
1118                                                                          true);
1119
1120                 if (m == NULL)
1121                         return false;
1122
1123                 (void) vm_call_method(m, o, object, e);
1124
1125                 if (exceptions_get_exception())
1126                         return false;
1127     }
1128
1129         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1130
1131         /* Remove thread from the thread group. */
1132
1133         if (group != NULL) {
1134                 LLNI_class_get(group, c);
1135
1136 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1137                 m = class_resolveclassmethod(c,
1138                                                                          utf_removeThread,
1139                                                                          utf_java_lang_Thread__V,
1140                                                                          class_java_lang_ThreadGroup,
1141                                                                          true);
1142 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1143                 m = class_resolveclassmethod(c,
1144                                                                          utf_remove,
1145                                                                          utf_java_lang_Thread__V,
1146                                                                          class_java_lang_ThreadGroup,
1147                                                                          true);
1148 # else
1149 #  error unknown classpath configuration
1150 # endif
1151
1152                 if (m == NULL)
1153                         return false;
1154
1155                 o = (java_handle_t *) group;
1156
1157                 (void) vm_call_method(m, o, object);
1158
1159                 if (exceptions_get_exception())
1160                         return false;
1161
1162                 /* Reset the threadgroup in the Java thread object (Mauve
1163                    test: gnu/testlet/java/lang/Thread/getThreadGroup). */
1164
1165                 LLNI_field_set_ref(object, group, NULL);
1166         }
1167 #endif
1168
1169         /* Thread has terminated. */
1170
1171         thread_set_state_terminated(t);
1172
1173         /* Notify all threads waiting on this thread.  These are joining
1174            this thread. */
1175
1176         o = (java_handle_t *) object;
1177
1178         /* XXX Care about exceptions? */
1179         (void) lock_monitor_enter(o);
1180         
1181         lock_notify_all_object(o);
1182
1183         /* XXX Care about exceptions? */
1184         (void) lock_monitor_exit(o);
1185
1186         /* Enter the join-mutex before calling thread_free, so
1187            threads_join_all_threads gets the correct number of non-daemon
1188            threads. */
1189
1190         threads_mutex_join_lock();
1191
1192         /* Free the internal thread data-structure. */
1193
1194         thread_free(t);
1195
1196         /* Signal that this thread has finished and leave the mutex. */
1197
1198         Condition_signal(cond_join);
1199         threads_mutex_join_unlock();
1200
1201         return true;
1202 }
1203
1204
1205 /* threads_suspend_thread ******************************************************
1206
1207    Suspend the passed thread. Execution stops until the thread
1208    is explicitly resumend again.
1209
1210    IN:
1211      reason.....Reason for suspending this thread.
1212
1213 *******************************************************************************/
1214
1215 bool threads_suspend_thread(threadobject *thread, s4 reason)
1216 {
1217         /* acquire the suspendmutex */
1218         Mutex_lock(thread->suspendmutex);
1219
1220         if (thread->suspended) {
1221                 Mutex_unlock(thread->suspendmutex);
1222                 return false;
1223         }
1224
1225         /* set the reason for the suspension */
1226         thread->suspend_reason = reason;
1227
1228         /* send the suspend signal to the thread */
1229         assert(thread != THREADOBJECT);
1230         if (pthread_kill(thread->tid, SIGUSR1) != 0)
1231                 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1232                                  strerror(errno));
1233
1234         /* REMEMBER: do not release the suspendmutex, this is done
1235            by the thread itself in threads_suspend_ack().  */
1236
1237         return true;
1238 }
1239
1240
1241 /* threads_suspend_ack *********************************************************
1242
1243    Acknowledges the suspension of the current thread.
1244
1245    IN:
1246      pc.....The PC where the thread suspended its execution.
1247      sp.....The SP before the thread suspended its execution.
1248
1249 *******************************************************************************/
1250
1251 #if defined(ENABLE_GC_CACAO)
1252 void threads_suspend_ack(u1* pc, u1* sp)
1253 {
1254         threadobject *thread;
1255
1256         thread = THREADOBJECT;
1257
1258         assert(thread->suspend_reason != 0);
1259
1260         /* TODO: remember dump memory size */
1261
1262         /* inform the GC about the suspension */
1263         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1264
1265                 /* check if the GC wants to leave the thread running */
1266                 if (!gc_suspend(thread, pc, sp)) {
1267
1268                         /* REMEMBER: we do not unlock the suspendmutex because the thread
1269                            will suspend itself again at a later time */
1270                         return;
1271
1272                 }
1273         }
1274
1275         /* mark this thread as suspended and remember the PC */
1276         thread->pc        = pc;
1277         thread->suspended = true;
1278
1279         /* if we are stopping the world, we should send a global ack */
1280         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1281                 threads_sem_post(&suspend_ack);
1282         }
1283
1284         DEBUGTHREADS("suspending", thread);
1285
1286         /* release the suspension mutex and wait till we are resumed */
1287         Condition_wait(thread->suspendcond, thread->suspendmutex);
1288
1289         DEBUGTHREADS("resuming", thread);
1290
1291         /* if we are stopping the world, we should send a global ack */
1292         if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1293                 threads_sem_post(&suspend_ack);
1294         }
1295
1296         /* TODO: free dump memory */
1297
1298         /* release the suspendmutex */
1299         Mutex_unlock(thread->suspendmutex);
1300 }
1301 #endif
1302
1303
1304 /* threads_resume_thread *******************************************************
1305
1306    Resumes the execution of the passed thread.
1307
1308 *******************************************************************************/
1309
1310 #if defined(ENABLE_GC_CACAO)
1311 bool threads_resume_thread(threadobject *thread)
1312 {
1313         /* acquire the suspendmutex */
1314         Mutex_lock(thread->suspendmutex);
1315
1316         if (!thread->suspended) {
1317                 Mutex_unlock(thread->suspendmutex);
1318                 return false;
1319         }
1320
1321         thread->suspended = false;
1322
1323         /* tell everyone that the thread should resume */
1324         assert(thread != THREADOBJECT);
1325         Condition_broadcast(thread->suspendcond);
1326
1327         /* release the suspendmutex */
1328         Mutex_unlock(thread->suspendmutex);
1329
1330         return true;
1331 }
1332 #endif
1333
1334
1335 /* threads_join_all_threads ****************************************************
1336
1337    Join all non-daemon threads.
1338
1339 *******************************************************************************/
1340
1341 void threads_join_all_threads(void)
1342 {
1343         threadobject *t;
1344
1345         /* get current thread */
1346
1347         t = THREADOBJECT;
1348
1349         /* This thread is waiting for all non-daemon threads to exit. */
1350
1351         thread_set_state_waiting(t);
1352
1353         /* enter join mutex */
1354
1355         threads_mutex_join_lock();
1356
1357         /* Wait for condition as long as we have non-daemon threads.  We
1358            compare against 1 because the current (main thread) is also a
1359            non-daemon thread. */
1360
1361         while (threadlist_get_non_daemons() > 1)
1362                 Condition_wait(cond_join, mutex_join);
1363
1364         /* leave join mutex */
1365
1366         threads_mutex_join_unlock();
1367 }
1368
1369
1370 /* threads_timespec_earlier ****************************************************
1371
1372    Return true if timespec tv1 is earlier than timespec tv2.
1373
1374    IN:
1375       tv1..........first timespec
1376           tv2..........second timespec
1377
1378    RETURN VALUE:
1379       true, if the first timespec is earlier
1380
1381 *******************************************************************************/
1382
1383 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1384                                                                                         const struct timespec *tv2)
1385 {
1386         return (tv1->tv_sec < tv2->tv_sec)
1387                                 ||
1388                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1389 }
1390
1391
1392 /* threads_current_time_is_earlier_than ****************************************
1393
1394    Check if the current time is earlier than the given timespec.
1395
1396    IN:
1397       tv...........the timespec to compare against
1398
1399    RETURN VALUE:
1400       true, if the current time is earlier
1401
1402 *******************************************************************************/
1403
1404 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1405 {
1406         struct timeval tvnow;
1407         struct timespec tsnow;
1408
1409         /* get current time */
1410
1411         if (gettimeofday(&tvnow, NULL) != 0)
1412                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1413
1414         /* convert it to a timespec */
1415
1416         tsnow.tv_sec = tvnow.tv_sec;
1417         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1418
1419         /* compare current time with the given timespec */
1420
1421         return threads_timespec_earlier(&tsnow, tv);
1422 }
1423
1424
1425 /* threads_wait_with_timeout ***************************************************
1426
1427    Wait until the given point in time on a monitor until either
1428    we are notified, we are interrupted, or the time is up.
1429
1430    IN:
1431       t............the current thread
1432           wakeupTime...absolute (latest) wakeup time
1433                            If both tv_sec and tv_nsec are zero, this function
1434                                            waits for an unlimited amount of time.
1435
1436 *******************************************************************************/
1437
1438 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1439 {
1440         /* acquire the waitmutex */
1441
1442         Mutex_lock(t->waitmutex);
1443
1444         /* wait on waitcond */
1445
1446         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1447                 /* with timeout */
1448                 while (!t->interrupted && !t->signaled
1449                            && threads_current_time_is_earlier_than(wakeupTime))
1450                 {
1451                         thread_set_state_timed_waiting(t);
1452
1453                         Condition_timedwait(t->waitcond, t->waitmutex, wakeupTime);
1454
1455                         thread_set_state_runnable(t);
1456                 }
1457         }
1458         else {
1459                 /* no timeout */
1460                 while (!t->interrupted && !t->signaled) {
1461                         thread_set_state_waiting(t);
1462
1463                         Condition_wait(t->waitcond, t->waitmutex);
1464
1465                         thread_set_state_runnable(t);
1466                 }
1467         }
1468
1469         /* release the waitmutex */
1470
1471         Mutex_unlock(t->waitmutex);
1472 }
1473
1474
1475 /* threads_wait_with_timeout_relative ******************************************
1476
1477    Wait for the given maximum amount of time on a monitor until either
1478    we are notified, we are interrupted, or the time is up.
1479
1480    IN:
1481       t............the current thread
1482           millis.......milliseconds to wait
1483           nanos........nanoseconds to wait
1484
1485 *******************************************************************************/
1486
1487 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1488                                                                                 s4 nanos)
1489 {
1490         struct timespec wakeupTime;
1491
1492         /* calculate the the (latest) wakeup time */
1493
1494         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1495
1496         /* wait */
1497
1498         threads_wait_with_timeout(thread, &wakeupTime);
1499 }
1500
1501
1502 /* threads_calc_absolute_time **************************************************
1503
1504    Calculate the absolute point in time a given number of ms and ns from now.
1505
1506    IN:
1507       millis............milliseconds from now
1508           nanos.............nanoseconds from now
1509
1510    OUT:
1511       *tm...............receives the timespec of the absolute point in time
1512
1513 *******************************************************************************/
1514
1515 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1516 {
1517         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1518                 struct timeval tv;
1519                 long nsec;
1520                 gettimeofday(&tv, NULL);
1521                 tv.tv_sec += millis / 1000;
1522                 millis %= 1000;
1523                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1524                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1525                 tm->tv_nsec = nsec % 1000000000;
1526         }
1527         else {
1528                 tm->tv_sec = 0;
1529                 tm->tv_nsec = 0;
1530         }
1531 }
1532
1533
1534 /* threads_thread_interrupt ****************************************************
1535
1536    Interrupt the given thread.
1537
1538    The thread gets the "waitcond" signal and 
1539    its interrupted flag is set to true.
1540
1541    IN:
1542       thread............the thread to interrupt
1543
1544 *******************************************************************************/
1545
1546 void threads_thread_interrupt(threadobject *thread)
1547 {
1548 #if defined(__LINUX__) && defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1549         /* See openjdk/jdk/src/solaris/native/java/net/linux_close.c, "sigWakeup" */
1550         int sig = (__SIGRTMAX - 2);
1551 #else
1552         int sig = SIGHUP;
1553 #endif
1554         /* Signal the thread a "waitcond" and tell it that it has been
1555            interrupted. */
1556
1557         Mutex_lock(thread->waitmutex);
1558
1559         DEBUGTHREADS("interrupted", thread);
1560
1561         /* Interrupt blocking system call using a signal. */
1562
1563         pthread_kill(thread->tid, sig);
1564
1565         Condition_signal(thread->waitcond);
1566
1567         thread->interrupted = true;
1568
1569         Mutex_unlock(thread->waitmutex);
1570 }
1571
1572
1573 /* threads_sleep ***************************************************************
1574
1575    Sleep the current thread for the specified amount of time.
1576
1577 *******************************************************************************/
1578
1579 void threads_sleep(int64_t millis, int32_t nanos)
1580 {
1581         threadobject    *t;
1582         struct timespec  wakeupTime;
1583         bool             interrupted;
1584
1585         if (millis < 0) {
1586 /*              exceptions_throw_illegalargumentexception("timeout value is negative"); */
1587                 exceptions_throw_illegalargumentexception();
1588                 return;
1589         }
1590
1591         t = thread_get_current();
1592
1593         if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1594                 /* Clear interrupted flag (Mauve test:
1595                    gnu/testlet/java/lang/Thread/interrupt). */
1596
1597                 thread_set_interrupted(t, false);
1598
1599 /*              exceptions_throw_interruptedexception("sleep interrupted"); */
1600                 exceptions_throw_interruptedexception();
1601                 return;
1602         }
1603
1604         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1605
1606         threads_wait_with_timeout(t, &wakeupTime);
1607
1608         interrupted = thread_is_interrupted(t);
1609
1610         if (interrupted) {
1611                 thread_set_interrupted(t, false);
1612
1613                 /* An other exception could have been thrown
1614                    (e.g. ThreadDeathException). */
1615
1616                 if (!exceptions_get_exception())
1617                         exceptions_throw_interruptedexception();
1618         }
1619 }
1620
1621
1622 /* threads_yield ***************************************************************
1623
1624    Yield to the scheduler.
1625
1626 *******************************************************************************/
1627
1628 void threads_yield(void)
1629 {
1630         sched_yield();
1631 }
1632
1633 #if defined(ENABLE_TLH)
1634
1635 void threads_tlh_add_frame() {
1636         tlh_add_frame(&(THREADOBJECT->tlh));
1637 }
1638
1639 void threads_tlh_remove_frame() {
1640         tlh_remove_frame(&(THREADOBJECT->tlh));
1641 }
1642
1643 #endif
1644
1645 /*
1646  * These are local overrides for various environment variables in Emacs.
1647  * Please do not remove this and leave it at the end of the file, where
1648  * Emacs will automagically detect them.
1649  * ---------------------------------------------------------------------
1650  * Local variables:
1651  * mode: c
1652  * indent-tabs-mode: t
1653  * c-basic-offset: 4
1654  * tab-width: 4
1655  * End:
1656  * vim:noexpandtab:sw=4:ts=4:
1657  */