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/globals.hpp"
68 #include "vm/javaobjects.hpp"
69 #include "vm/options.h"
70 #include "vm/signallocal.h"
71 #include "vm/string.hpp"
74 #if defined(ENABLE_STATISTICS)
75 # include "vm/statistics.h"
78 #include "vm/jit/asmpart.h"
80 #if !defined(__DARWIN__)
81 # include <semaphore.h>
84 #if defined(__LINUX__)
85 # define GC_LINUX_THREADS
86 #elif defined(__IRIX__)
87 # define GC_IRIX_THREADS
88 #elif defined(__DARWIN__)
89 # define GC_DARWIN_THREADS
92 #if defined(ENABLE_GC_BOEHM)
93 /* We need to include Boehm's gc.h here because it overrides
94 pthread_create and friends. */
95 # include "mm/boehm-gc/include/gc.h"
98 #if defined(ENABLE_JVMTI)
99 #include "native/jvmti/cacaodbg.h"
103 // FIXME For now we export everything as C functions.
106 #if defined(__DARWIN__)
107 /* Darwin has no working semaphore implementation. This one is taken
111 This is a very simple semaphore implementation for Darwin. It
112 is implemented in terms of pthreads calls so it isn't async signal
113 safe. This isn't a problem because signals aren't used to
114 suspend threads on Darwin.
117 static int sem_init(sem_t *sem, int pshared, int value)
122 sem->mutex = new Mutex();
123 sem->cond = new Condition();
129 static int sem_post(sem_t *sem)
134 sem->mutex->unlock();
139 static int sem_wait(sem_t *sem)
143 while (sem->value == 0) {
144 sem->cond->wait(sem->mutex);
148 sem->mutex->unlock();
153 static int sem_destroy(sem_t *sem)
160 #endif /* defined(__DARWIN__) */
163 /* startupinfo *****************************************************************
165 Struct used to pass info from threads_start_thread to
166 threads_startup_thread.
168 ******************************************************************************/
171 threadobject *thread; /* threadobject for this thread */
172 functionptr function; /* function to run in the new thread */
173 sem_t *psem; /* signals when thread has been entered */
174 /* in the thread list */
175 sem_t *psem_first; /* signals when pthread_create has returned */
179 /* prototypes *****************************************************************/
181 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
184 /******************************************************************************/
185 /* GLOBAL VARIABLES */
186 /******************************************************************************/
188 /* the thread object of the current thread */
189 /* This is either a thread-local variable defined with __thread, or */
190 /* a thread-specific value stored with key threads_current_threadobject_key. */
191 #if defined(HAVE___THREAD)
192 __thread threadobject *thread_current;
194 pthread_key_t thread_current_key;
197 /* global mutex for stop-the-world */
198 static Mutex* stopworldlock;
200 #if defined(ENABLE_GC_CACAO)
201 /* global mutex for the GC */
202 static Mutex* mutex_gc;
205 /* global mutex and condition for joining threads on exit */
206 static Mutex* mutex_join;
207 static Condition* cond_join;
209 #if defined(ENABLE_GC_CACAO)
210 /* semaphore used for acknowleding thread suspension */
211 static sem_t suspend_ack;
215 /* threads_sem_init ************************************************************
217 Initialize a semaphore. Checks against errors and interruptions.
220 sem..............the semaphore to initialize
221 shared...........true if this semaphore will be shared between processes
222 value............the initial value for the semaphore
224 *******************************************************************************/
226 void threads_sem_init(sem_t *sem, bool shared, int value)
233 r = sem_init(sem, shared, value);
236 } while (errno == EINTR);
238 vm_abort("sem_init failed: %s", strerror(errno));
242 /* threads_sem_wait ************************************************************
244 Wait for a semaphore, non-interruptible.
246 IMPORTANT: Always use this function instead of `sem_wait` directly, as
247 `sem_wait` may be interrupted by signals!
250 sem..............the semaphore to wait on
252 *******************************************************************************/
254 void threads_sem_wait(sem_t *sem)
264 } while (errno == EINTR);
266 vm_abort("sem_wait failed: %s", strerror(errno));
270 /* threads_sem_post ************************************************************
272 Increase the count of a semaphore. Checks for errors.
275 sem..............the semaphore to increase the count of
277 *******************************************************************************/
279 void threads_sem_post(sem_t *sem)
285 /* unlike sem_wait, sem_post is not interruptible */
291 vm_abort("sem_post failed: %s", strerror(errno));
295 /* threads_stopworld ***********************************************************
297 Stops the world from turning. All threads except the calling one
298 are suspended. The function returns as soon as all threads have
299 acknowledged their suspension.
301 *******************************************************************************/
303 #if defined(ENABLE_GC_CACAO)
304 void threads_stopworld(void)
306 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
313 stopworldlock->lock();
315 /* lock the threads lists */
319 #if defined(__DARWIN__)
320 /*threads_cast_darwinstop();*/
322 #elif defined(__CYGWIN__)
328 DEBUGTHREADS("stops World", self);
332 /* suspend all running threads */
333 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
334 /* don't send the signal to ourself */
339 /* don't send the signal to NEW threads (because they are not
340 completely initialized) */
342 if (t->state == THREAD_STATE_NEW)
345 /* send the signal */
347 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
350 /* increase threads count */
355 /* wait for all threads signaled to suspend */
356 for (i = 0; i < count; i++)
357 threads_sem_wait(&suspend_ack);
360 /* ATTENTION: Don't unlock the threads-lists here so that
361 non-signaled NEW threads can't change their state and execute
367 /* threads_startworld **********************************************************
369 Starts the world again after it has previously been stopped.
371 *******************************************************************************/
373 #if defined(ENABLE_GC_CACAO)
374 void threads_startworld(void)
376 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
383 #if defined(__DARWIN__)
384 /*threads_cast_darwinresume();*/
386 #elif defined(__IRIX__)
387 threads_cast_irixresume();
388 #elif defined(__CYGWIN__)
394 DEBUGTHREADS("starts World", self);
398 /* resume all thread we haltet */
399 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
400 /* don't send the signal to ourself */
405 /* don't send the signal to NEW threads (because they are not
406 completely initialized) */
408 if (t->state == THREAD_STATE_NEW)
411 /* send the signal */
413 result = threads_resume_thread(t);
416 /* increase threads count */
421 /* wait for all threads signaled to suspend */
422 for (i = 0; i < count; i++)
423 threads_sem_wait(&suspend_ack);
427 /* unlock the threads lists */
431 stopworldlock->unlock();
436 /* threads_impl_thread_init ****************************************************
438 Initialize OS-level locking constructs in threadobject.
441 t....the threadobject
443 *******************************************************************************/
445 void threads_impl_thread_init(threadobject *t)
447 /* initialize the mutex and the condition */
449 t->flc_lock = new Mutex();
450 t->flc_cond = new Condition();
452 t->waitmutex = new Mutex();
453 t->waitcond = new Condition();
455 t->suspendmutex = new Mutex();
456 t->suspendcond = new Condition();
458 #if defined(ENABLE_TLH)
463 /* threads_impl_thread_clear ***************************************************
465 Clears all fields in threadobject the way an MZERO would have
466 done. MZERO cannot be used anymore because it would mess up the
470 t....the threadobject
472 *******************************************************************************/
474 void threads_impl_thread_clear(threadobject *t)
486 #if defined(__DARWIN__)
490 t->interrupted = false;
493 t->suspended = false;
494 t->suspend_reason = 0;
498 t->_exceptionptr = NULL;
499 t->_stackframeinfo = NULL;
500 t->_localref_table = NULL;
502 #if defined(ENABLE_INTRP)
503 t->_global_sp = NULL;
506 #if defined(ENABLE_GC_CACAO)
507 t->gc_critical = false;
513 MZERO(&t->dumpinfo, dumpinfo_t, 1);
516 /* threads_impl_thread_reuse ***************************************************
518 Resets some implementation fields in threadobject. This was
519 previously done in threads_impl_thread_new.
522 t....the threadobject
524 *******************************************************************************/
526 void threads_impl_thread_reuse(threadobject *t)
528 /* get the pthread id */
530 t->tid = pthread_self();
532 #if defined(ENABLE_DEBUG_FILTER)
533 /* Initialize filter counters */
534 t->filterverbosecallctr[0] = 0;
535 t->filterverbosecallctr[1] = 0;
539 t->tracejavacallindent = 0;
540 t->tracejavacallcount = 0;
547 /* not really needed */
548 t->flc_object = NULL;
550 #if defined(ENABLE_TLH)
551 tlh_destroy(&(t->tlh));
557 /* threads_impl_thread_free ****************************************************
559 Cleanup thread stuff.
562 t....the threadobject
564 *******************************************************************************/
568 void threads_impl_thread_free(threadobject *t)
572 /* Destroy the mutex and the condition. */
576 result = pthread_cond_destroy(&(t->flc_cond));
579 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
583 result = pthread_cond_destroy(&(t->waitcond));
586 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
588 delete t->suspendmutex;
590 result = pthread_cond_destroy(&(t->suspendcond));
593 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
598 /* threads_impl_preinit ********************************************************
600 Do some early initialization of stuff required.
602 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
603 is called AFTER this function!
605 *******************************************************************************/
607 void threads_impl_preinit(void)
611 stopworldlock = new Mutex();
613 /* initialize exit mutex and condition (on exit we join all
616 mutex_join = new Mutex();
617 cond_join = new Condition();
619 #if defined(ENABLE_GC_CACAO)
620 /* initialize the GC mutex & suspend semaphore */
622 mutex_gc = new Mutex();
623 threads_sem_init(&suspend_ack, 0, 0);
626 #if !defined(HAVE___THREAD)
627 result = pthread_key_create(&thread_current_key, NULL);
629 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
634 /* threads_mutex_gc_lock *******************************************************
636 Enter the global GC mutex.
638 *******************************************************************************/
640 #if defined(ENABLE_GC_CACAO)
641 void threads_mutex_gc_lock(void)
648 /* threads_mutex_gc_unlock *****************************************************
650 Leave the global GC mutex.
652 *******************************************************************************/
654 #if defined(ENABLE_GC_CACAO)
655 void threads_mutex_gc_unlock(void)
661 /* threads_mutex_join_lock *****************************************************
663 Enter the join mutex.
665 *******************************************************************************/
667 void threads_mutex_join_lock(void)
673 /* threads_mutex_join_unlock ***************************************************
675 Leave the join mutex.
677 *******************************************************************************/
679 void threads_mutex_join_unlock(void)
681 mutex_join->unlock();
685 /* threads_impl_init ***********************************************************
687 Initializes the implementation specific bits.
689 *******************************************************************************/
691 void threads_impl_init(void)
696 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
698 /* Initialize the thread attribute object. */
700 result = pthread_attr_init(&attr);
703 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
705 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
708 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
712 /* threads_startup_thread ******************************************************
714 Thread startup function called by pthread_create.
716 Thread which have a startup.function != NULL are marked as internal
717 threads. All other threads are threated as normal Java threads.
719 NOTE: This function is not called directly by pthread_create. The Boehm GC
720 inserts its own GC_start_routine in between, which then calls
724 arg..........the argument passed to pthread_create, ie. a pointer to
725 a startupinfo struct. CAUTION: When the `psem` semaphore
726 is posted, the startupinfo struct becomes invalid! (It
727 is allocated on the stack of threads_start_thread.)
729 ******************************************************************************/
731 static void *threads_startup_thread(void *arg)
733 startupinfo *startup;
738 functionptr function;
740 #if defined(ENABLE_GC_BOEHM)
741 # if !defined(__DARWIN__)
742 struct GC_stack_base sb;
747 #if defined(ENABLE_INTRP)
748 u1 *intrp_thread_stack;
751 #if defined(ENABLE_INTRP)
752 /* create interpreter stack */
755 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
756 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
759 intrp_thread_stack = NULL;
762 /* get passed startupinfo structure and the values in there */
764 startup = (startupinfo*) arg;
767 function = startup->function;
768 psem = startup->psem;
770 /* Seems like we've encountered a situation where thread->tid was
771 not set by pthread_create. We alleviate this problem by waiting
772 for pthread_create to return. */
774 threads_sem_wait(startup->psem_first);
776 #if defined(__DARWIN__)
777 t->mach_thread = mach_thread_self();
780 /* Now that we are in the new thread, we can store the internal
781 thread data-structure in the TSD. */
783 thread_set_current(t);
785 #if defined(ENABLE_GC_BOEHM)
786 # if defined(__DARWIN__)
787 // This is currently not implemented in Boehm-GC. Just fail silently.
789 /* Register the thread with Boehm-GC. This must happen before the
790 thread allocates any memory from the GC heap.*/
792 result = GC_get_stack_base(&sb);
795 vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
797 GC_register_my_thread(&sb);
801 // Get the java.lang.Thread object for this thread.
802 java_handle_t* object = thread_get_object(t);
803 java_lang_Thread jlt(object);
805 /* set our priority */
807 threads_set_thread_priority(t->tid, jlt.get_priority());
809 /* Thread is completely initialized. */
811 thread_set_state_runnable(t);
813 /* tell threads_startup_thread that we registered ourselves */
814 /* CAUTION: *startup becomes invalid with this! */
817 threads_sem_post(psem);
819 #if defined(ENABLE_INTRP)
820 /* set interpreter stack */
823 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
826 #if defined(ENABLE_JVMTI)
827 /* fire thread start event */
830 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
833 DEBUGTHREADS("starting", t);
835 /* find and run the Thread.run()V method if no other function was passed */
837 if (function == NULL) {
838 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
839 /* We need to start the run method of
840 java.lang.VMThread. Since this is a final class, we can use
841 the class object directly. */
843 c = class_java_lang_VMThread;
844 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
845 LLNI_class_get(object, c);
847 # error unknown classpath configuration
850 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
853 vm_abort("threads_startup_thread: run() method not found in class");
855 /* set ThreadMXBean variables */
857 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
858 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
860 /* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
861 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
862 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
863 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
866 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
868 // We need to start the run method of java.lang.VMThread.
869 java_lang_VMThread jlvmt(jlt.get_vmThread());
870 java_handle_t* h = jlvmt.get_handle();
872 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
874 java_handle_t* h = jlt.get_handle();
877 # error unknown classpath configuration
880 /* Run the thread. */
882 (void) vm_call_method(m, h);
885 /* set ThreadMXBean variables */
887 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
888 /* _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
890 /* if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
891 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
892 /* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
893 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
896 /* call passed function, e.g. finalizer_thread */
901 DEBUGTHREADS("stopping", t);
903 #if defined(ENABLE_JVMTI)
904 /* fire thread end event */
907 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
910 /* We ignore the return value. */
912 (void) thread_detach_current_thread();
914 /* set ThreadMXBean variables */
916 /* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
923 /* threads_impl_thread_start ***************************************************
925 Start a thread in the JVM. Both (vm internal and java) thread
929 thread....the thread object
930 f.........function to run in the new thread. NULL means that the
931 "run" method of the object `t` should be called
933 ******************************************************************************/
935 void threads_impl_thread_start(threadobject *thread, functionptr f)
943 /* fill startupinfo structure passed by pthread_create to
944 * threads_startup_thread */
946 startup.thread = thread;
947 startup.function = f; /* maybe we don't call Thread.run()V */
949 startup.psem_first = &sem_first;
951 threads_sem_init(&sem, 0, 0);
952 threads_sem_init(&sem_first, 0, 0);
954 /* Initialize thread attributes. */
956 result = pthread_attr_init(&attr);
959 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
961 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
964 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
966 /* initialize thread stacksize */
968 result = pthread_attr_setstacksize(&attr, opt_stacksize);
971 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
973 /* create the thread */
975 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
978 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
980 /* destroy the thread attributes */
982 result = pthread_attr_destroy(&attr);
985 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
987 /* signal that pthread_create has returned, so thread->tid is valid */
989 threads_sem_post(&sem_first);
991 /* wait here until the thread has entered itself into the thread list */
993 threads_sem_wait(&sem);
998 sem_destroy(&sem_first);
1002 /* threads_set_thread_priority *************************************************
1004 Set the priority of the given thread.
1007 tid..........thread id
1008 priority.....priority to set
1010 ******************************************************************************/
1012 void threads_set_thread_priority(pthread_t tid, int priority)
1014 struct sched_param schedp;
1017 pthread_getschedparam(tid, &policy, &schedp);
1018 schedp.sched_priority = priority;
1019 pthread_setschedparam(tid, policy, &schedp);
1024 * Detaches the current thread from the VM.
1026 * @return true on success, false otherwise
1028 bool thread_detach_current_thread(void)
1030 threadobject* t = thread_get_current();
1036 /* If the given thread has already been detached, this operation
1039 if (thread_is_attached(t) == false)
1042 DEBUGTHREADS("detaching", t);
1044 java_handle_t* object = thread_get_object(t);
1045 java_lang_Thread jlt(object);
1047 #if defined(ENABLE_JAVASE)
1048 java_handle_t* group = jlt.get_group();
1050 /* If there's an uncaught exception, call uncaughtException on the
1051 thread's exception handler, or the thread's group if this is
1054 java_handle_t* e = exceptions_get_and_clear_exception();
1057 /* We use the type void* for handler here, as it's not trivial
1058 to build the java_lang_Thread_UncaughtExceptionHandler
1059 header file with cacaoh. */
1061 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1063 java_handle_t* handler = jlt.get_exceptionHandler();
1065 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1067 java_handle_t* handler = jlt.get_uncaughtExceptionHandler();
1074 if (handler != NULL) {
1075 LLNI_class_get(handler, c);
1076 h = (java_handle_t *) handler;
1079 LLNI_class_get(group, c);
1080 h = (java_handle_t *) group;
1083 methodinfo* m = class_resolveclassmethod(c,
1084 utf_uncaughtException,
1085 utf_java_lang_Thread_java_lang_Throwable__V,
1092 (void) vm_call_method(m, h, object, e);
1094 if (exceptions_get_exception())
1098 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1100 /* Remove thread from the thread group. */
1102 if (group != NULL) {
1104 LLNI_class_get(group, c);
1106 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1107 methodinfo* m = class_resolveclassmethod(c,
1109 utf_java_lang_Thread__V,
1110 class_java_lang_ThreadGroup,
1112 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
1113 methodinfo* m = class_resolveclassmethod(c,
1115 utf_java_lang_Thread__V,
1116 class_java_lang_ThreadGroup,
1119 # error unknown classpath configuration
1125 (void) vm_call_method(m, group, object);
1127 if (exceptions_get_exception())
1130 // Clear the ThreadGroup in the Java thread object (Mauve
1131 // test: gnu/testlet/java/lang/Thread/getThreadGroup).
1132 jlt.set_group(NULL);
1136 /* Thread has terminated. */
1138 thread_set_state_terminated(t);
1140 /* Notify all threads waiting on this thread. These are joining
1143 /* XXX Care about exceptions? */
1144 (void) lock_monitor_enter(jlt.get_handle());
1146 lock_notify_all_object(jlt.get_handle());
1148 /* XXX Care about exceptions? */
1149 (void) lock_monitor_exit(jlt.get_handle());
1151 /* Enter the join-mutex before calling thread_free, so
1152 threads_join_all_threads gets the correct number of non-daemon
1155 threads_mutex_join_lock();
1157 /* Free the internal thread data-structure. */
1161 /* Signal that this thread has finished and leave the mutex. */
1163 cond_join->signal();
1164 threads_mutex_join_unlock();
1170 /* threads_suspend_thread ******************************************************
1172 Suspend the passed thread. Execution stops until the thread
1173 is explicitly resumend again.
1176 reason.....Reason for suspending this thread.
1178 *******************************************************************************/
1180 bool threads_suspend_thread(threadobject *thread, s4 reason)
1182 /* acquire the suspendmutex */
1183 thread->suspendmutex->lock();
1185 if (thread->suspended) {
1186 thread->suspendmutex->unlock();
1190 /* set the reason for the suspension */
1191 thread->suspend_reason = reason;
1193 /* send the suspend signal to the thread */
1194 assert(thread != THREADOBJECT);
1195 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1196 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1199 /* REMEMBER: do not release the suspendmutex, this is done
1200 by the thread itself in threads_suspend_ack(). */
1206 /* threads_suspend_ack *********************************************************
1208 Acknowledges the suspension of the current thread.
1211 pc.....The PC where the thread suspended its execution.
1212 sp.....The SP before the thread suspended its execution.
1214 *******************************************************************************/
1216 #if defined(ENABLE_GC_CACAO)
1217 void threads_suspend_ack(u1* pc, u1* sp)
1219 threadobject *thread;
1221 thread = THREADOBJECT;
1223 assert(thread->suspend_reason != 0);
1225 /* TODO: remember dump memory size */
1227 /* inform the GC about the suspension */
1228 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1230 /* check if the GC wants to leave the thread running */
1231 if (!gc_suspend(thread, pc, sp)) {
1233 /* REMEMBER: we do not unlock the suspendmutex because the thread
1234 will suspend itself again at a later time */
1240 /* mark this thread as suspended and remember the PC */
1242 thread->suspended = true;
1244 /* if we are stopping the world, we should send a global ack */
1245 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1246 threads_sem_post(&suspend_ack);
1249 DEBUGTHREADS("suspending", thread);
1251 /* release the suspension mutex and wait till we are resumed */
1252 thread->suspendcond->wait(thread->suspendmutex);
1254 DEBUGTHREADS("resuming", thread);
1256 /* if we are stopping the world, we should send a global ack */
1257 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1258 threads_sem_post(&suspend_ack);
1261 /* TODO: free dump memory */
1263 /* release the suspendmutex */
1264 thread->suspendmutex->unlock();
1269 /* threads_resume_thread *******************************************************
1271 Resumes the execution of the passed thread.
1273 *******************************************************************************/
1275 #if defined(ENABLE_GC_CACAO)
1276 bool threads_resume_thread(threadobject *thread)
1278 /* acquire the suspendmutex */
1279 thread->suspendmutex->lock();
1281 if (!thread->suspended) {
1282 thread->suspendmutex->unlock();
1286 thread->suspended = false;
1288 /* tell everyone that the thread should resume */
1289 assert(thread != THREADOBJECT);
1290 thread->suspendcond->broadcast();
1292 /* release the suspendmutex */
1293 thread->suspendmutex->unlock();
1300 /* threads_join_all_threads ****************************************************
1302 Join all non-daemon threads.
1304 *******************************************************************************/
1306 void threads_join_all_threads(void)
1310 /* get current thread */
1314 /* This thread is waiting for all non-daemon threads to exit. */
1316 thread_set_state_waiting(t);
1318 /* enter join mutex */
1320 threads_mutex_join_lock();
1322 /* Wait for condition as long as we have non-daemon threads. We
1323 compare against 1 because the current (main thread) is also a
1324 non-daemon thread. */
1326 while (threadlist_get_non_daemons() > 1)
1327 cond_join->wait(mutex_join);
1329 /* leave join mutex */
1331 threads_mutex_join_unlock();
1335 /* threads_timespec_earlier ****************************************************
1337 Return true if timespec tv1 is earlier than timespec tv2.
1340 tv1..........first timespec
1341 tv2..........second timespec
1344 true, if the first timespec is earlier
1346 *******************************************************************************/
1348 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1349 const struct timespec *tv2)
1351 return (tv1->tv_sec < tv2->tv_sec)
1353 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1357 /* threads_current_time_is_earlier_than ****************************************
1359 Check if the current time is earlier than the given timespec.
1362 tv...........the timespec to compare against
1365 true, if the current time is earlier
1367 *******************************************************************************/
1369 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1371 struct timeval tvnow;
1372 struct timespec tsnow;
1374 /* get current time */
1376 if (gettimeofday(&tvnow, NULL) != 0)
1377 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1379 /* convert it to a timespec */
1381 tsnow.tv_sec = tvnow.tv_sec;
1382 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1384 /* compare current time with the given timespec */
1386 return threads_timespec_earlier(&tsnow, tv);
1390 /* threads_wait_with_timeout ***************************************************
1392 Wait until the given point in time on a monitor until either
1393 we are notified, we are interrupted, or the time is up.
1396 t............the current thread
1397 wakeupTime...absolute (latest) wakeup time
1398 If both tv_sec and tv_nsec are zero, this function
1399 waits for an unlimited amount of time.
1401 *******************************************************************************/
1403 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1405 // Acquire the waitmutex.
1406 t->waitmutex->lock();
1408 /* wait on waitcond */
1410 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1412 while (!t->interrupted && !t->signaled
1413 && threads_current_time_is_earlier_than(wakeupTime))
1415 thread_set_state_timed_waiting(t);
1417 t->waitcond->timedwait(t->waitmutex, wakeupTime);
1419 thread_set_state_runnable(t);
1424 while (!t->interrupted && !t->signaled) {
1425 thread_set_state_waiting(t);
1427 t->waitcond->wait(t->waitmutex);
1429 thread_set_state_runnable(t);
1433 // Release the waitmutex.
1434 t->waitmutex->unlock();
1438 /* threads_wait_with_timeout_relative ******************************************
1440 Wait for the given maximum amount of time on a monitor until either
1441 we are notified, we are interrupted, or the time is up.
1444 t............the current thread
1445 millis.......milliseconds to wait
1446 nanos........nanoseconds to wait
1448 *******************************************************************************/
1450 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1453 struct timespec wakeupTime;
1455 /* calculate the the (latest) wakeup time */
1457 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1461 threads_wait_with_timeout(thread, &wakeupTime);
1465 /* threads_calc_absolute_time **************************************************
1467 Calculate the absolute point in time a given number of ms and ns from now.
1470 millis............milliseconds from now
1471 nanos.............nanoseconds from now
1474 *tm...............receives the timespec of the absolute point in time
1476 *******************************************************************************/
1478 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1480 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1483 gettimeofday(&tv, NULL);
1484 tv.tv_sec += millis / 1000;
1486 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1487 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1488 tm->tv_nsec = nsec % 1000000000;
1497 /* threads_thread_interrupt ****************************************************
1499 Interrupt the given thread.
1501 The thread gets the "waitcond" signal and
1502 its interrupted flag is set to true.
1505 thread............the thread to interrupt
1507 *******************************************************************************/
1509 void threads_thread_interrupt(threadobject *t)
1511 /* Signal the thread a "waitcond" and tell it that it has been
1514 t->waitmutex->lock();
1516 DEBUGTHREADS("interrupted", t);
1518 /* Interrupt blocking system call using a signal. */
1520 pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL);
1522 t->waitcond->signal();
1524 t->interrupted = true;
1526 t->waitmutex->unlock();
1531 * Sleep the current thread for the specified amount of time.
1533 * @param millis Milliseconds to sleep.
1534 * @param nanos Nanoseconds to sleep.
1536 void threads_sleep(int64_t millis, int32_t nanos)
1539 struct timespec wakeupTime;
1543 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1544 exceptions_throw_illegalargumentexception();
1548 t = thread_get_current();
1550 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1551 /* Clear interrupted flag (Mauve test:
1552 gnu/testlet/java/lang/Thread/interrupt). */
1554 thread_set_interrupted(t, false);
1556 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1557 exceptions_throw_interruptedexception();
1561 // (Note taken from classpath/vm/reference/java/lang/VMThread.java (sleep))
1562 // Note: JDK treats a zero length sleep is like Thread.yield(),
1563 // without checking the interrupted status of the thread. It's
1564 // unclear if this is a bug in the implementation or the spec.
1565 // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 */
1566 if (millis == 0 && nanos == 0) {
1570 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1572 threads_wait_with_timeout(t, &wakeupTime);
1574 interrupted = thread_is_interrupted(t);
1577 thread_set_interrupted(t, false);
1579 // An other exception could have been thrown
1580 // (e.g. ThreadDeathException).
1581 if (!exceptions_get_exception())
1582 exceptions_throw_interruptedexception();
1588 /* threads_yield ***************************************************************
1590 Yield to the scheduler.
1592 *******************************************************************************/
1594 void threads_yield(void)
1599 #if defined(ENABLE_TLH)
1601 void threads_tlh_add_frame() {
1602 tlh_add_frame(&(THREADOBJECT->tlh));
1605 void threads_tlh_remove_frame() {
1606 tlh_remove_frame(&(THREADOBJECT->tlh));
1615 * These are local overrides for various environment variables in Emacs.
1616 * Please do not remove this and leave it at the end of the file, where
1617 * Emacs will automagically detect them.
1618 * ---------------------------------------------------------------------
1621 * indent-tabs-mode: t
1625 * vim:noexpandtab:sw=4:ts=4: