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