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