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>
47 #include "mm/memory.h"
49 #if defined(ENABLE_GC_CACAO)
50 # include "mm/cacao-gc/gc.h"
53 #include "native/jni.h"
54 #include "native/llni.h"
55 #include "native/native.h"
57 #include "native/include/java_lang_Object.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
60 #include "native/include/java_lang_Thread.h"
62 #if defined(ENABLE_JAVASE)
63 # include "native/include/java_lang_ThreadGroup.h"
66 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
67 # include "native/include/java_lang_VMThread.h"
70 #include "threads/condition.hpp"
71 #include "threads/lock-common.h"
72 #include "threads/mutex.hpp"
73 #include "threads/threadlist.h"
74 #include "threads/thread.hpp"
76 #include "toolbox/logging.h"
78 #include "vm/builtin.h"
79 #include "vm/exceptions.hpp"
80 #include "vm/global.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)
137 sem->mutex = new Mutex();
139 if (pthread_cond_init(&sem->cond, NULL) < 0)
145 static int sem_post(sem_t *sem)
151 if (pthread_cond_signal(&sem->cond) < 0) {
152 sem->mutex->unlock();
156 sem->mutex->unlock();
161 static int sem_wait(sem_t *sem)
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);
172 sem->mutex->unlock();
177 static int sem_destroy(sem_t *sem)
179 if (pthread_cond_destroy(&sem->cond) < 0)
186 #endif /* defined(__DARWIN__) */
189 /* startupinfo *****************************************************************
191 Struct used to pass info from threads_start_thread to
192 threads_startup_thread.
194 ******************************************************************************/
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 */
205 /* prototypes *****************************************************************/
207 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
210 /******************************************************************************/
211 /* GLOBAL VARIABLES */
212 /******************************************************************************/
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;
220 pthread_key_t thread_current_key;
223 /* global mutex for stop-the-world */
224 static Mutex* stopworldlock;
226 #if defined(ENABLE_GC_CACAO)
227 /* global mutex for the GC */
228 static Mutex* mutex_gc;
231 /* global mutex and condition for joining threads on exit */
232 static Mutex* mutex_join;
233 static Condition* cond_join;
235 #if defined(ENABLE_GC_CACAO)
236 /* semaphore used for acknowleding thread suspension */
237 static sem_t suspend_ack;
241 /* threads_sem_init ************************************************************
243 Initialize a semaphore. Checks against errors and interruptions.
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
250 *******************************************************************************/
252 void threads_sem_init(sem_t *sem, bool shared, int value)
259 r = sem_init(sem, shared, value);
262 } while (errno == EINTR);
264 vm_abort("sem_init failed: %s", strerror(errno));
268 /* threads_sem_wait ************************************************************
270 Wait for a semaphore, non-interruptible.
272 IMPORTANT: Always use this function instead of `sem_wait` directly, as
273 `sem_wait` may be interrupted by signals!
276 sem..............the semaphore to wait on
278 *******************************************************************************/
280 void threads_sem_wait(sem_t *sem)
290 } while (errno == EINTR);
292 vm_abort("sem_wait failed: %s", strerror(errno));
296 /* threads_sem_post ************************************************************
298 Increase the count of a semaphore. Checks for errors.
301 sem..............the semaphore to increase the count of
303 *******************************************************************************/
305 void threads_sem_post(sem_t *sem)
311 /* unlike sem_wait, sem_post is not interruptible */
317 vm_abort("sem_post failed: %s", strerror(errno));
321 /* threads_stopworld ***********************************************************
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.
327 *******************************************************************************/
329 #if defined(ENABLE_GC_CACAO)
330 void threads_stopworld(void)
332 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
339 stopworldlock->lock();
341 /* lock the threads lists */
345 #if defined(__DARWIN__)
346 /*threads_cast_darwinstop();*/
348 #elif defined(__CYGWIN__)
354 DEBUGTHREADS("stops World", self);
358 /* suspend all running threads */
359 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
360 /* don't send the signal to ourself */
365 /* don't send the signal to NEW threads (because they are not
366 completely initialized) */
368 if (t->state == THREAD_STATE_NEW)
371 /* send the signal */
373 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
376 /* increase threads count */
381 /* wait for all threads signaled to suspend */
382 for (i = 0; i < count; i++)
383 threads_sem_wait(&suspend_ack);
386 /* ATTENTION: Don't unlock the threads-lists here so that
387 non-signaled NEW threads can't change their state and execute
393 /* threads_startworld **********************************************************
395 Starts the world again after it has previously been stopped.
397 *******************************************************************************/
399 #if defined(ENABLE_GC_CACAO)
400 void threads_startworld(void)
402 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
409 #if defined(__DARWIN__)
410 /*threads_cast_darwinresume();*/
412 #elif defined(__IRIX__)
413 threads_cast_irixresume();
414 #elif defined(__CYGWIN__)
420 DEBUGTHREADS("starts World", self);
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 */
431 /* don't send the signal to NEW threads (because they are not
432 completely initialized) */
434 if (t->state == THREAD_STATE_NEW)
437 /* send the signal */
439 result = threads_resume_thread(t);
442 /* increase threads count */
447 /* wait for all threads signaled to suspend */
448 for (i = 0; i < count; i++)
449 threads_sem_wait(&suspend_ack);
453 /* unlock the threads lists */
457 stopworldlock->unlock();
462 /* threads_impl_thread_init ****************************************************
464 Initialize OS-level locking constructs in threadobject.
467 t....the threadobject
469 *******************************************************************************/
471 void threads_impl_thread_init(threadobject *t)
473 /* initialize the mutex and the condition */
475 t->flc_lock = new Mutex();
476 t->flc_cond = new Condition();
478 t->waitmutex = new Mutex();
479 t->waitcond = new Condition();
481 t->suspendmutex = new Mutex();
482 t->suspendcond = new Condition();
484 #if defined(ENABLE_TLH)
489 /* threads_impl_thread_clear ***************************************************
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
496 t....the threadobject
498 *******************************************************************************/
500 void threads_impl_thread_clear(threadobject *t)
512 #if defined(__DARWIN__)
516 t->interrupted = false;
519 t->suspended = false;
520 t->suspend_reason = 0;
524 t->_exceptionptr = NULL;
525 t->_stackframeinfo = NULL;
526 t->_localref_table = NULL;
528 #if defined(ENABLE_INTRP)
529 t->_global_sp = NULL;
532 #if defined(ENABLE_GC_CACAO)
533 t->gc_critical = false;
539 MZERO(&t->dumpinfo, dumpinfo_t, 1);
542 /* threads_impl_thread_reuse ***************************************************
544 Resets some implementation fields in threadobject. This was
545 previously done in threads_impl_thread_new.
548 t....the threadobject
550 *******************************************************************************/
552 void threads_impl_thread_reuse(threadobject *t)
554 /* get the pthread id */
556 t->tid = pthread_self();
558 #if defined(ENABLE_DEBUG_FILTER)
559 /* Initialize filter counters */
560 t->filterverbosecallctr[0] = 0;
561 t->filterverbosecallctr[1] = 0;
565 t->tracejavacallindent = 0;
566 t->tracejavacallcount = 0;
573 /* not really needed */
574 t->flc_object = NULL;
576 #if defined(ENABLE_TLH)
577 tlh_destroy(&(t->tlh));
583 /* threads_impl_thread_free ****************************************************
585 Cleanup thread stuff.
588 t....the threadobject
590 *******************************************************************************/
594 void threads_impl_thread_free(threadobject *t)
598 /* Destroy the mutex and the condition. */
602 result = pthread_cond_destroy(&(t->flc_cond));
605 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
609 result = pthread_cond_destroy(&(t->waitcond));
612 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
614 delete t->suspendmutex;
616 result = pthread_cond_destroy(&(t->suspendcond));
619 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
624 /* threads_impl_preinit ********************************************************
626 Do some early initialization of stuff required.
628 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
629 is called AFTER this function!
631 *******************************************************************************/
633 void threads_impl_preinit(void)
637 stopworldlock = new Mutex();
639 /* initialize exit mutex and condition (on exit we join all
642 mutex_join = new Mutex();
643 cond_join = new Condition();
645 #if defined(ENABLE_GC_CACAO)
646 /* initialize the GC mutex & suspend semaphore */
648 mutex_gc = new Mutex();
649 threads_sem_init(&suspend_ack, 0, 0);
652 #if !defined(HAVE___THREAD)
653 result = pthread_key_create(&thread_current_key, NULL);
655 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
660 /* threads_mutex_gc_lock *******************************************************
662 Enter the global GC mutex.
664 *******************************************************************************/
666 #if defined(ENABLE_GC_CACAO)
667 void threads_mutex_gc_lock(void)
674 /* threads_mutex_gc_unlock *****************************************************
676 Leave the global GC mutex.
678 *******************************************************************************/
680 #if defined(ENABLE_GC_CACAO)
681 void threads_mutex_gc_unlock(void)
687 /* threads_mutex_join_lock *****************************************************
689 Enter the join mutex.
691 *******************************************************************************/
693 void threads_mutex_join_lock(void)
699 /* threads_mutex_join_unlock ***************************************************
701 Leave the join mutex.
703 *******************************************************************************/
705 void threads_mutex_join_unlock(void)
707 mutex_join->unlock();
711 /* threads_impl_init ***********************************************************
713 Initializes the implementation specific bits.
715 *******************************************************************************/
717 void threads_impl_init(void)
722 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
724 /* Initialize the thread attribute object. */
726 result = pthread_attr_init(&attr);
729 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
731 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
734 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
738 /* threads_startup_thread ******************************************************
740 Thread startup function called by pthread_create.
742 Thread which have a startup.function != NULL are marked as internal
743 threads. All other threads are threated as normal Java threads.
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
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.)
755 ******************************************************************************/
757 static void *threads_startup_thread(void *arg)
759 startupinfo *startup;
761 java_lang_Thread *object;
762 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
763 java_lang_VMThread *vmt;
769 functionptr function;
771 #if defined(ENABLE_GC_BOEHM)
772 # if !defined(__DARWIN__)
773 struct GC_stack_base sb;
778 #if defined(ENABLE_INTRP)
779 u1 *intrp_thread_stack;
782 #if defined(ENABLE_INTRP)
783 /* create interpreter stack */
786 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
787 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
790 intrp_thread_stack = NULL;
793 /* get passed startupinfo structure and the values in there */
795 startup = (startupinfo*) arg;
798 function = startup->function;
799 psem = startup->psem;
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. */
805 threads_sem_wait(startup->psem_first);
807 #if defined(__DARWIN__)
808 t->mach_thread = mach_thread_self();
811 /* Now that we are in the new thread, we can store the internal
812 thread data-structure in the TSD. */
814 thread_set_current(t);
816 #if defined(ENABLE_GC_BOEHM)
817 # if defined(__DARWIN__)
818 // This is currently not implemented in Boehm-GC. Just fail silently.
820 /* Register the thread with Boehm-GC. This must happen before the
821 thread allocates any memory from the GC heap.*/
823 result = GC_get_stack_base(&sb);
826 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
828 GC_register_my_thread(&sb);
832 /* get the java.lang.Thread object for this thread */
834 object = (java_lang_Thread *) thread_get_object(t);
836 /* set our priority */
838 threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
840 /* Thread is completely initialized. */
842 thread_set_state_runnable(t);
844 /* tell threads_startup_thread that we registered ourselves */
845 /* CAUTION: *startup becomes invalid with this! */
848 threads_sem_post(psem);
850 #if defined(ENABLE_INTRP)
851 /* set interpreter stack */
854 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
857 #if defined(ENABLE_JVMTI)
858 /* fire thread start event */
861 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
864 DEBUGTHREADS("starting", t);
866 /* find and run the Thread.run()V method if no other function was passed */
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. */
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);
878 # error unknown classpath configuration
881 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
884 vm_abort("threads_startup_thread: run() method not found in class");
886 /* set ThreadMXBean variables */
888 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
889 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
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; */
897 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
898 /* we need to start the run method of java.lang.VMThread */
900 LLNI_field_get_ref(object, vmThread, vmt);
901 o = (java_handle_t *) vmt;
903 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
904 o = (java_handle_t *) object;
906 # error unknown classpath configuration
909 /* Run the thread. */
911 (void) vm_call_method(m, o);
914 /* set ThreadMXBean variables */
916 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
917 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
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; */
925 /* call passed function, e.g. finalizer_thread */
930 DEBUGTHREADS("stopping", t);
932 #if defined(ENABLE_JVMTI)
933 /* fire thread end event */
936 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
939 /* We ignore the return value. */
941 (void) thread_detach_current_thread();
943 /* set ThreadMXBean variables */
945 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
952 /* threads_impl_thread_start ***************************************************
954 Start a thread in the JVM. Both (vm internal and java) thread
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
962 ******************************************************************************/
964 void threads_impl_thread_start(threadobject *thread, functionptr f)
972 /* fill startupinfo structure passed by pthread_create to
973 * threads_startup_thread */
975 startup.thread = thread;
976 startup.function = f; /* maybe we don't call Thread.run()V */
978 startup.psem_first = &sem_first;
980 threads_sem_init(&sem, 0, 0);
981 threads_sem_init(&sem_first, 0, 0);
983 /* Initialize thread attributes. */
985 result = pthread_attr_init(&attr);
988 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
990 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
993 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
995 /* initialize thread stacksize */
997 result = pthread_attr_setstacksize(&attr, opt_stacksize);
1000 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
1002 /* create the thread */
1004 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1007 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1009 /* destroy the thread attributes */
1011 result = pthread_attr_destroy(&attr);
1014 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1016 /* signal that pthread_create has returned, so thread->tid is valid */
1018 threads_sem_post(&sem_first);
1020 /* wait here until the thread has entered itself into the thread list */
1022 threads_sem_wait(&sem);
1027 sem_destroy(&sem_first);
1031 /* threads_set_thread_priority *************************************************
1033 Set the priority of the given thread.
1036 tid..........thread id
1037 priority.....priority to set
1039 ******************************************************************************/
1041 void threads_set_thread_priority(pthread_t tid, int priority)
1043 struct sched_param schedp;
1046 pthread_getschedparam(tid, &policy, &schedp);
1047 schedp.sched_priority = priority;
1048 pthread_setschedparam(tid, policy, &schedp);
1053 * Detaches the current thread from the VM.
1055 * @return true on success, false otherwise
1057 bool thread_detach_current_thread(void)
1061 java_lang_Thread *object;
1063 #if defined(ENABLE_JAVASE)
1064 java_lang_ThreadGroup *group;
1071 t = thread_get_current();
1077 /* If the given thread has already been detached, this operation
1080 result = thread_is_attached(t);
1082 if (result == false)
1085 DEBUGTHREADS("detaching", t);
1087 object = (java_lang_Thread *) thread_get_object(t);
1089 #if defined(ENABLE_JAVASE)
1090 LLNI_field_get_ref(object, group, group);
1092 /* If there's an uncaught exception, call uncaughtException on the
1093 thread's exception handler, or the thread's group if this is
1096 e = exceptions_get_and_clear_exception();
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. */
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);
1109 if (handler != NULL) {
1110 LLNI_class_get(handler, c);
1111 o = (java_handle_t *) handler;
1114 LLNI_class_get(group, c);
1115 o = (java_handle_t *) group;
1118 m = class_resolveclassmethod(c,
1119 utf_uncaughtException,
1120 utf_java_lang_Thread_java_lang_Throwable__V,
1127 (void) vm_call_method(m, o, object, e);
1129 if (exceptions_get_exception())
1133 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1135 /* Remove thread from the thread group. */
1137 if (group != NULL) {
1138 LLNI_class_get(group, c);
1140 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1141 m = class_resolveclassmethod(c,
1143 utf_java_lang_Thread__V,
1144 class_java_lang_ThreadGroup,
1146 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1147 m = class_resolveclassmethod(c,
1149 utf_java_lang_Thread__V,
1150 class_java_lang_ThreadGroup,
1153 # error unknown classpath configuration
1159 o = (java_handle_t *) group;
1161 (void) vm_call_method(m, o, object);
1163 if (exceptions_get_exception())
1166 /* Reset the threadgroup in the Java thread object (Mauve
1167 test: gnu/testlet/java/lang/Thread/getThreadGroup). */
1169 LLNI_field_set_ref(object, group, NULL);
1173 /* Thread has terminated. */
1175 thread_set_state_terminated(t);
1177 /* Notify all threads waiting on this thread. These are joining
1180 o = (java_handle_t *) object;
1182 /* XXX Care about exceptions? */
1183 (void) lock_monitor_enter(o);
1185 lock_notify_all_object(o);
1187 /* XXX Care about exceptions? */
1188 (void) lock_monitor_exit(o);
1190 /* Enter the join-mutex before calling thread_free, so
1191 threads_join_all_threads gets the correct number of non-daemon
1194 threads_mutex_join_lock();
1196 /* Free the internal thread data-structure. */
1200 /* Signal that this thread has finished and leave the mutex. */
1202 cond_join->signal();
1203 threads_mutex_join_unlock();
1209 /* threads_suspend_thread ******************************************************
1211 Suspend the passed thread. Execution stops until the thread
1212 is explicitly resumend again.
1215 reason.....Reason for suspending this thread.
1217 *******************************************************************************/
1219 bool threads_suspend_thread(threadobject *thread, s4 reason)
1221 /* acquire the suspendmutex */
1222 thread->suspendmutex->lock();
1224 if (thread->suspended) {
1225 thread->suspendmutex->unlock();
1229 /* set the reason for the suspension */
1230 thread->suspend_reason = reason;
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",
1238 /* REMEMBER: do not release the suspendmutex, this is done
1239 by the thread itself in threads_suspend_ack(). */
1245 /* threads_suspend_ack *********************************************************
1247 Acknowledges the suspension of the current thread.
1250 pc.....The PC where the thread suspended its execution.
1251 sp.....The SP before the thread suspended its execution.
1253 *******************************************************************************/
1255 #if defined(ENABLE_GC_CACAO)
1256 void threads_suspend_ack(u1* pc, u1* sp)
1258 threadobject *thread;
1260 thread = THREADOBJECT;
1262 assert(thread->suspend_reason != 0);
1264 /* TODO: remember dump memory size */
1266 /* inform the GC about the suspension */
1267 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1269 /* check if the GC wants to leave the thread running */
1270 if (!gc_suspend(thread, pc, sp)) {
1272 /* REMEMBER: we do not unlock the suspendmutex because the thread
1273 will suspend itself again at a later time */
1279 /* mark this thread as suspended and remember the PC */
1281 thread->suspended = true;
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);
1288 DEBUGTHREADS("suspending", thread);
1290 /* release the suspension mutex and wait till we are resumed */
1291 thread->suspendcond->wait(thread->suspendmutex);
1293 DEBUGTHREADS("resuming", thread);
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);
1300 /* TODO: free dump memory */
1302 /* release the suspendmutex */
1303 thread->suspendmutex->unlock();
1308 /* threads_resume_thread *******************************************************
1310 Resumes the execution of the passed thread.
1312 *******************************************************************************/
1314 #if defined(ENABLE_GC_CACAO)
1315 bool threads_resume_thread(threadobject *thread)
1317 /* acquire the suspendmutex */
1318 thread->suspendmutex->lock();
1320 if (!thread->suspended) {
1321 thread->suspendmutex->unlock();
1325 thread->suspended = false;
1327 /* tell everyone that the thread should resume */
1328 assert(thread != THREADOBJECT);
1329 thread->suspendcond->broadcast();
1331 /* release the suspendmutex */
1332 thread->suspendmutex->unlock();
1339 /* threads_join_all_threads ****************************************************
1341 Join all non-daemon threads.
1343 *******************************************************************************/
1345 void threads_join_all_threads(void)
1349 /* get current thread */
1353 /* This thread is waiting for all non-daemon threads to exit. */
1355 thread_set_state_waiting(t);
1357 /* enter join mutex */
1359 threads_mutex_join_lock();
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. */
1365 while (threadlist_get_non_daemons() > 1)
1366 cond_join->wait(mutex_join);
1368 /* leave join mutex */
1370 threads_mutex_join_unlock();
1374 /* threads_timespec_earlier ****************************************************
1376 Return true if timespec tv1 is earlier than timespec tv2.
1379 tv1..........first timespec
1380 tv2..........second timespec
1383 true, if the first timespec is earlier
1385 *******************************************************************************/
1387 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1388 const struct timespec *tv2)
1390 return (tv1->tv_sec < tv2->tv_sec)
1392 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1396 /* threads_current_time_is_earlier_than ****************************************
1398 Check if the current time is earlier than the given timespec.
1401 tv...........the timespec to compare against
1404 true, if the current time is earlier
1406 *******************************************************************************/
1408 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1410 struct timeval tvnow;
1411 struct timespec tsnow;
1413 /* get current time */
1415 if (gettimeofday(&tvnow, NULL) != 0)
1416 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1418 /* convert it to a timespec */
1420 tsnow.tv_sec = tvnow.tv_sec;
1421 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1423 /* compare current time with the given timespec */
1425 return threads_timespec_earlier(&tsnow, tv);
1429 /* threads_wait_with_timeout ***************************************************
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.
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.
1440 *******************************************************************************/
1442 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1444 // Acquire the waitmutex.
1445 t->waitmutex->lock();
1447 /* wait on waitcond */
1449 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1451 while (!t->interrupted && !t->signaled
1452 && threads_current_time_is_earlier_than(wakeupTime))
1454 thread_set_state_timed_waiting(t);
1456 t->waitcond->timedwait(t->waitmutex, wakeupTime);
1458 thread_set_state_runnable(t);
1463 while (!t->interrupted && !t->signaled) {
1464 thread_set_state_waiting(t);
1466 t->waitcond->wait(t->waitmutex);
1468 thread_set_state_runnable(t);
1472 // Release the waitmutex.
1473 t->waitmutex->unlock();
1477 /* threads_wait_with_timeout_relative ******************************************
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.
1483 t............the current thread
1484 millis.......milliseconds to wait
1485 nanos........nanoseconds to wait
1487 *******************************************************************************/
1489 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1492 struct timespec wakeupTime;
1494 /* calculate the the (latest) wakeup time */
1496 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1500 threads_wait_with_timeout(thread, &wakeupTime);
1504 /* threads_calc_absolute_time **************************************************
1506 Calculate the absolute point in time a given number of ms and ns from now.
1509 millis............milliseconds from now
1510 nanos.............nanoseconds from now
1513 *tm...............receives the timespec of the absolute point in time
1515 *******************************************************************************/
1517 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1519 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1522 gettimeofday(&tv, NULL);
1523 tv.tv_sec += 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;
1536 /* threads_thread_interrupt ****************************************************
1538 Interrupt the given thread.
1540 The thread gets the "waitcond" signal and
1541 its interrupted flag is set to true.
1544 thread............the thread to interrupt
1546 *******************************************************************************/
1548 void threads_thread_interrupt(threadobject *t)
1550 #if defined(__LINUX__) && defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1551 /* See openjdk/jdk/src/solaris/native/java/net/linux_close.c, "sigWakeup" */
1552 int sig = (__SIGRTMAX - 2);
1556 /* Signal the thread a "waitcond" and tell it that it has been
1559 t->waitmutex->lock();
1561 DEBUGTHREADS("interrupted", t);
1563 /* Interrupt blocking system call using a signal. */
1565 pthread_kill(t->tid, sig);
1567 t->waitcond->signal();
1569 t->interrupted = true;
1571 t->waitmutex->unlock();
1575 /* threads_sleep ***************************************************************
1577 Sleep the current thread for the specified amount of time.
1579 *******************************************************************************/
1581 void threads_sleep(int64_t millis, int32_t nanos)
1584 struct timespec wakeupTime;
1588 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1589 exceptions_throw_illegalargumentexception();
1593 t = thread_get_current();
1595 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1596 /* Clear interrupted flag (Mauve test:
1597 gnu/testlet/java/lang/Thread/interrupt). */
1599 thread_set_interrupted(t, false);
1601 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1602 exceptions_throw_interruptedexception();
1606 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1608 threads_wait_with_timeout(t, &wakeupTime);
1610 interrupted = thread_is_interrupted(t);
1613 thread_set_interrupted(t, false);
1615 /* An other exception could have been thrown
1616 (e.g. ThreadDeathException). */
1618 if (!exceptions_get_exception())
1619 exceptions_throw_interruptedexception();
1624 /* threads_yield ***************************************************************
1626 Yield to the scheduler.
1628 *******************************************************************************/
1630 void threads_yield(void)
1635 #if defined(ENABLE_TLH)
1637 void threads_tlh_add_frame() {
1638 tlh_add_frame(&(THREADOBJECT->tlh));
1641 void threads_tlh_remove_frame() {
1642 tlh_remove_frame(&(THREADOBJECT->tlh));
1651 * These are local overrides for various environment variables in Emacs.
1652 * Please do not remove this and leave it at the end of the file, where
1653 * Emacs will automagically detect them.
1654 * ---------------------------------------------------------------------
1657 * indent-tabs-mode: t
1661 * vim:noexpandtab:sw=4:ts=4: