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)
123 sem->mutex = new Mutex();
124 sem->cond = new Condition();
130 static int sem_post(sem_t *sem)
135 sem->mutex->unlock();
140 static int sem_wait(sem_t *sem)
144 while (sem->value == 0) {
145 sem->cond->wait(sem->mutex);
149 sem->mutex->unlock();
154 static int sem_destroy(sem_t *sem)
161 #endif /* defined(__DARWIN__) */
164 /* startupinfo *****************************************************************
166 Struct used to pass info from threads_start_thread to
167 threads_startup_thread.
169 ******************************************************************************/
172 threadobject *thread; /* threadobject for this thread */
173 functionptr function; /* function to run in the new thread */
174 sem_t *psem; /* signals when thread has been entered */
175 /* in the thread list */
176 sem_t *psem_first; /* signals when pthread_create has returned */
180 /* prototypes *****************************************************************/
182 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
185 /******************************************************************************/
186 /* GLOBAL VARIABLES */
187 /******************************************************************************/
189 /* the thread object of the current thread */
190 /* This is either a thread-local variable defined with __thread, or */
191 /* a thread-specific value stored with key threads_current_threadobject_key. */
192 #if defined(HAVE___THREAD)
193 __thread threadobject *thread_current;
195 pthread_key_t thread_current_key;
198 /* global mutex for stop-the-world */
199 static Mutex* stopworldlock;
201 #if defined(ENABLE_GC_CACAO)
202 /* global mutex for the GC */
203 static Mutex* mutex_gc;
206 /* global mutex and condition for joining threads on exit */
207 static Mutex* mutex_join;
208 static Condition* cond_join;
210 #if defined(ENABLE_GC_CACAO)
211 /* semaphore used for acknowleding thread suspension */
212 static sem_t suspend_ack;
216 /* threads_sem_init ************************************************************
218 Initialize a semaphore. Checks against errors and interruptions.
221 sem..............the semaphore to initialize
222 shared...........true if this semaphore will be shared between processes
223 value............the initial value for the semaphore
225 *******************************************************************************/
227 void threads_sem_init(sem_t *sem, bool shared, int value)
234 r = sem_init(sem, shared, value);
237 } while (errno == EINTR);
239 vm_abort("sem_init failed: %s", strerror(errno));
243 /* threads_sem_wait ************************************************************
245 Wait for a semaphore, non-interruptible.
247 IMPORTANT: Always use this function instead of `sem_wait` directly, as
248 `sem_wait` may be interrupted by signals!
251 sem..............the semaphore to wait on
253 *******************************************************************************/
255 void threads_sem_wait(sem_t *sem)
265 } while (errno == EINTR);
267 vm_abort("sem_wait failed: %s", strerror(errno));
271 /* threads_sem_post ************************************************************
273 Increase the count of a semaphore. Checks for errors.
276 sem..............the semaphore to increase the count of
278 *******************************************************************************/
280 void threads_sem_post(sem_t *sem)
286 /* unlike sem_wait, sem_post is not interruptible */
292 vm_abort("sem_post failed: %s", strerror(errno));
296 /* threads_stopworld ***********************************************************
298 Stops the world from turning. All threads except the calling one
299 are suspended. The function returns as soon as all threads have
300 acknowledged their suspension.
302 *******************************************************************************/
304 #if defined(ENABLE_GC_CACAO)
305 void threads_stopworld(void)
307 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
314 stopworldlock->lock();
316 /* lock the threads lists */
320 #if defined(__DARWIN__)
321 /*threads_cast_darwinstop();*/
323 #elif defined(__CYGWIN__)
329 DEBUGTHREADS("stops World", self);
333 /* suspend all running threads */
334 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
335 /* don't send the signal to ourself */
340 /* don't send the signal to NEW threads (because they are not
341 completely initialized) */
343 if (t->state == THREAD_STATE_NEW)
346 /* send the signal */
348 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
351 /* increase threads count */
356 /* wait for all threads signaled to suspend */
357 for (i = 0; i < count; i++)
358 threads_sem_wait(&suspend_ack);
361 /* ATTENTION: Don't unlock the threads-lists here so that
362 non-signaled NEW threads can't change their state and execute
368 /* threads_startworld **********************************************************
370 Starts the world again after it has previously been stopped.
372 *******************************************************************************/
374 #if defined(ENABLE_GC_CACAO)
375 void threads_startworld(void)
377 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
384 #if defined(__DARWIN__)
385 /*threads_cast_darwinresume();*/
387 #elif defined(__IRIX__)
388 threads_cast_irixresume();
389 #elif defined(__CYGWIN__)
395 DEBUGTHREADS("starts World", self);
399 /* resume all thread we haltet */
400 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
401 /* don't send the signal to ourself */
406 /* don't send the signal to NEW threads (because they are not
407 completely initialized) */
409 if (t->state == THREAD_STATE_NEW)
412 /* send the signal */
414 result = threads_resume_thread(t);
417 /* increase threads count */
422 /* wait for all threads signaled to suspend */
423 for (i = 0; i < count; i++)
424 threads_sem_wait(&suspend_ack);
428 /* unlock the threads lists */
432 stopworldlock->unlock();
437 /* threads_impl_thread_init ****************************************************
439 Initialize OS-level locking constructs in threadobject.
442 t....the threadobject
444 *******************************************************************************/
446 void threads_impl_thread_init(threadobject *t)
448 /* initialize the mutex and the condition */
450 t->flc_lock = new Mutex();
451 t->flc_cond = new Condition();
453 t->waitmutex = new Mutex();
454 t->waitcond = new Condition();
456 t->suspendmutex = new Mutex();
457 t->suspendcond = new Condition();
459 #if defined(ENABLE_TLH)
464 /* threads_impl_thread_clear ***************************************************
466 Clears all fields in threadobject the way an MZERO would have
467 done. MZERO cannot be used anymore because it would mess up the
471 t....the threadobject
473 *******************************************************************************/
475 void threads_impl_thread_clear(threadobject *t)
487 #if defined(__DARWIN__)
491 t->interrupted = false;
494 t->suspended = false;
495 t->suspend_reason = 0;
499 t->_exceptionptr = NULL;
500 t->_stackframeinfo = NULL;
501 t->_localref_table = NULL;
503 #if defined(ENABLE_INTRP)
504 t->_global_sp = NULL;
507 #if defined(ENABLE_GC_CACAO)
508 t->gc_critical = false;
514 MZERO(&t->dumpinfo, dumpinfo_t, 1);
517 /* threads_impl_thread_reuse ***************************************************
519 Resets some implementation fields in threadobject. This was
520 previously done in threads_impl_thread_new.
523 t....the threadobject
525 *******************************************************************************/
527 void threads_impl_thread_reuse(threadobject *t)
529 /* get the pthread id */
531 t->tid = pthread_self();
533 #if defined(ENABLE_DEBUG_FILTER)
534 /* Initialize filter counters */
535 t->filterverbosecallctr[0] = 0;
536 t->filterverbosecallctr[1] = 0;
540 t->tracejavacallindent = 0;
541 t->tracejavacallcount = 0;
548 /* not really needed */
549 t->flc_object = NULL;
551 #if defined(ENABLE_TLH)
552 tlh_destroy(&(t->tlh));
558 /* threads_impl_thread_free ****************************************************
560 Cleanup thread stuff.
563 t....the threadobject
565 *******************************************************************************/
569 void threads_impl_thread_free(threadobject *t)
573 /* Destroy the mutex and the condition. */
577 result = pthread_cond_destroy(&(t->flc_cond));
580 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
584 result = pthread_cond_destroy(&(t->waitcond));
587 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
589 delete t->suspendmutex;
591 result = pthread_cond_destroy(&(t->suspendcond));
594 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
599 /* threads_impl_preinit ********************************************************
601 Do some early initialization of stuff required.
603 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
604 is called AFTER this function!
606 *******************************************************************************/
608 void threads_impl_preinit(void)
612 stopworldlock = new Mutex();
614 /* initialize exit mutex and condition (on exit we join all
617 mutex_join = new Mutex();
618 cond_join = new Condition();
620 #if defined(ENABLE_GC_CACAO)
621 /* initialize the GC mutex & suspend semaphore */
623 mutex_gc = new Mutex();
624 threads_sem_init(&suspend_ack, 0, 0);
627 #if !defined(HAVE___THREAD)
628 result = pthread_key_create(&thread_current_key, NULL);
630 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
635 /* threads_mutex_gc_lock *******************************************************
637 Enter the global GC mutex.
639 *******************************************************************************/
641 #if defined(ENABLE_GC_CACAO)
642 void threads_mutex_gc_lock(void)
649 /* threads_mutex_gc_unlock *****************************************************
651 Leave the global GC mutex.
653 *******************************************************************************/
655 #if defined(ENABLE_GC_CACAO)
656 void threads_mutex_gc_unlock(void)
662 /* threads_mutex_join_lock *****************************************************
664 Enter the join mutex.
666 *******************************************************************************/
668 void threads_mutex_join_lock(void)
674 /* threads_mutex_join_unlock ***************************************************
676 Leave the join mutex.
678 *******************************************************************************/
680 void threads_mutex_join_unlock(void)
682 mutex_join->unlock();
686 /* threads_impl_init ***********************************************************
688 Initializes the implementation specific bits.
690 *******************************************************************************/
692 void threads_impl_init(void)
697 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
699 /* Initialize the thread attribute object. */
701 result = pthread_attr_init(&attr);
704 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
706 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
709 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
713 /* threads_startup_thread ******************************************************
715 Thread startup function called by pthread_create.
717 Thread which have a startup.function != NULL are marked as internal
718 threads. All other threads are threated as normal Java threads.
720 NOTE: This function is not called directly by pthread_create. The Boehm GC
721 inserts its own GC_start_routine in between, which then calls
725 arg..........the argument passed to pthread_create, ie. a pointer to
726 a startupinfo struct. CAUTION: When the `psem` semaphore
727 is posted, the startupinfo struct becomes invalid! (It
728 is allocated on the stack of threads_start_thread.)
730 ******************************************************************************/
732 static void *threads_startup_thread(void *arg)
734 startupinfo *startup;
739 functionptr function;
741 #if defined(ENABLE_GC_BOEHM)
742 # if !defined(__DARWIN__)
743 struct GC_stack_base sb;
748 #if defined(ENABLE_INTRP)
749 u1 *intrp_thread_stack;
752 #if defined(ENABLE_INTRP)
753 /* create interpreter stack */
756 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
757 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
760 intrp_thread_stack = NULL;
763 /* get passed startupinfo structure and the values in there */
765 startup = (startupinfo*) arg;
768 function = startup->function;
769 psem = startup->psem;
771 /* Seems like we've encountered a situation where thread->tid was
772 not set by pthread_create. We alleviate this problem by waiting
773 for pthread_create to return. */
775 threads_sem_wait(startup->psem_first);
777 #if defined(__DARWIN__)
778 t->mach_thread = mach_thread_self();
781 /* Now that we are in the new thread, we can store the internal
782 thread data-structure in the TSD. */
784 thread_set_current(t);
786 #if defined(ENABLE_GC_BOEHM)
787 # if defined(__DARWIN__)
788 // This is currently not implemented in Boehm-GC. Just fail silently.
790 /* Register the thread with Boehm-GC. This must happen before the
791 thread allocates any memory from the GC heap.*/
793 result = GC_get_stack_base(&sb);
796 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
798 GC_register_my_thread(&sb);
802 // Get the java.lang.Thread object for this thread.
803 java_handle_t* object = thread_get_object(t);
804 java_lang_Thread jlt(object);
806 /* set our priority */
808 threads_set_thread_priority(t->tid, jlt.get_priority());
810 /* Thread is completely initialized. */
812 thread_set_state_runnable(t);
814 /* tell threads_startup_thread that we registered ourselves */
815 /* CAUTION: *startup becomes invalid with this! */
818 threads_sem_post(psem);
820 #if defined(ENABLE_INTRP)
821 /* set interpreter stack */
824 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
827 #if defined(ENABLE_JVMTI)
828 /* fire thread start event */
831 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
834 DEBUGTHREADS("starting", t);
836 /* find and run the Thread.run()V method if no other function was passed */
838 if (function == NULL) {
839 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
840 /* We need to start the run method of
841 java.lang.VMThread. Since this is a final class, we can use
842 the class object directly. */
844 c = class_java_lang_VMThread;
845 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
846 LLNI_class_get(object, c);
848 # error unknown classpath configuration
851 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
854 vm_abort("threads_startup_thread: run() method not found in class");
856 /* set ThreadMXBean variables */
858 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
859 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
861 /* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
862 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
863 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
864 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
867 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
869 // We need to start the run method of java.lang.VMThread.
870 java_lang_VMThread jlvmt(jlt.get_vmThread());
871 java_handle_t* h = jlvmt.get_handle();
873 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
875 java_handle_t* h = jlt.get_handle();
878 # error unknown classpath configuration
881 /* Run the thread. */
883 (void) vm_call_method(m, h);
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 /* call passed function, e.g. finalizer_thread */
902 DEBUGTHREADS("stopping", t);
904 #if defined(ENABLE_JVMTI)
905 /* fire thread end event */
908 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
911 /* We ignore the return value. */
913 (void) thread_detach_current_thread();
915 /* set ThreadMXBean variables */
917 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
924 /* threads_impl_thread_start ***************************************************
926 Start a thread in the JVM. Both (vm internal and java) thread
930 thread....the thread object
931 f.........function to run in the new thread. NULL means that the
932 "run" method of the object `t` should be called
934 ******************************************************************************/
936 void threads_impl_thread_start(threadobject *thread, functionptr f)
944 /* fill startupinfo structure passed by pthread_create to
945 * threads_startup_thread */
947 startup.thread = thread;
948 startup.function = f; /* maybe we don't call Thread.run()V */
950 startup.psem_first = &sem_first;
952 threads_sem_init(&sem, 0, 0);
953 threads_sem_init(&sem_first, 0, 0);
955 /* Initialize thread attributes. */
957 result = pthread_attr_init(&attr);
960 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
962 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
965 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
967 /* initialize thread stacksize */
969 result = pthread_attr_setstacksize(&attr, opt_stacksize);
972 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
974 /* create the thread */
976 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
979 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
981 /* destroy the thread attributes */
983 result = pthread_attr_destroy(&attr);
986 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
988 /* signal that pthread_create has returned, so thread->tid is valid */
990 threads_sem_post(&sem_first);
992 /* wait here until the thread has entered itself into the thread list */
994 threads_sem_wait(&sem);
999 sem_destroy(&sem_first);
1003 /* threads_set_thread_priority *************************************************
1005 Set the priority of the given thread.
1008 tid..........thread id
1009 priority.....priority to set
1011 ******************************************************************************/
1013 void threads_set_thread_priority(pthread_t tid, int priority)
1015 struct sched_param schedp;
1018 pthread_getschedparam(tid, &policy, &schedp);
1019 schedp.sched_priority = priority;
1020 pthread_setschedparam(tid, policy, &schedp);
1025 * Detaches the current thread from the VM.
1027 * @return true on success, false otherwise
1029 bool thread_detach_current_thread(void)
1031 threadobject* t = thread_get_current();
1037 /* If the given thread has already been detached, this operation
1040 if (thread_is_attached(t) == false)
1043 DEBUGTHREADS("detaching", t);
1045 java_handle_t* object = thread_get_object(t);
1046 java_lang_Thread jlt(object);
1048 #if defined(ENABLE_JAVASE)
1049 java_handle_t* group = jlt.get_group();
1051 /* If there's an uncaught exception, call uncaughtException on the
1052 thread's exception handler, or the thread's group if this is
1055 java_handle_t* e = exceptions_get_and_clear_exception();
1058 /* We use the type void* for handler here, as it's not trivial
1059 to build the java_lang_Thread_UncaughtExceptionHandler
1060 header file with cacaoh. */
1062 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1064 java_handle_t* handler = jlt.get_exceptionHandler();
1066 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1068 java_handle_t* handler = jlt.get_uncaughtExceptionHandler();
1075 if (handler != NULL) {
1076 LLNI_class_get(handler, c);
1077 h = (java_handle_t *) handler;
1080 LLNI_class_get(group, c);
1081 h = (java_handle_t *) group;
1084 methodinfo* m = class_resolveclassmethod(c,
1085 utf_uncaughtException,
1086 utf_java_lang_Thread_java_lang_Throwable__V,
1093 (void) vm_call_method(m, h, object, e);
1095 if (exceptions_get_exception())
1099 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1101 /* Remove thread from the thread group. */
1103 if (group != NULL) {
1105 LLNI_class_get(group, c);
1107 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1108 methodinfo* m = class_resolveclassmethod(c,
1110 utf_java_lang_Thread__V,
1111 class_java_lang_ThreadGroup,
1113 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1114 methodinfo* m = class_resolveclassmethod(c,
1116 utf_java_lang_Thread__V,
1117 class_java_lang_ThreadGroup,
1120 # error unknown classpath configuration
1126 (void) vm_call_method(m, group, object);
1128 if (exceptions_get_exception())
1131 // Clear the ThreadGroup in the Java thread object (Mauve
1132 // test: gnu/testlet/java/lang/Thread/getThreadGroup).
1133 jlt.set_group(NULL);
1137 /* Thread has terminated. */
1139 thread_set_state_terminated(t);
1141 /* Notify all threads waiting on this thread. These are joining
1144 /* XXX Care about exceptions? */
1145 (void) lock_monitor_enter(jlt.get_handle());
1147 lock_notify_all_object(jlt.get_handle());
1149 /* XXX Care about exceptions? */
1150 (void) lock_monitor_exit(jlt.get_handle());
1152 /* Enter the join-mutex before calling thread_free, so
1153 threads_join_all_threads gets the correct number of non-daemon
1156 threads_mutex_join_lock();
1158 /* Free the internal thread data-structure. */
1162 /* Signal that this thread has finished and leave the mutex. */
1164 cond_join->signal();
1165 threads_mutex_join_unlock();
1171 /* threads_suspend_thread ******************************************************
1173 Suspend the passed thread. Execution stops until the thread
1174 is explicitly resumend again.
1177 reason.....Reason for suspending this thread.
1179 *******************************************************************************/
1181 bool threads_suspend_thread(threadobject *thread, s4 reason)
1183 /* acquire the suspendmutex */
1184 thread->suspendmutex->lock();
1186 if (thread->suspended) {
1187 thread->suspendmutex->unlock();
1191 /* set the reason for the suspension */
1192 thread->suspend_reason = reason;
1194 /* send the suspend signal to the thread */
1195 assert(thread != THREADOBJECT);
1196 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1197 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1200 /* REMEMBER: do not release the suspendmutex, this is done
1201 by the thread itself in threads_suspend_ack(). */
1207 /* threads_suspend_ack *********************************************************
1209 Acknowledges the suspension of the current thread.
1212 pc.....The PC where the thread suspended its execution.
1213 sp.....The SP before the thread suspended its execution.
1215 *******************************************************************************/
1217 #if defined(ENABLE_GC_CACAO)
1218 void threads_suspend_ack(u1* pc, u1* sp)
1220 threadobject *thread;
1222 thread = THREADOBJECT;
1224 assert(thread->suspend_reason != 0);
1226 /* TODO: remember dump memory size */
1228 /* inform the GC about the suspension */
1229 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1231 /* check if the GC wants to leave the thread running */
1232 if (!gc_suspend(thread, pc, sp)) {
1234 /* REMEMBER: we do not unlock the suspendmutex because the thread
1235 will suspend itself again at a later time */
1241 /* mark this thread as suspended and remember the PC */
1243 thread->suspended = true;
1245 /* if we are stopping the world, we should send a global ack */
1246 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1247 threads_sem_post(&suspend_ack);
1250 DEBUGTHREADS("suspending", thread);
1252 /* release the suspension mutex and wait till we are resumed */
1253 thread->suspendcond->wait(thread->suspendmutex);
1255 DEBUGTHREADS("resuming", thread);
1257 /* if we are stopping the world, we should send a global ack */
1258 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1259 threads_sem_post(&suspend_ack);
1262 /* TODO: free dump memory */
1264 /* release the suspendmutex */
1265 thread->suspendmutex->unlock();
1270 /* threads_resume_thread *******************************************************
1272 Resumes the execution of the passed thread.
1274 *******************************************************************************/
1276 #if defined(ENABLE_GC_CACAO)
1277 bool threads_resume_thread(threadobject *thread)
1279 /* acquire the suspendmutex */
1280 thread->suspendmutex->lock();
1282 if (!thread->suspended) {
1283 thread->suspendmutex->unlock();
1287 thread->suspended = false;
1289 /* tell everyone that the thread should resume */
1290 assert(thread != THREADOBJECT);
1291 thread->suspendcond->broadcast();
1293 /* release the suspendmutex */
1294 thread->suspendmutex->unlock();
1301 /* threads_join_all_threads ****************************************************
1303 Join all non-daemon threads.
1305 *******************************************************************************/
1307 void threads_join_all_threads(void)
1311 /* get current thread */
1315 /* This thread is waiting for all non-daemon threads to exit. */
1317 thread_set_state_waiting(t);
1319 /* enter join mutex */
1321 threads_mutex_join_lock();
1323 /* Wait for condition as long as we have non-daemon threads. We
1324 compare against 1 because the current (main thread) is also a
1325 non-daemon thread. */
1327 while (threadlist_get_non_daemons() > 1)
1328 cond_join->wait(mutex_join);
1330 /* leave join mutex */
1332 threads_mutex_join_unlock();
1336 /* threads_timespec_earlier ****************************************************
1338 Return true if timespec tv1 is earlier than timespec tv2.
1341 tv1..........first timespec
1342 tv2..........second timespec
1345 true, if the first timespec is earlier
1347 *******************************************************************************/
1349 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1350 const struct timespec *tv2)
1352 return (tv1->tv_sec < tv2->tv_sec)
1354 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1358 /* threads_current_time_is_earlier_than ****************************************
1360 Check if the current time is earlier than the given timespec.
1363 tv...........the timespec to compare against
1366 true, if the current time is earlier
1368 *******************************************************************************/
1370 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1372 struct timeval tvnow;
1373 struct timespec tsnow;
1375 /* get current time */
1377 if (gettimeofday(&tvnow, NULL) != 0)
1378 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1380 /* convert it to a timespec */
1382 tsnow.tv_sec = tvnow.tv_sec;
1383 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1385 /* compare current time with the given timespec */
1387 return threads_timespec_earlier(&tsnow, tv);
1391 /* threads_wait_with_timeout ***************************************************
1393 Wait until the given point in time on a monitor until either
1394 we are notified, we are interrupted, or the time is up.
1397 t............the current thread
1398 wakeupTime...absolute (latest) wakeup time
1399 If both tv_sec and tv_nsec are zero, this function
1400 waits for an unlimited amount of time.
1402 *******************************************************************************/
1404 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1406 // Acquire the waitmutex.
1407 t->waitmutex->lock();
1409 /* wait on waitcond */
1411 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1413 while (!t->interrupted && !t->signaled
1414 && threads_current_time_is_earlier_than(wakeupTime))
1416 thread_set_state_timed_waiting(t);
1418 t->waitcond->timedwait(t->waitmutex, wakeupTime);
1420 thread_set_state_runnable(t);
1425 while (!t->interrupted && !t->signaled) {
1426 thread_set_state_waiting(t);
1428 t->waitcond->wait(t->waitmutex);
1430 thread_set_state_runnable(t);
1434 // Release the waitmutex.
1435 t->waitmutex->unlock();
1439 /* threads_wait_with_timeout_relative ******************************************
1441 Wait for the given maximum amount of time on a monitor until either
1442 we are notified, we are interrupted, or the time is up.
1445 t............the current thread
1446 millis.......milliseconds to wait
1447 nanos........nanoseconds to wait
1449 *******************************************************************************/
1451 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1454 struct timespec wakeupTime;
1456 /* calculate the the (latest) wakeup time */
1458 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1462 threads_wait_with_timeout(thread, &wakeupTime);
1466 /* threads_calc_absolute_time **************************************************
1468 Calculate the absolute point in time a given number of ms and ns from now.
1471 millis............milliseconds from now
1472 nanos.............nanoseconds from now
1475 *tm...............receives the timespec of the absolute point in time
1477 *******************************************************************************/
1479 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1481 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1484 gettimeofday(&tv, NULL);
1485 tv.tv_sec += millis / 1000;
1487 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1488 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1489 tm->tv_nsec = nsec % 1000000000;
1498 /* threads_thread_interrupt ****************************************************
1500 Interrupt the given thread.
1502 The thread gets the "waitcond" signal and
1503 its interrupted flag is set to true.
1506 thread............the thread to interrupt
1508 *******************************************************************************/
1510 void threads_thread_interrupt(threadobject *t)
1512 /* Signal the thread a "waitcond" and tell it that it has been
1515 t->waitmutex->lock();
1517 DEBUGTHREADS("interrupted", t);
1519 /* Interrupt blocking system call using a signal. */
1521 pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL);
1523 t->waitcond->signal();
1525 t->interrupted = true;
1527 t->waitmutex->unlock();
1532 * Sleep the current thread for the specified amount of time.
1534 * @param millis Milliseconds to sleep.
1535 * @param nanos Nanoseconds to sleep.
1537 void threads_sleep(int64_t millis, int32_t nanos)
1540 struct timespec wakeupTime;
1544 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1545 exceptions_throw_illegalargumentexception();
1549 t = thread_get_current();
1551 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1552 /* Clear interrupted flag (Mauve test:
1553 gnu/testlet/java/lang/Thread/interrupt). */
1555 thread_set_interrupted(t, false);
1557 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1558 exceptions_throw_interruptedexception();
1562 // (Note taken from classpath/vm/reference/java/lang/VMThread.java (sleep))
1563 // Note: JDK treats a zero length sleep is like Thread.yield(),
1564 // without checking the interrupted status of the thread. It's
1565 // unclear if this is a bug in the implementation or the spec.
1566 // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 */
1567 if (millis == 0 && nanos == 0) {
1571 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1573 threads_wait_with_timeout(t, &wakeupTime);
1575 interrupted = thread_is_interrupted(t);
1578 thread_set_interrupted(t, false);
1580 // An other exception could have been thrown
1581 // (e.g. ThreadDeathException).
1582 if (!exceptions_get_exception())
1583 exceptions_throw_interruptedexception();
1589 /* threads_yield ***************************************************************
1591 Yield to the scheduler.
1593 *******************************************************************************/
1595 void threads_yield(void)
1600 #if defined(ENABLE_TLH)
1602 void threads_tlh_add_frame() {
1603 tlh_add_frame(&(THREADOBJECT->tlh));
1606 void threads_tlh_remove_frame() {
1607 tlh_remove_frame(&(THREADOBJECT->tlh));
1616 * These are local overrides for various environment variables in Emacs.
1617 * Please do not remove this and leave it at the end of the file, where
1618 * Emacs will automagically detect them.
1619 * ---------------------------------------------------------------------
1622 * indent-tabs-mode: t
1626 * vim:noexpandtab:sw=4:ts=4: