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