1 /* src/threads/posix/thread-posix.cpp - POSIX thread functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
28 /* XXX cleanup these includes */
33 #include <sys/types.h>
46 #include "mm/memory.h"
48 #if defined(ENABLE_GC_CACAO)
49 # include "mm/cacao-gc/gc.h"
52 #include "native/jni.h"
53 #include "native/llni.h"
54 #include "native/native.h"
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"
61 #if defined(ENABLE_JAVASE)
62 # include "native/include/java_lang_ThreadGroup.h"
65 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
66 # include "native/include/java_lang_VMThread.h"
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"
75 #include "toolbox/logging.h"
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"
84 #include "vm/jit/asmpart.h"
86 #include "vmcore/globals.hpp"
87 #include "vmcore/options.h"
89 #if defined(ENABLE_STATISTICS)
90 # include "vmcore/statistics.h"
93 #if !defined(__DARWIN__)
94 # include <semaphore.h>
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
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"
111 #if defined(ENABLE_JVMTI)
112 #include "native/jvmti/cacaodbg.h"
116 // FIXME For now we export everything as C functions.
119 #if defined(__DARWIN__)
120 /* Darwin has no working semaphore implementation. This one is taken
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.
130 static int sem_init(sem_t *sem, int pshared, int value)
135 sem->mutex = new Mutex();
136 sem->cond = new Condition();
142 static int sem_post(sem_t *sem)
147 sem->mutex->unlock();
152 static int sem_wait(sem_t *sem)
156 while (sem->value == 0) {
157 sem->cond->wait(sem->mutex);
161 sem->mutex->unlock();
166 static int sem_destroy(sem_t *sem)
173 #endif /* defined(__DARWIN__) */
176 /* startupinfo *****************************************************************
178 Struct used to pass info from threads_start_thread to
179 threads_startup_thread.
181 ******************************************************************************/
184 threadobject *thread; /* threadobject for this thread */
185 functionptr function; /* function to run in the new thread */
186 sem_t *psem; /* signals when thread has been entered */
187 /* in the thread list */
188 sem_t *psem_first; /* signals when pthread_create has returned */
192 /* prototypes *****************************************************************/
194 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
197 /******************************************************************************/
198 /* GLOBAL VARIABLES */
199 /******************************************************************************/
201 /* the thread object of the current thread */
202 /* This is either a thread-local variable defined with __thread, or */
203 /* a thread-specific value stored with key threads_current_threadobject_key. */
204 #if defined(HAVE___THREAD)
205 __thread threadobject *thread_current;
207 pthread_key_t thread_current_key;
210 /* global mutex for stop-the-world */
211 static Mutex* stopworldlock;
213 #if defined(ENABLE_GC_CACAO)
214 /* global mutex for the GC */
215 static Mutex* mutex_gc;
218 /* global mutex and condition for joining threads on exit */
219 static Mutex* mutex_join;
220 static Condition* cond_join;
222 #if defined(ENABLE_GC_CACAO)
223 /* semaphore used for acknowleding thread suspension */
224 static sem_t suspend_ack;
228 /* threads_sem_init ************************************************************
230 Initialize a semaphore. Checks against errors and interruptions.
233 sem..............the semaphore to initialize
234 shared...........true if this semaphore will be shared between processes
235 value............the initial value for the semaphore
237 *******************************************************************************/
239 void threads_sem_init(sem_t *sem, bool shared, int value)
246 r = sem_init(sem, shared, value);
249 } while (errno == EINTR);
251 vm_abort("sem_init failed: %s", strerror(errno));
255 /* threads_sem_wait ************************************************************
257 Wait for a semaphore, non-interruptible.
259 IMPORTANT: Always use this function instead of `sem_wait` directly, as
260 `sem_wait` may be interrupted by signals!
263 sem..............the semaphore to wait on
265 *******************************************************************************/
267 void threads_sem_wait(sem_t *sem)
277 } while (errno == EINTR);
279 vm_abort("sem_wait failed: %s", strerror(errno));
283 /* threads_sem_post ************************************************************
285 Increase the count of a semaphore. Checks for errors.
288 sem..............the semaphore to increase the count of
290 *******************************************************************************/
292 void threads_sem_post(sem_t *sem)
298 /* unlike sem_wait, sem_post is not interruptible */
304 vm_abort("sem_post failed: %s", strerror(errno));
308 /* threads_stopworld ***********************************************************
310 Stops the world from turning. All threads except the calling one
311 are suspended. The function returns as soon as all threads have
312 acknowledged their suspension.
314 *******************************************************************************/
316 #if defined(ENABLE_GC_CACAO)
317 void threads_stopworld(void)
319 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
326 stopworldlock->lock();
328 /* lock the threads lists */
332 #if defined(__DARWIN__)
333 /*threads_cast_darwinstop();*/
335 #elif defined(__CYGWIN__)
341 DEBUGTHREADS("stops World", self);
345 /* suspend all running threads */
346 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
347 /* don't send the signal to ourself */
352 /* don't send the signal to NEW threads (because they are not
353 completely initialized) */
355 if (t->state == THREAD_STATE_NEW)
358 /* send the signal */
360 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
363 /* increase threads count */
368 /* wait for all threads signaled to suspend */
369 for (i = 0; i < count; i++)
370 threads_sem_wait(&suspend_ack);
373 /* ATTENTION: Don't unlock the threads-lists here so that
374 non-signaled NEW threads can't change their state and execute
380 /* threads_startworld **********************************************************
382 Starts the world again after it has previously been stopped.
384 *******************************************************************************/
386 #if defined(ENABLE_GC_CACAO)
387 void threads_startworld(void)
389 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
396 #if defined(__DARWIN__)
397 /*threads_cast_darwinresume();*/
399 #elif defined(__IRIX__)
400 threads_cast_irixresume();
401 #elif defined(__CYGWIN__)
407 DEBUGTHREADS("starts World", self);
411 /* resume all thread we haltet */
412 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
413 /* don't send the signal to ourself */
418 /* don't send the signal to NEW threads (because they are not
419 completely initialized) */
421 if (t->state == THREAD_STATE_NEW)
424 /* send the signal */
426 result = threads_resume_thread(t);
429 /* increase threads count */
434 /* wait for all threads signaled to suspend */
435 for (i = 0; i < count; i++)
436 threads_sem_wait(&suspend_ack);
440 /* unlock the threads lists */
444 stopworldlock->unlock();
449 /* threads_impl_thread_init ****************************************************
451 Initialize OS-level locking constructs in threadobject.
454 t....the threadobject
456 *******************************************************************************/
458 void threads_impl_thread_init(threadobject *t)
460 /* initialize the mutex and the condition */
462 t->flc_lock = new Mutex();
463 t->flc_cond = new Condition();
465 t->waitmutex = new Mutex();
466 t->waitcond = new Condition();
468 t->suspendmutex = new Mutex();
469 t->suspendcond = new Condition();
471 #if defined(ENABLE_TLH)
476 /* threads_impl_thread_clear ***************************************************
478 Clears all fields in threadobject the way an MZERO would have
479 done. MZERO cannot be used anymore because it would mess up the
483 t....the threadobject
485 *******************************************************************************/
487 void threads_impl_thread_clear(threadobject *t)
499 #if defined(__DARWIN__)
503 t->interrupted = false;
506 t->suspended = false;
507 t->suspend_reason = 0;
511 t->_exceptionptr = NULL;
512 t->_stackframeinfo = NULL;
513 t->_localref_table = NULL;
515 #if defined(ENABLE_INTRP)
516 t->_global_sp = NULL;
519 #if defined(ENABLE_GC_CACAO)
520 t->gc_critical = false;
526 MZERO(&t->dumpinfo, dumpinfo_t, 1);
529 /* threads_impl_thread_reuse ***************************************************
531 Resets some implementation fields in threadobject. This was
532 previously done in threads_impl_thread_new.
535 t....the threadobject
537 *******************************************************************************/
539 void threads_impl_thread_reuse(threadobject *t)
541 /* get the pthread id */
543 t->tid = pthread_self();
545 #if defined(ENABLE_DEBUG_FILTER)
546 /* Initialize filter counters */
547 t->filterverbosecallctr[0] = 0;
548 t->filterverbosecallctr[1] = 0;
552 t->tracejavacallindent = 0;
553 t->tracejavacallcount = 0;
560 /* not really needed */
561 t->flc_object = NULL;
563 #if defined(ENABLE_TLH)
564 tlh_destroy(&(t->tlh));
570 /* threads_impl_thread_free ****************************************************
572 Cleanup thread stuff.
575 t....the threadobject
577 *******************************************************************************/
581 void threads_impl_thread_free(threadobject *t)
585 /* Destroy the mutex and the condition. */
589 result = pthread_cond_destroy(&(t->flc_cond));
592 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
596 result = pthread_cond_destroy(&(t->waitcond));
599 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
601 delete t->suspendmutex;
603 result = pthread_cond_destroy(&(t->suspendcond));
606 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
611 /* threads_impl_preinit ********************************************************
613 Do some early initialization of stuff required.
615 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
616 is called AFTER this function!
618 *******************************************************************************/
620 void threads_impl_preinit(void)
624 stopworldlock = new Mutex();
626 /* initialize exit mutex and condition (on exit we join all
629 mutex_join = new Mutex();
630 cond_join = new Condition();
632 #if defined(ENABLE_GC_CACAO)
633 /* initialize the GC mutex & suspend semaphore */
635 mutex_gc = new Mutex();
636 threads_sem_init(&suspend_ack, 0, 0);
639 #if !defined(HAVE___THREAD)
640 result = pthread_key_create(&thread_current_key, NULL);
642 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
647 /* threads_mutex_gc_lock *******************************************************
649 Enter the global GC mutex.
651 *******************************************************************************/
653 #if defined(ENABLE_GC_CACAO)
654 void threads_mutex_gc_lock(void)
661 /* threads_mutex_gc_unlock *****************************************************
663 Leave the global GC mutex.
665 *******************************************************************************/
667 #if defined(ENABLE_GC_CACAO)
668 void threads_mutex_gc_unlock(void)
674 /* threads_mutex_join_lock *****************************************************
676 Enter the join mutex.
678 *******************************************************************************/
680 void threads_mutex_join_lock(void)
686 /* threads_mutex_join_unlock ***************************************************
688 Leave the join mutex.
690 *******************************************************************************/
692 void threads_mutex_join_unlock(void)
694 mutex_join->unlock();
698 /* threads_impl_init ***********************************************************
700 Initializes the implementation specific bits.
702 *******************************************************************************/
704 void threads_impl_init(void)
709 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
711 /* Initialize the thread attribute object. */
713 result = pthread_attr_init(&attr);
716 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
718 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
721 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
725 /* threads_startup_thread ******************************************************
727 Thread startup function called by pthread_create.
729 Thread which have a startup.function != NULL are marked as internal
730 threads. All other threads are threated as normal Java threads.
732 NOTE: This function is not called directly by pthread_create. The Boehm GC
733 inserts its own GC_start_routine in between, which then calls
737 arg..........the argument passed to pthread_create, ie. a pointer to
738 a startupinfo struct. CAUTION: When the `psem` semaphore
739 is posted, the startupinfo struct becomes invalid! (It
740 is allocated on the stack of threads_start_thread.)
742 ******************************************************************************/
744 static void *threads_startup_thread(void *arg)
746 startupinfo *startup;
748 java_lang_Thread *object;
749 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
750 java_lang_VMThread *vmt;
756 functionptr function;
758 #if defined(ENABLE_GC_BOEHM)
759 # if !defined(__DARWIN__)
760 struct GC_stack_base sb;
765 #if defined(ENABLE_INTRP)
766 u1 *intrp_thread_stack;
769 #if defined(ENABLE_INTRP)
770 /* create interpreter stack */
773 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
774 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
777 intrp_thread_stack = NULL;
780 /* get passed startupinfo structure and the values in there */
782 startup = (startupinfo*) arg;
785 function = startup->function;
786 psem = startup->psem;
788 /* Seems like we've encountered a situation where thread->tid was
789 not set by pthread_create. We alleviate this problem by waiting
790 for pthread_create to return. */
792 threads_sem_wait(startup->psem_first);
794 #if defined(__DARWIN__)
795 t->mach_thread = mach_thread_self();
798 /* Now that we are in the new thread, we can store the internal
799 thread data-structure in the TSD. */
801 thread_set_current(t);
803 #if defined(ENABLE_GC_BOEHM)
804 # if defined(__DARWIN__)
805 // This is currently not implemented in Boehm-GC. Just fail silently.
807 /* Register the thread with Boehm-GC. This must happen before the
808 thread allocates any memory from the GC heap.*/
810 result = GC_get_stack_base(&sb);
813 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
815 GC_register_my_thread(&sb);
819 /* get the java.lang.Thread object for this thread */
821 object = (java_lang_Thread *) thread_get_object(t);
823 /* set our priority */
825 threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
827 /* Thread is completely initialized. */
829 thread_set_state_runnable(t);
831 /* tell threads_startup_thread that we registered ourselves */
832 /* CAUTION: *startup becomes invalid with this! */
835 threads_sem_post(psem);
837 #if defined(ENABLE_INTRP)
838 /* set interpreter stack */
841 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
844 #if defined(ENABLE_JVMTI)
845 /* fire thread start event */
848 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
851 DEBUGTHREADS("starting", t);
853 /* find and run the Thread.run()V method if no other function was passed */
855 if (function == NULL) {
856 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
857 /* We need to start the run method of
858 java.lang.VMThread. Since this is a final class, we can use
859 the class object directly. */
861 c = class_java_lang_VMThread;
862 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
863 LLNI_class_get(object, c);
865 # error unknown classpath configuration
868 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
871 vm_abort("threads_startup_thread: run() method not found in class");
873 /* set ThreadMXBean variables */
875 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
876 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
878 /* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
879 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
880 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
881 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
884 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
885 /* we need to start the run method of java.lang.VMThread */
887 LLNI_field_get_ref(object, vmThread, vmt);
888 o = (java_handle_t *) vmt;
890 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
891 o = (java_handle_t *) object;
893 # error unknown classpath configuration
896 /* Run the thread. */
898 (void) vm_call_method(m, o);
901 /* set ThreadMXBean variables */
903 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
904 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
906 /* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
907 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
908 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
909 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
912 /* call passed function, e.g. finalizer_thread */
917 DEBUGTHREADS("stopping", t);
919 #if defined(ENABLE_JVMTI)
920 /* fire thread end event */
923 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
926 /* We ignore the return value. */
928 (void) thread_detach_current_thread();
930 /* set ThreadMXBean variables */
932 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
939 /* threads_impl_thread_start ***************************************************
941 Start a thread in the JVM. Both (vm internal and java) thread
945 thread....the thread object
946 f.........function to run in the new thread. NULL means that the
947 "run" method of the object `t` should be called
949 ******************************************************************************/
951 void threads_impl_thread_start(threadobject *thread, functionptr f)
959 /* fill startupinfo structure passed by pthread_create to
960 * threads_startup_thread */
962 startup.thread = thread;
963 startup.function = f; /* maybe we don't call Thread.run()V */
965 startup.psem_first = &sem_first;
967 threads_sem_init(&sem, 0, 0);
968 threads_sem_init(&sem_first, 0, 0);
970 /* Initialize thread attributes. */
972 result = pthread_attr_init(&attr);
975 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
977 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
980 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
982 /* initialize thread stacksize */
984 result = pthread_attr_setstacksize(&attr, opt_stacksize);
987 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
989 /* create the thread */
991 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
994 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
996 /* destroy the thread attributes */
998 result = pthread_attr_destroy(&attr);
1001 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1003 /* signal that pthread_create has returned, so thread->tid is valid */
1005 threads_sem_post(&sem_first);
1007 /* wait here until the thread has entered itself into the thread list */
1009 threads_sem_wait(&sem);
1014 sem_destroy(&sem_first);
1018 /* threads_set_thread_priority *************************************************
1020 Set the priority of the given thread.
1023 tid..........thread id
1024 priority.....priority to set
1026 ******************************************************************************/
1028 void threads_set_thread_priority(pthread_t tid, int priority)
1030 struct sched_param schedp;
1033 pthread_getschedparam(tid, &policy, &schedp);
1034 schedp.sched_priority = priority;
1035 pthread_setschedparam(tid, policy, &schedp);
1040 * Detaches the current thread from the VM.
1042 * @return true on success, false otherwise
1044 bool thread_detach_current_thread(void)
1048 java_lang_Thread *object;
1050 #if defined(ENABLE_JAVASE)
1051 java_lang_ThreadGroup *group;
1058 t = thread_get_current();
1064 /* If the given thread has already been detached, this operation
1067 result = thread_is_attached(t);
1069 if (result == false)
1072 DEBUGTHREADS("detaching", t);
1074 object = (java_lang_Thread *) thread_get_object(t);
1076 #if defined(ENABLE_JAVASE)
1077 LLNI_field_get_ref(object, group, group);
1079 /* If there's an uncaught exception, call uncaughtException on the
1080 thread's exception handler, or the thread's group if this is
1083 e = exceptions_get_and_clear_exception();
1086 /* We use the type void* for handler here, as it's not trivial
1087 to build the java_lang_Thread_UncaughtExceptionHandler
1088 header file with cacaoh. */
1090 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1091 LLNI_field_get_ref(object, exceptionHandler, handler);
1092 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1093 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1096 if (handler != NULL) {
1097 LLNI_class_get(handler, c);
1098 o = (java_handle_t *) handler;
1101 LLNI_class_get(group, c);
1102 o = (java_handle_t *) group;
1105 m = class_resolveclassmethod(c,
1106 utf_uncaughtException,
1107 utf_java_lang_Thread_java_lang_Throwable__V,
1114 (void) vm_call_method(m, o, object, e);
1116 if (exceptions_get_exception())
1120 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1122 /* Remove thread from the thread group. */
1124 if (group != NULL) {
1125 LLNI_class_get(group, c);
1127 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1128 m = class_resolveclassmethod(c,
1130 utf_java_lang_Thread__V,
1131 class_java_lang_ThreadGroup,
1133 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1134 m = class_resolveclassmethod(c,
1136 utf_java_lang_Thread__V,
1137 class_java_lang_ThreadGroup,
1140 # error unknown classpath configuration
1146 o = (java_handle_t *) group;
1148 (void) vm_call_method(m, o, object);
1150 if (exceptions_get_exception())
1153 /* Reset the threadgroup in the Java thread object (Mauve
1154 test: gnu/testlet/java/lang/Thread/getThreadGroup). */
1156 LLNI_field_set_ref(object, group, NULL);
1160 /* Thread has terminated. */
1162 thread_set_state_terminated(t);
1164 /* Notify all threads waiting on this thread. These are joining
1167 o = (java_handle_t *) object;
1169 /* XXX Care about exceptions? */
1170 (void) lock_monitor_enter(o);
1172 lock_notify_all_object(o);
1174 /* XXX Care about exceptions? */
1175 (void) lock_monitor_exit(o);
1177 /* Enter the join-mutex before calling thread_free, so
1178 threads_join_all_threads gets the correct number of non-daemon
1181 threads_mutex_join_lock();
1183 /* Free the internal thread data-structure. */
1187 /* Signal that this thread has finished and leave the mutex. */
1189 cond_join->signal();
1190 threads_mutex_join_unlock();
1196 /* threads_suspend_thread ******************************************************
1198 Suspend the passed thread. Execution stops until the thread
1199 is explicitly resumend again.
1202 reason.....Reason for suspending this thread.
1204 *******************************************************************************/
1206 bool threads_suspend_thread(threadobject *thread, s4 reason)
1208 /* acquire the suspendmutex */
1209 thread->suspendmutex->lock();
1211 if (thread->suspended) {
1212 thread->suspendmutex->unlock();
1216 /* set the reason for the suspension */
1217 thread->suspend_reason = reason;
1219 /* send the suspend signal to the thread */
1220 assert(thread != THREADOBJECT);
1221 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1222 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1225 /* REMEMBER: do not release the suspendmutex, this is done
1226 by the thread itself in threads_suspend_ack(). */
1232 /* threads_suspend_ack *********************************************************
1234 Acknowledges the suspension of the current thread.
1237 pc.....The PC where the thread suspended its execution.
1238 sp.....The SP before the thread suspended its execution.
1240 *******************************************************************************/
1242 #if defined(ENABLE_GC_CACAO)
1243 void threads_suspend_ack(u1* pc, u1* sp)
1245 threadobject *thread;
1247 thread = THREADOBJECT;
1249 assert(thread->suspend_reason != 0);
1251 /* TODO: remember dump memory size */
1253 /* inform the GC about the suspension */
1254 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1256 /* check if the GC wants to leave the thread running */
1257 if (!gc_suspend(thread, pc, sp)) {
1259 /* REMEMBER: we do not unlock the suspendmutex because the thread
1260 will suspend itself again at a later time */
1266 /* mark this thread as suspended and remember the PC */
1268 thread->suspended = true;
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);
1275 DEBUGTHREADS("suspending", thread);
1277 /* release the suspension mutex and wait till we are resumed */
1278 thread->suspendcond->wait(thread->suspendmutex);
1280 DEBUGTHREADS("resuming", thread);
1282 /* if we are stopping the world, we should send a global ack */
1283 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1284 threads_sem_post(&suspend_ack);
1287 /* TODO: free dump memory */
1289 /* release the suspendmutex */
1290 thread->suspendmutex->unlock();
1295 /* threads_resume_thread *******************************************************
1297 Resumes the execution of the passed thread.
1299 *******************************************************************************/
1301 #if defined(ENABLE_GC_CACAO)
1302 bool threads_resume_thread(threadobject *thread)
1304 /* acquire the suspendmutex */
1305 thread->suspendmutex->lock();
1307 if (!thread->suspended) {
1308 thread->suspendmutex->unlock();
1312 thread->suspended = false;
1314 /* tell everyone that the thread should resume */
1315 assert(thread != THREADOBJECT);
1316 thread->suspendcond->broadcast();
1318 /* release the suspendmutex */
1319 thread->suspendmutex->unlock();
1326 /* threads_join_all_threads ****************************************************
1328 Join all non-daemon threads.
1330 *******************************************************************************/
1332 void threads_join_all_threads(void)
1336 /* get current thread */
1340 /* This thread is waiting for all non-daemon threads to exit. */
1342 thread_set_state_waiting(t);
1344 /* enter join mutex */
1346 threads_mutex_join_lock();
1348 /* Wait for condition as long as we have non-daemon threads. We
1349 compare against 1 because the current (main thread) is also a
1350 non-daemon thread. */
1352 while (threadlist_get_non_daemons() > 1)
1353 cond_join->wait(mutex_join);
1355 /* leave join mutex */
1357 threads_mutex_join_unlock();
1361 /* threads_timespec_earlier ****************************************************
1363 Return true if timespec tv1 is earlier than timespec tv2.
1366 tv1..........first timespec
1367 tv2..........second timespec
1370 true, if the first timespec is earlier
1372 *******************************************************************************/
1374 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1375 const struct timespec *tv2)
1377 return (tv1->tv_sec < tv2->tv_sec)
1379 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1383 /* threads_current_time_is_earlier_than ****************************************
1385 Check if the current time is earlier than the given timespec.
1388 tv...........the timespec to compare against
1391 true, if the current time is earlier
1393 *******************************************************************************/
1395 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1397 struct timeval tvnow;
1398 struct timespec tsnow;
1400 /* get current time */
1402 if (gettimeofday(&tvnow, NULL) != 0)
1403 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1405 /* convert it to a timespec */
1407 tsnow.tv_sec = tvnow.tv_sec;
1408 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1410 /* compare current time with the given timespec */
1412 return threads_timespec_earlier(&tsnow, tv);
1416 /* threads_wait_with_timeout ***************************************************
1418 Wait until the given point in time on a monitor until either
1419 we are notified, we are interrupted, or the time is up.
1422 t............the current thread
1423 wakeupTime...absolute (latest) wakeup time
1424 If both tv_sec and tv_nsec are zero, this function
1425 waits for an unlimited amount of time.
1427 *******************************************************************************/
1429 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1431 // Acquire the waitmutex.
1432 t->waitmutex->lock();
1434 /* wait on waitcond */
1436 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1438 while (!t->interrupted && !t->signaled
1439 && threads_current_time_is_earlier_than(wakeupTime))
1441 thread_set_state_timed_waiting(t);
1443 t->waitcond->timedwait(t->waitmutex, wakeupTime);
1445 thread_set_state_runnable(t);
1450 while (!t->interrupted && !t->signaled) {
1451 thread_set_state_waiting(t);
1453 t->waitcond->wait(t->waitmutex);
1455 thread_set_state_runnable(t);
1459 // Release the waitmutex.
1460 t->waitmutex->unlock();
1464 /* threads_wait_with_timeout_relative ******************************************
1466 Wait for the given maximum amount of time on a monitor until either
1467 we are notified, we are interrupted, or the time is up.
1470 t............the current thread
1471 millis.......milliseconds to wait
1472 nanos........nanoseconds to wait
1474 *******************************************************************************/
1476 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1479 struct timespec wakeupTime;
1481 /* calculate the the (latest) wakeup time */
1483 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1487 threads_wait_with_timeout(thread, &wakeupTime);
1491 /* threads_calc_absolute_time **************************************************
1493 Calculate the absolute point in time a given number of ms and ns from now.
1496 millis............milliseconds from now
1497 nanos.............nanoseconds from now
1500 *tm...............receives the timespec of the absolute point in time
1502 *******************************************************************************/
1504 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1506 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1509 gettimeofday(&tv, NULL);
1510 tv.tv_sec += millis / 1000;
1512 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1513 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1514 tm->tv_nsec = nsec % 1000000000;
1523 /* threads_thread_interrupt ****************************************************
1525 Interrupt the given thread.
1527 The thread gets the "waitcond" signal and
1528 its interrupted flag is set to true.
1531 thread............the thread to interrupt
1533 *******************************************************************************/
1535 void threads_thread_interrupt(threadobject *t)
1537 /* Signal the thread a "waitcond" and tell it that it has been
1540 t->waitmutex->lock();
1542 DEBUGTHREADS("interrupted", t);
1544 /* Interrupt blocking system call using a signal. */
1546 pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL);
1548 t->waitcond->signal();
1550 t->interrupted = true;
1552 t->waitmutex->unlock();
1557 * Sleep the current thread for the specified amount of time.
1559 * @param millis Milliseconds to sleep.
1560 * @param nanos Nanoseconds to sleep.
1562 void threads_sleep(int64_t millis, int32_t nanos)
1565 struct timespec wakeupTime;
1569 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1570 exceptions_throw_illegalargumentexception();
1574 t = thread_get_current();
1576 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1577 /* Clear interrupted flag (Mauve test:
1578 gnu/testlet/java/lang/Thread/interrupt). */
1580 thread_set_interrupted(t, false);
1582 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1583 exceptions_throw_interruptedexception();
1587 // (Note taken from classpath/vm/reference/java/lang/VMThread.java (sleep))
1588 // Note: JDK treats a zero length sleep is like Thread.yield(),
1589 // without checking the interrupted status of the thread. It's
1590 // unclear if this is a bug in the implementation or the spec.
1591 // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 */
1592 if (millis == 0 && nanos == 0) {
1596 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1598 threads_wait_with_timeout(t, &wakeupTime);
1600 interrupted = thread_is_interrupted(t);
1603 thread_set_interrupted(t, false);
1605 // An other exception could have been thrown
1606 // (e.g. ThreadDeathException).
1607 if (!exceptions_get_exception())
1608 exceptions_throw_interruptedexception();
1614 /* threads_yield ***************************************************************
1616 Yield to the scheduler.
1618 *******************************************************************************/
1620 void threads_yield(void)
1625 #if defined(ENABLE_TLH)
1627 void threads_tlh_add_frame() {
1628 tlh_add_frame(&(THREADOBJECT->tlh));
1631 void threads_tlh_remove_frame() {
1632 tlh_remove_frame(&(THREADOBJECT->tlh));
1641 * These are local overrides for various environment variables in Emacs.
1642 * Please do not remove this and leave it at the end of the file, where
1643 * Emacs will automagically detect them.
1644 * ---------------------------------------------------------------------
1647 * indent-tabs-mode: t
1651 * vim:noexpandtab:sw=4:ts=4: