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 "threads/condition.hpp"
57 #include "threads/lock-common.h"
58 #include "threads/mutex.hpp"
59 #include "threads/threadlist.h"
60 #include "threads/thread.hpp"
62 #include "toolbox/logging.h"
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"
71 #include "vm/jit/asmpart.h"
73 #include "vmcore/globals.hpp"
74 #include "vmcore/javaobjects.hpp"
75 #include "vmcore/options.h"
77 #if defined(ENABLE_STATISTICS)
78 # include "vmcore/statistics.h"
81 #if !defined(__DARWIN__)
82 # include <semaphore.h>
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
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"
99 #if defined(ENABLE_JVMTI)
100 #include "native/jvmti/cacaodbg.h"
104 // FIXME For now we export everything as C functions.
107 #if defined(__DARWIN__)
108 /* Darwin has no working semaphore implementation. This one is taken
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.
118 static int sem_init(sem_t *sem, int pshared, int value)
125 sem->mutex = new Mutex();
127 if (pthread_cond_init(&sem->cond, NULL) < 0)
133 static int sem_post(sem_t *sem)
139 if (pthread_cond_signal(&sem->cond) < 0) {
140 sem->mutex->unlock();
144 sem->mutex->unlock();
149 static int sem_wait(sem_t *sem)
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);
160 sem->mutex->unlock();
165 static int sem_destroy(sem_t *sem)
167 if (pthread_cond_destroy(&sem->cond) < 0)
174 #endif /* defined(__DARWIN__) */
177 /* startupinfo *****************************************************************
179 Struct used to pass info from threads_start_thread to
180 threads_startup_thread.
182 ******************************************************************************/
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 */
193 /* prototypes *****************************************************************/
195 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
198 /******************************************************************************/
199 /* GLOBAL VARIABLES */
200 /******************************************************************************/
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;
208 pthread_key_t thread_current_key;
211 /* global mutex for stop-the-world */
212 static Mutex* stopworldlock;
214 #if defined(ENABLE_GC_CACAO)
215 /* global mutex for the GC */
216 static Mutex* mutex_gc;
219 /* global mutex and condition for joining threads on exit */
220 static Mutex* mutex_join;
221 static Condition* cond_join;
223 #if defined(ENABLE_GC_CACAO)
224 /* semaphore used for acknowleding thread suspension */
225 static sem_t suspend_ack;
229 /* threads_sem_init ************************************************************
231 Initialize a semaphore. Checks against errors and interruptions.
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
238 *******************************************************************************/
240 void threads_sem_init(sem_t *sem, bool shared, int value)
247 r = sem_init(sem, shared, value);
250 } while (errno == EINTR);
252 vm_abort("sem_init failed: %s", strerror(errno));
256 /* threads_sem_wait ************************************************************
258 Wait for a semaphore, non-interruptible.
260 IMPORTANT: Always use this function instead of `sem_wait` directly, as
261 `sem_wait` may be interrupted by signals!
264 sem..............the semaphore to wait on
266 *******************************************************************************/
268 void threads_sem_wait(sem_t *sem)
278 } while (errno == EINTR);
280 vm_abort("sem_wait failed: %s", strerror(errno));
284 /* threads_sem_post ************************************************************
286 Increase the count of a semaphore. Checks for errors.
289 sem..............the semaphore to increase the count of
291 *******************************************************************************/
293 void threads_sem_post(sem_t *sem)
299 /* unlike sem_wait, sem_post is not interruptible */
305 vm_abort("sem_post failed: %s", strerror(errno));
309 /* threads_stopworld ***********************************************************
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.
315 *******************************************************************************/
317 #if defined(ENABLE_GC_CACAO)
318 void threads_stopworld(void)
320 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
327 stopworldlock->lock();
329 /* lock the threads lists */
333 #if defined(__DARWIN__)
334 /*threads_cast_darwinstop();*/
336 #elif defined(__CYGWIN__)
342 DEBUGTHREADS("stops World", self);
346 /* suspend all running threads */
347 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
348 /* don't send the signal to ourself */
353 /* don't send the signal to NEW threads (because they are not
354 completely initialized) */
356 if (t->state == THREAD_STATE_NEW)
359 /* send the signal */
361 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
364 /* increase threads count */
369 /* wait for all threads signaled to suspend */
370 for (i = 0; i < count; i++)
371 threads_sem_wait(&suspend_ack);
374 /* ATTENTION: Don't unlock the threads-lists here so that
375 non-signaled NEW threads can't change their state and execute
381 /* threads_startworld **********************************************************
383 Starts the world again after it has previously been stopped.
385 *******************************************************************************/
387 #if defined(ENABLE_GC_CACAO)
388 void threads_startworld(void)
390 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
397 #if defined(__DARWIN__)
398 /*threads_cast_darwinresume();*/
400 #elif defined(__IRIX__)
401 threads_cast_irixresume();
402 #elif defined(__CYGWIN__)
408 DEBUGTHREADS("starts World", self);
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 */
419 /* don't send the signal to NEW threads (because they are not
420 completely initialized) */
422 if (t->state == THREAD_STATE_NEW)
425 /* send the signal */
427 result = threads_resume_thread(t);
430 /* increase threads count */
435 /* wait for all threads signaled to suspend */
436 for (i = 0; i < count; i++)
437 threads_sem_wait(&suspend_ack);
441 /* unlock the threads lists */
445 stopworldlock->unlock();
450 /* threads_impl_thread_init ****************************************************
452 Initialize OS-level locking constructs in threadobject.
455 t....the threadobject
457 *******************************************************************************/
459 void threads_impl_thread_init(threadobject *t)
461 /* initialize the mutex and the condition */
463 t->flc_lock = new Mutex();
464 t->flc_cond = new Condition();
466 t->waitmutex = new Mutex();
467 t->waitcond = new Condition();
469 t->suspendmutex = new Mutex();
470 t->suspendcond = new Condition();
472 #if defined(ENABLE_TLH)
477 /* threads_impl_thread_clear ***************************************************
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
484 t....the threadobject
486 *******************************************************************************/
488 void threads_impl_thread_clear(threadobject *t)
500 #if defined(__DARWIN__)
504 t->interrupted = false;
507 t->suspended = false;
508 t->suspend_reason = 0;
512 t->_exceptionptr = NULL;
513 t->_stackframeinfo = NULL;
514 t->_localref_table = NULL;
516 #if defined(ENABLE_INTRP)
517 t->_global_sp = NULL;
520 #if defined(ENABLE_GC_CACAO)
521 t->gc_critical = false;
527 MZERO(&t->dumpinfo, dumpinfo_t, 1);
530 /* threads_impl_thread_reuse ***************************************************
532 Resets some implementation fields in threadobject. This was
533 previously done in threads_impl_thread_new.
536 t....the threadobject
538 *******************************************************************************/
540 void threads_impl_thread_reuse(threadobject *t)
542 /* get the pthread id */
544 t->tid = pthread_self();
546 #if defined(ENABLE_DEBUG_FILTER)
547 /* Initialize filter counters */
548 t->filterverbosecallctr[0] = 0;
549 t->filterverbosecallctr[1] = 0;
553 t->tracejavacallindent = 0;
554 t->tracejavacallcount = 0;
561 /* not really needed */
562 t->flc_object = NULL;
564 #if defined(ENABLE_TLH)
565 tlh_destroy(&(t->tlh));
571 /* threads_impl_thread_free ****************************************************
573 Cleanup thread stuff.
576 t....the threadobject
578 *******************************************************************************/
582 void threads_impl_thread_free(threadobject *t)
586 /* Destroy the mutex and the condition. */
590 result = pthread_cond_destroy(&(t->flc_cond));
593 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
597 result = pthread_cond_destroy(&(t->waitcond));
600 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
602 delete t->suspendmutex;
604 result = pthread_cond_destroy(&(t->suspendcond));
607 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
612 /* threads_impl_preinit ********************************************************
614 Do some early initialization of stuff required.
616 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
617 is called AFTER this function!
619 *******************************************************************************/
621 void threads_impl_preinit(void)
625 stopworldlock = new Mutex();
627 /* initialize exit mutex and condition (on exit we join all
630 mutex_join = new Mutex();
631 cond_join = new Condition();
633 #if defined(ENABLE_GC_CACAO)
634 /* initialize the GC mutex & suspend semaphore */
636 mutex_gc = new Mutex();
637 threads_sem_init(&suspend_ack, 0, 0);
640 #if !defined(HAVE___THREAD)
641 result = pthread_key_create(&thread_current_key, NULL);
643 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
648 /* threads_mutex_gc_lock *******************************************************
650 Enter the global GC mutex.
652 *******************************************************************************/
654 #if defined(ENABLE_GC_CACAO)
655 void threads_mutex_gc_lock(void)
662 /* threads_mutex_gc_unlock *****************************************************
664 Leave the global GC mutex.
666 *******************************************************************************/
668 #if defined(ENABLE_GC_CACAO)
669 void threads_mutex_gc_unlock(void)
675 /* threads_mutex_join_lock *****************************************************
677 Enter the join mutex.
679 *******************************************************************************/
681 void threads_mutex_join_lock(void)
687 /* threads_mutex_join_unlock ***************************************************
689 Leave the join mutex.
691 *******************************************************************************/
693 void threads_mutex_join_unlock(void)
695 mutex_join->unlock();
699 /* threads_impl_init ***********************************************************
701 Initializes the implementation specific bits.
703 *******************************************************************************/
705 void threads_impl_init(void)
710 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
712 /* Initialize the thread attribute object. */
714 result = pthread_attr_init(&attr);
717 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
719 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
722 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
726 /* threads_startup_thread ******************************************************
728 Thread startup function called by pthread_create.
730 Thread which have a startup.function != NULL are marked as internal
731 threads. All other threads are threated as normal Java threads.
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
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.)
743 ******************************************************************************/
745 static void *threads_startup_thread(void *arg)
747 startupinfo *startup;
752 functionptr function;
754 #if defined(ENABLE_GC_BOEHM)
755 # if !defined(__DARWIN__)
756 struct GC_stack_base sb;
761 #if defined(ENABLE_INTRP)
762 u1 *intrp_thread_stack;
765 #if defined(ENABLE_INTRP)
766 /* create interpreter stack */
769 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
770 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
773 intrp_thread_stack = NULL;
776 /* get passed startupinfo structure and the values in there */
778 startup = (startupinfo*) arg;
781 function = startup->function;
782 psem = startup->psem;
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. */
788 threads_sem_wait(startup->psem_first);
790 #if defined(__DARWIN__)
791 t->mach_thread = mach_thread_self();
794 /* Now that we are in the new thread, we can store the internal
795 thread data-structure in the TSD. */
797 thread_set_current(t);
799 #if defined(ENABLE_GC_BOEHM)
800 # if defined(__DARWIN__)
801 // This is currently not implemented in Boehm-GC. Just fail silently.
803 /* Register the thread with Boehm-GC. This must happen before the
804 thread allocates any memory from the GC heap.*/
806 result = GC_get_stack_base(&sb);
809 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
811 GC_register_my_thread(&sb);
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);
819 /* set our priority */
821 threads_set_thread_priority(t->tid, jlt.get_priority());
823 /* Thread is completely initialized. */
825 thread_set_state_runnable(t);
827 /* tell threads_startup_thread that we registered ourselves */
828 /* CAUTION: *startup becomes invalid with this! */
831 threads_sem_post(psem);
833 #if defined(ENABLE_INTRP)
834 /* set interpreter stack */
837 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
840 #if defined(ENABLE_JVMTI)
841 /* fire thread start event */
844 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
847 DEBUGTHREADS("starting", t);
849 /* find and run the Thread.run()V method if no other function was passed */
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. */
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);
861 # error unknown classpath configuration
864 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
867 vm_abort("threads_startup_thread: run() method not found in class");
869 /* set ThreadMXBean variables */
871 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
872 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
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; */
880 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
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();
886 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
888 java_handle_t* h = jlt.get_handle();
891 # error unknown classpath configuration
894 /* Run the thread. */
896 (void) vm_call_method(m, h);
899 /* set ThreadMXBean variables */
901 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
902 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
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; */
910 /* call passed function, e.g. finalizer_thread */
915 DEBUGTHREADS("stopping", t);
917 #if defined(ENABLE_JVMTI)
918 /* fire thread end event */
921 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
924 /* We ignore the return value. */
926 (void) thread_detach_current_thread();
928 /* set ThreadMXBean variables */
930 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
937 /* threads_impl_thread_start ***************************************************
939 Start a thread in the JVM. Both (vm internal and java) thread
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
947 ******************************************************************************/
949 void threads_impl_thread_start(threadobject *thread, functionptr f)
957 /* fill startupinfo structure passed by pthread_create to
958 * threads_startup_thread */
960 startup.thread = thread;
961 startup.function = f; /* maybe we don't call Thread.run()V */
963 startup.psem_first = &sem_first;
965 threads_sem_init(&sem, 0, 0);
966 threads_sem_init(&sem_first, 0, 0);
968 /* Initialize thread attributes. */
970 result = pthread_attr_init(&attr);
973 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
975 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
978 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
980 /* initialize thread stacksize */
982 result = pthread_attr_setstacksize(&attr, opt_stacksize);
985 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
987 /* create the thread */
989 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
992 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
994 /* destroy the thread attributes */
996 result = pthread_attr_destroy(&attr);
999 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1001 /* signal that pthread_create has returned, so thread->tid is valid */
1003 threads_sem_post(&sem_first);
1005 /* wait here until the thread has entered itself into the thread list */
1007 threads_sem_wait(&sem);
1012 sem_destroy(&sem_first);
1016 /* threads_set_thread_priority *************************************************
1018 Set the priority of the given thread.
1021 tid..........thread id
1022 priority.....priority to set
1024 ******************************************************************************/
1026 void threads_set_thread_priority(pthread_t tid, int priority)
1028 struct sched_param schedp;
1031 pthread_getschedparam(tid, &policy, &schedp);
1032 schedp.sched_priority = priority;
1033 pthread_setschedparam(tid, policy, &schedp);
1038 * Detaches the current thread from the VM.
1040 * @return true on success, false otherwise
1042 bool thread_detach_current_thread(void)
1044 threadobject* t = thread_get_current();
1050 /* If the given thread has already been detached, this operation
1053 if (thread_is_attached(t) == false)
1056 DEBUGTHREADS("detaching", t);
1058 java_handle_t* object = thread_get_object(t);
1059 java_lang_Thread jlt(object);
1061 #if defined(ENABLE_JAVASE)
1062 java_handle_t* group = jlt.get_group();
1064 /* If there's an uncaught exception, call uncaughtException on the
1065 thread's exception handler, or the thread's group if this is
1068 java_handle_t* e = exceptions_get_and_clear_exception();
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. */
1075 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1077 java_handle_t* handler = jlt.get_exceptionHandler();
1079 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1081 java_handle_t* handler = jlt.get_uncaughtExceptionHandler();
1088 if (handler != NULL) {
1089 LLNI_class_get(handler, c);
1090 h = (java_handle_t *) handler;
1093 LLNI_class_get(group, c);
1094 h = (java_handle_t *) group;
1097 methodinfo* m = class_resolveclassmethod(c,
1098 utf_uncaughtException,
1099 utf_java_lang_Thread_java_lang_Throwable__V,
1106 (void) vm_call_method(m, h, object, e);
1108 if (exceptions_get_exception())
1112 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1114 /* Remove thread from the thread group. */
1116 if (group != NULL) {
1118 LLNI_class_get(group, c);
1120 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1121 methodinfo* m = class_resolveclassmethod(c,
1123 utf_java_lang_Thread__V,
1124 class_java_lang_ThreadGroup,
1126 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1127 methodinfo* m = class_resolveclassmethod(c,
1129 utf_java_lang_Thread__V,
1130 class_java_lang_ThreadGroup,
1133 # error unknown classpath configuration
1139 (void) vm_call_method(m, group, object);
1141 if (exceptions_get_exception())
1144 // Clear the ThreadGroup in the Java thread object (Mauve
1145 // test: gnu/testlet/java/lang/Thread/getThreadGroup).
1146 jlt.set_group(NULL);
1150 /* Thread has terminated. */
1152 thread_set_state_terminated(t);
1154 /* Notify all threads waiting on this thread. These are joining
1157 /* XXX Care about exceptions? */
1158 (void) lock_monitor_enter(jlt.get_handle());
1160 lock_notify_all_object(jlt.get_handle());
1162 /* XXX Care about exceptions? */
1163 (void) lock_monitor_exit(jlt.get_handle());
1165 /* Enter the join-mutex before calling thread_free, so
1166 threads_join_all_threads gets the correct number of non-daemon
1169 threads_mutex_join_lock();
1171 /* Free the internal thread data-structure. */
1175 /* Signal that this thread has finished and leave the mutex. */
1177 cond_join->signal();
1178 threads_mutex_join_unlock();
1184 /* threads_suspend_thread ******************************************************
1186 Suspend the passed thread. Execution stops until the thread
1187 is explicitly resumend again.
1190 reason.....Reason for suspending this thread.
1192 *******************************************************************************/
1194 bool threads_suspend_thread(threadobject *thread, s4 reason)
1196 /* acquire the suspendmutex */
1197 thread->suspendmutex->lock();
1199 if (thread->suspended) {
1200 thread->suspendmutex->unlock();
1204 /* set the reason for the suspension */
1205 thread->suspend_reason = reason;
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",
1213 /* REMEMBER: do not release the suspendmutex, this is done
1214 by the thread itself in threads_suspend_ack(). */
1220 /* threads_suspend_ack *********************************************************
1222 Acknowledges the suspension of the current thread.
1225 pc.....The PC where the thread suspended its execution.
1226 sp.....The SP before the thread suspended its execution.
1228 *******************************************************************************/
1230 #if defined(ENABLE_GC_CACAO)
1231 void threads_suspend_ack(u1* pc, u1* sp)
1233 threadobject *thread;
1235 thread = THREADOBJECT;
1237 assert(thread->suspend_reason != 0);
1239 /* TODO: remember dump memory size */
1241 /* inform the GC about the suspension */
1242 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1244 /* check if the GC wants to leave the thread running */
1245 if (!gc_suspend(thread, pc, sp)) {
1247 /* REMEMBER: we do not unlock the suspendmutex because the thread
1248 will suspend itself again at a later time */
1254 /* mark this thread as suspended and remember the PC */
1256 thread->suspended = true;
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);
1263 DEBUGTHREADS("suspending", thread);
1265 /* release the suspension mutex and wait till we are resumed */
1266 thread->suspendcond->wait(thread->suspendmutex);
1268 DEBUGTHREADS("resuming", thread);
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 /* TODO: free dump memory */
1277 /* release the suspendmutex */
1278 thread->suspendmutex->unlock();
1283 /* threads_resume_thread *******************************************************
1285 Resumes the execution of the passed thread.
1287 *******************************************************************************/
1289 #if defined(ENABLE_GC_CACAO)
1290 bool threads_resume_thread(threadobject *thread)
1292 /* acquire the suspendmutex */
1293 thread->suspendmutex->lock();
1295 if (!thread->suspended) {
1296 thread->suspendmutex->unlock();
1300 thread->suspended = false;
1302 /* tell everyone that the thread should resume */
1303 assert(thread != THREADOBJECT);
1304 thread->suspendcond->broadcast();
1306 /* release the suspendmutex */
1307 thread->suspendmutex->unlock();
1314 /* threads_join_all_threads ****************************************************
1316 Join all non-daemon threads.
1318 *******************************************************************************/
1320 void threads_join_all_threads(void)
1324 /* get current thread */
1328 /* This thread is waiting for all non-daemon threads to exit. */
1330 thread_set_state_waiting(t);
1332 /* enter join mutex */
1334 threads_mutex_join_lock();
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. */
1340 while (threadlist_get_non_daemons() > 1)
1341 cond_join->wait(mutex_join);
1343 /* leave join mutex */
1345 threads_mutex_join_unlock();
1349 /* threads_timespec_earlier ****************************************************
1351 Return true if timespec tv1 is earlier than timespec tv2.
1354 tv1..........first timespec
1355 tv2..........second timespec
1358 true, if the first timespec is earlier
1360 *******************************************************************************/
1362 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1363 const struct timespec *tv2)
1365 return (tv1->tv_sec < tv2->tv_sec)
1367 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1371 /* threads_current_time_is_earlier_than ****************************************
1373 Check if the current time is earlier than the given timespec.
1376 tv...........the timespec to compare against
1379 true, if the current time is earlier
1381 *******************************************************************************/
1383 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1385 struct timeval tvnow;
1386 struct timespec tsnow;
1388 /* get current time */
1390 if (gettimeofday(&tvnow, NULL) != 0)
1391 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1393 /* convert it to a timespec */
1395 tsnow.tv_sec = tvnow.tv_sec;
1396 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1398 /* compare current time with the given timespec */
1400 return threads_timespec_earlier(&tsnow, tv);
1404 /* threads_wait_with_timeout ***************************************************
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.
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.
1415 *******************************************************************************/
1417 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1419 // Acquire the waitmutex.
1420 t->waitmutex->lock();
1422 /* wait on waitcond */
1424 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1426 while (!t->interrupted && !t->signaled
1427 && threads_current_time_is_earlier_than(wakeupTime))
1429 thread_set_state_timed_waiting(t);
1431 t->waitcond->timedwait(t->waitmutex, wakeupTime);
1433 thread_set_state_runnable(t);
1438 while (!t->interrupted && !t->signaled) {
1439 thread_set_state_waiting(t);
1441 t->waitcond->wait(t->waitmutex);
1443 thread_set_state_runnable(t);
1447 // Release the waitmutex.
1448 t->waitmutex->unlock();
1452 /* threads_wait_with_timeout_relative ******************************************
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.
1458 t............the current thread
1459 millis.......milliseconds to wait
1460 nanos........nanoseconds to wait
1462 *******************************************************************************/
1464 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1467 struct timespec wakeupTime;
1469 /* calculate the the (latest) wakeup time */
1471 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1475 threads_wait_with_timeout(thread, &wakeupTime);
1479 /* threads_calc_absolute_time **************************************************
1481 Calculate the absolute point in time a given number of ms and ns from now.
1484 millis............milliseconds from now
1485 nanos.............nanoseconds from now
1488 *tm...............receives the timespec of the absolute point in time
1490 *******************************************************************************/
1492 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1494 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1497 gettimeofday(&tv, NULL);
1498 tv.tv_sec += 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;
1511 /* threads_thread_interrupt ****************************************************
1513 Interrupt the given thread.
1515 The thread gets the "waitcond" signal and
1516 its interrupted flag is set to true.
1519 thread............the thread to interrupt
1521 *******************************************************************************/
1523 void threads_thread_interrupt(threadobject *t)
1525 /* Signal the thread a "waitcond" and tell it that it has been
1528 t->waitmutex->lock();
1530 DEBUGTHREADS("interrupted", t);
1532 /* Interrupt blocking system call using a signal. */
1534 pthread_kill(t->tid, Signal_THREAD_INTERRUPT);
1536 t->waitcond->signal();
1538 t->interrupted = true;
1540 t->waitmutex->unlock();
1545 * Sleep the current thread for the specified amount of time.
1547 * @param millis Milliseconds to sleep.
1548 * @param nanos Nanoseconds to sleep.
1550 void threads_sleep(int64_t millis, int32_t nanos)
1553 struct timespec wakeupTime;
1557 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1558 exceptions_throw_illegalargumentexception();
1562 t = thread_get_current();
1564 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1565 /* Clear interrupted flag (Mauve test:
1566 gnu/testlet/java/lang/Thread/interrupt). */
1568 thread_set_interrupted(t, false);
1570 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1571 exceptions_throw_interruptedexception();
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) {
1584 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1586 threads_wait_with_timeout(t, &wakeupTime);
1588 interrupted = thread_is_interrupted(t);
1591 thread_set_interrupted(t, false);
1593 // An other exception could have been thrown
1594 // (e.g. ThreadDeathException).
1595 if (!exceptions_get_exception())
1596 exceptions_throw_interruptedexception();
1602 /* threads_yield ***************************************************************
1604 Yield to the scheduler.
1606 *******************************************************************************/
1608 void threads_yield(void)
1613 #if defined(ENABLE_TLH)
1615 void threads_tlh_add_frame() {
1616 tlh_add_frame(&(THREADOBJECT->tlh));
1619 void threads_tlh_remove_frame() {
1620 tlh_remove_frame(&(THREADOBJECT->tlh));
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 * ---------------------------------------------------------------------
1635 * indent-tabs-mode: t
1639 * vim:noexpandtab:sw=4:ts=4: