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