1 /* src/threads/posix/thread-posix.c - 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 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
47 # include "machine-instr.h"
49 # include "threads/posix/generic-primitives.h"
52 #include "mm/gc-common.h"
53 #include "mm/memory.h"
55 #if defined(ENABLE_GC_CACAO)
56 # include "mm/cacao-gc/gc.h"
59 #include "native/jni.h"
60 #include "native/llni.h"
61 #include "native/native.h"
63 #include "native/include/java_lang_Object.h"
64 #include "native/include/java_lang_String.h"
65 #include "native/include/java_lang_Throwable.h"
66 #include "native/include/java_lang_Thread.h"
68 #if defined(ENABLE_JAVASE)
69 # include "native/include/java_lang_ThreadGroup.h"
72 #if defined(WITH_CLASSPATH_GNU)
73 # include "native/include/java_lang_VMThread.h"
76 #include "threads/lock-common.h"
77 #include "threads/mutex.h"
78 #include "threads/threadlist.h"
79 #include "threads/thread.h"
81 #include "toolbox/logging.h"
83 #include "vm/builtin.h"
84 #include "vm/exceptions.h"
85 #include "vm/global.h"
86 #include "vm/stringlocal.h"
89 #include "vm/jit/asmpart.h"
91 #include "vmcore/options.h"
93 #if defined(ENABLE_STATISTICS)
94 # include "vmcore/statistics.h"
97 #if !defined(__DARWIN__)
98 # if defined(__LINUX__)
99 # define GC_LINUX_THREADS
100 # elif defined(__IRIX__)
101 # define GC_IRIX_THREADS
103 # include <semaphore.h>
104 # if defined(ENABLE_GC_BOEHM)
105 # include "mm/boehm-gc/include/gc.h"
109 #if defined(ENABLE_JVMTI)
110 #include "native/jvmti/cacaodbg.h"
113 #if defined(__DARWIN__)
114 /* Darwin has no working semaphore implementation. This one is taken
118 This is a very simple semaphore implementation for darwin. It
119 is implemented in terms of pthreads calls so it isn't async signal
120 safe. This isn't a problem because signals aren't used to
121 suspend threads on darwin.
124 static int sem_init(sem_t *sem, int pshared, int value)
131 mutex_init(&sem->mutex, NULL)
133 if (pthread_cond_init(&sem->cond, NULL) < 0)
139 static int sem_post(sem_t *sem)
141 mutex_lock(&sem->mutex)
145 if (pthread_cond_signal(&sem->cond) < 0) {
146 mutex_unlock(&sem->mutex);
150 mutex_unlock(&sem->mutex)
155 static int sem_wait(sem_t *sem)
157 mutex_lock(&sem->mutex)
159 while (sem->value == 0) {
160 pthread_cond_wait(&sem->cond, &sem->mutex);
165 mutex_unlock(&sem->mutex)
170 static int sem_destroy(sem_t *sem)
172 if (pthread_cond_destroy(&sem->cond) < 0)
175 mutex_destroy(&sem->mutex)
179 #endif /* defined(__DARWIN__) */
182 /* internally used constants **************************************************/
184 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
185 #define STOPWORLD_FROM_GC 1
186 #define STOPWORLD_FROM_CLASS_NUMBERING 2
189 /* startupinfo *****************************************************************
191 Struct used to pass info from threads_start_thread to
192 threads_startup_thread.
194 ******************************************************************************/
197 threadobject *thread; /* threadobject for this thread */
198 functionptr function; /* function to run in the new thread */
199 sem_t *psem; /* signals when thread has been entered */
200 /* in the thread list */
201 sem_t *psem_first; /* signals when pthread_create has returned */
205 /* prototypes *****************************************************************/
207 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
210 /******************************************************************************/
211 /* GLOBAL VARIABLES */
212 /******************************************************************************/
214 /* the thread object of the current thread */
215 /* This is either a thread-local variable defined with __thread, or */
216 /* a thread-specific value stored with key threads_current_threadobject_key. */
217 #if defined(HAVE___THREAD)
218 __thread threadobject *thread_current;
220 pthread_key_t thread_current_key;
223 /* global mutex for stop-the-world */
224 static mutex_t stopworldlock;
226 #if defined(ENABLE_GC_CACAO)
227 /* global mutex for the GC */
228 static mutex_t mutex_gc;
231 /* global mutex and condition for joining threads on exit */
232 static mutex_t mutex_join;
233 static pthread_cond_t cond_join;
235 /* XXX We disable that whole bunch of code until we have the exact-GC
240 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
242 static volatile int stopworldwhere;
244 /* semaphore used for acknowleding thread suspension */
245 static sem_t suspend_ack;
246 #if defined(__IRIX__)
247 static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
248 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
253 /* mutexes used by the fake atomic instructions */
254 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
255 mutex_t _cas_lock = MUTEX_INITIALIZER;
256 mutex_t _mb_lock = MUTEX_INITIALIZER;
260 /* threads_sem_init ************************************************************
262 Initialize a semaphore. Checks against errors and interruptions.
265 sem..............the semaphore to initialize
266 shared...........true if this semaphore will be shared between processes
267 value............the initial value for the semaphore
269 *******************************************************************************/
271 void threads_sem_init(sem_t *sem, bool shared, int value)
278 r = sem_init(sem, shared, value);
281 } while (errno == EINTR);
283 vm_abort("sem_init failed: %s", strerror(errno));
287 /* threads_sem_wait ************************************************************
289 Wait for a semaphore, non-interruptible.
291 IMPORTANT: Always use this function instead of `sem_wait` directly, as
292 `sem_wait` may be interrupted by signals!
295 sem..............the semaphore to wait on
297 *******************************************************************************/
299 void threads_sem_wait(sem_t *sem)
309 } while (errno == EINTR);
311 vm_abort("sem_wait failed: %s", strerror(errno));
315 /* threads_sem_post ************************************************************
317 Increase the count of a semaphore. Checks for errors.
320 sem..............the semaphore to increase the count of
322 *******************************************************************************/
324 void threads_sem_post(sem_t *sem)
330 /* unlike sem_wait, sem_post is not interruptible */
336 vm_abort("sem_post failed: %s", strerror(errno));
340 /* lock_stopworld **************************************************************
342 Enter the stopworld lock, specifying why the world shall be stopped.
345 where........ STOPWORLD_FROM_GC (1) from within GC
346 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
348 ******************************************************************************/
350 void lock_stopworld(int where)
352 mutex_lock(&stopworldlock);
353 /* stopworldwhere = where; */
357 /* unlock_stopworld ************************************************************
359 Release the stopworld lock.
361 ******************************************************************************/
363 void unlock_stopworld(void)
365 /* stopworldwhere = 0; */
366 mutex_unlock(&stopworldlock);
369 /* XXX We disable that whole bunch of code until we have the exact-GC
374 #if !defined(__DARWIN__)
375 /* Caller must hold threadlistlock */
376 static s4 threads_cast_sendsignals(s4 sig)
384 /* iterate over all started threads */
388 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
389 /* don't send the signal to ourself */
394 /* don't send the signal to NEW threads (because they are not
395 completely initialized) */
397 if (t->state == THREAD_STATE_NEW)
400 /* send the signal */
402 pthread_kill(t->tid, sig);
404 /* increase threads count */
414 static void threads_cast_darwinstop(void)
416 threadobject *tobj = mainthreadobj;
417 threadobject *self = THREADOBJECT;
422 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
423 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
424 #if defined(__I386__)
425 i386_thread_state_t thread_state;
427 ppc_thread_state_t thread_state;
429 mach_port_t thread = tobj->mach_thread;
432 r = thread_suspend(thread);
434 if (r != KERN_SUCCESS)
435 vm_abort("thread_suspend failed");
437 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
438 &thread_state_count);
440 if (r != KERN_SUCCESS)
441 vm_abort("thread_get_state failed");
443 md_critical_section_restart((ucontext_t *) &thread_state);
445 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
448 if (r != KERN_SUCCESS)
449 vm_abort("thread_set_state failed");
453 } while (tobj != mainthreadobj);
456 static void threads_cast_darwinresume(void)
458 threadobject *tobj = mainthreadobj;
459 threadobject *self = THREADOBJECT;
464 mach_port_t thread = tobj->mach_thread;
467 r = thread_resume(thread);
469 if (r != KERN_SUCCESS)
470 vm_abort("thread_resume failed");
474 } while (tobj != mainthreadobj);
479 #if defined(__IRIX__)
480 static void threads_cast_irixresume(void)
482 mutex_lock(&suspend_ack_lock);
483 pthread_cond_broadcast(&suspend_cond);
484 mutex_unlock(&suspend_ack_lock);
488 #if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
489 static void threads_sigsuspend_handler(ucontext_t *_uc)
494 /* XXX TWISTI: this is just a quick hack */
495 #if defined(ENABLE_JIT)
496 md_critical_section_restart(_uc);
499 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
500 (not POSIX async-safe). */
501 #if defined(__IRIX__)
502 mutex_lock(&suspend_ack_lock);
503 threads_sem_post(&suspend_ack);
504 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
505 mutex_unlock(&suspend_ack_lock);
506 #elif defined(__CYGWIN__)
513 sigdelset(&sigs, sig);
522 /* threads_stopworld ***********************************************************
524 Stops the world from turning. All threads except the calling one
525 are suspended. The function returns as soon as all threads have
526 acknowledged their suspension.
528 *******************************************************************************/
530 #if !defined(DISABLE_GC)
531 void threads_stopworld(void)
533 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
540 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
542 /* lock the threads lists */
546 #if defined(__DARWIN__)
547 /*threads_cast_darwinstop();*/
549 #elif defined(__CYGWIN__)
555 DEBUGTHREADS("stops World", self);
559 /* suspend all running threads */
560 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
561 /* don't send the signal to ourself */
566 /* don't send the signal to NEW threads (because they are not
567 completely initialized) */
569 if (t->state == THREAD_STATE_NEW)
572 /* send the signal */
574 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
577 /* increase threads count */
582 /* wait for all threads signaled to suspend */
583 for (i = 0; i < count; i++)
584 threads_sem_wait(&suspend_ack);
587 /* ATTENTION: Don't unlock the threads-lists here so that
588 non-signaled NEW threads can't change their state and execute
591 #endif /* !defined(DISABLE_GC) */
594 /* threads_startworld **********************************************************
596 Starts the world again after it has previously been stopped.
598 *******************************************************************************/
600 #if !defined(DISABLE_GC)
601 void threads_startworld(void)
603 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
610 #if defined(__DARWIN__)
611 /*threads_cast_darwinresume();*/
613 #elif defined(__IRIX__)
614 threads_cast_irixresume();
615 #elif defined(__CYGWIN__)
621 DEBUGTHREADS("starts World", self);
625 /* resume all thread we haltet */
626 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
627 /* don't send the signal to ourself */
632 /* don't send the signal to NEW threads (because they are not
633 completely initialized) */
635 if (t->state == THREAD_STATE_NEW)
638 /* send the signal */
640 result = threads_resume_thread(t);
643 /* increase threads count */
648 /* wait for all threads signaled to suspend */
649 for (i = 0; i < count; i++)
650 threads_sem_wait(&suspend_ack);
654 /* unlock the threads lists */
663 /* threads_impl_thread_init ****************************************************
665 Initialize OS-level locking constructs in threadobject.
668 t....the threadobject
670 *******************************************************************************/
672 void threads_impl_thread_init(threadobject *t)
676 /* initialize the mutex and the condition */
678 mutex_init(&t->flc_lock);
680 result = pthread_cond_init(&t->flc_cond, NULL);
682 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
684 mutex_init(&(t->waitmutex));
686 result = pthread_cond_init(&(t->waitcond), NULL);
688 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
690 mutex_init(&(t->suspendmutex));
692 result = pthread_cond_init(&(t->suspendcond), NULL);
694 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
697 /* threads_impl_thread_clear ***************************************************
699 Clears all fields in threadobject the way an MZERO would have
700 done. MZERO cannot be used anymore because it would mess up the
704 t....the threadobject
706 *******************************************************************************/
708 void threads_impl_thread_clear(threadobject *t)
720 #if defined(__DARWIN__)
724 t->interrupted = false;
728 t->suspended = false;
729 t->suspend_reason = 0;
733 t->_exceptionptr = NULL;
734 t->_stackframeinfo = NULL;
735 t->_localref_table = NULL;
737 #if defined(ENABLE_INTRP)
738 t->_global_sp = NULL;
741 #if defined(ENABLE_GC_CACAO)
742 t->gc_critical = false;
748 MZERO(&t->dumpinfo, dumpinfo_t, 1);
751 /* threads_impl_thread_reuse ***************************************************
753 Resets some implementation fields in threadobject. This was
754 previously done in threads_impl_thread_new.
757 t....the threadobject
759 *******************************************************************************/
761 void threads_impl_thread_reuse(threadobject *t)
763 /* get the pthread id */
765 t->tid = pthread_self();
767 #if defined(ENABLE_DEBUG_FILTER)
768 /* Initialize filter counters */
769 t->filterverbosecallctr[0] = 0;
770 t->filterverbosecallctr[1] = 0;
774 t->tracejavacallindent = 0;
775 t->tracejavacallcount = 0;
782 /* not really needed */
783 t->flc_object = NULL;
787 /* threads_impl_thread_free ****************************************************
789 Cleanup thread stuff.
792 t....the threadobject
794 *******************************************************************************/
798 void threads_impl_thread_free(threadobject *t)
802 /* Destroy the mutex and the condition. */
804 mutex_destroy(&(t->flc_lock));
806 result = pthread_cond_destroy(&(t->flc_cond));
809 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
811 mutex_destroy(&(t->waitmutex));
813 result = pthread_cond_destroy(&(t->waitcond));
816 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
818 mutex_destroy(&(t->suspendmutex));
820 result = pthread_cond_destroy(&(t->suspendcond));
823 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
828 /* threads_impl_preinit ********************************************************
830 Do some early initialization of stuff required.
832 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
833 is called AFTER this function!
835 *******************************************************************************/
837 void threads_impl_preinit(void)
841 mutex_init(&stopworldlock);
843 /* initialize exit mutex and condition (on exit we join all
846 mutex_init(&mutex_join);
848 result = pthread_cond_init(&cond_join, NULL);
850 vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
852 #if defined(ENABLE_GC_CACAO)
853 /* initialize the GC mutext */
855 mutex_init(&mutex_gc);
858 #if !defined(HAVE___THREAD)
859 result = pthread_key_create(&thread_current_key, NULL);
861 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
864 threads_sem_init(&suspend_ack, 0, 0);
868 /* threads_mutex_gc_lock *******************************************************
870 Enter the global GC mutex.
872 *******************************************************************************/
874 #if defined(ENABLE_GC_CACAO)
875 void threads_mutex_gc_lock(void)
877 mutex_lock(&mutex_gc);
882 /* threads_mutex_gc_unlock *****************************************************
884 Leave the global GC mutex.
886 *******************************************************************************/
888 #if defined(ENABLE_GC_CACAO)
889 void threads_mutex_gc_unlock(void)
891 mutex_unlock(&mutex_gc);
895 /* threads_mutex_join_lock *****************************************************
897 Enter the join mutex.
899 *******************************************************************************/
901 void threads_mutex_join_lock(void)
903 mutex_lock(&mutex_join);
907 /* threads_mutex_join_unlock ***************************************************
909 Leave the join mutex.
911 *******************************************************************************/
913 void threads_mutex_join_unlock(void)
915 mutex_unlock(&mutex_join);
919 /* threads_impl_init ***********************************************************
921 Initializes the implementation specific bits.
923 *******************************************************************************/
925 void threads_impl_init(void)
930 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
932 /* Initialize the thread attribute object. */
934 result = pthread_attr_init(&attr);
937 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
939 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
942 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
946 /* threads_startup_thread ******************************************************
948 Thread startup function called by pthread_create.
950 Thread which have a startup.function != NULL are marked as internal
951 threads. All other threads are threated as normal Java threads.
953 NOTE: This function is not called directly by pthread_create. The Boehm GC
954 inserts its own GC_start_routine in between, which then calls
958 arg..........the argument passed to pthread_create, ie. a pointer to
959 a startupinfo struct. CAUTION: When the `psem` semaphore
960 is posted, the startupinfo struct becomes invalid! (It
961 is allocated on the stack of threads_start_thread.)
963 ******************************************************************************/
965 static void *threads_startup_thread(void *arg)
967 startupinfo *startup;
968 threadobject *thread;
969 java_lang_Thread *object;
970 #if defined(WITH_CLASSPATH_GNU)
971 java_lang_VMThread *vmt;
977 functionptr function;
979 #if defined(ENABLE_INTRP)
980 u1 *intrp_thread_stack;
982 /* create interpreter stack */
985 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
986 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
989 intrp_thread_stack = NULL;
992 /* get passed startupinfo structure and the values in there */
996 thread = startup->thread;
997 function = startup->function;
998 psem = startup->psem;
1000 /* Seems like we've encountered a situation where thread->tid was
1001 not set by pthread_create. We alleviate this problem by waiting
1002 for pthread_create to return. */
1004 threads_sem_wait(startup->psem_first);
1006 #if defined(__DARWIN__)
1007 thread->mach_thread = mach_thread_self();
1010 /* Store the internal thread data-structure in the TSD. */
1012 thread_set_current(thread);
1014 /* get the java.lang.Thread object for this thread */
1016 object = (java_lang_Thread *) thread_get_object(thread);
1018 /* set our priority */
1020 threads_set_thread_priority(thread->tid, LLNI_field_direct(object, priority));
1022 /* thread is completely initialized */
1024 threads_thread_state_runnable(thread);
1026 /* tell threads_startup_thread that we registered ourselves */
1027 /* CAUTION: *startup becomes invalid with this! */
1030 threads_sem_post(psem);
1032 #if defined(ENABLE_INTRP)
1033 /* set interpreter stack */
1036 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1039 #if defined(ENABLE_JVMTI)
1040 /* fire thread start event */
1043 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1046 DEBUGTHREADS("starting", thread);
1048 /* find and run the Thread.run()V method if no other function was passed */
1050 if (function == NULL) {
1051 #if defined(WITH_CLASSPATH_GNU)
1052 /* We need to start the run method of
1053 java.lang.VMThread. Since this is a final class, we can use
1054 the class object directly. */
1056 c = class_java_lang_VMThread;
1057 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1058 LLNI_class_get(object, c);
1060 # error unknown classpath configuration
1063 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1066 vm_abort("threads_startup_thread: run() method not found in class");
1068 /* set ThreadMXBean variables */
1070 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1071 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1073 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1074 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1075 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1076 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1078 #if defined(WITH_CLASSPATH_GNU)
1079 /* we need to start the run method of java.lang.VMThread */
1081 LLNI_field_get_ref(object, vmThread, vmt);
1082 o = (java_handle_t *) vmt;
1084 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1085 o = (java_handle_t *) object;
1087 # error unknown classpath configuration
1090 /* run the thread */
1092 (void) vm_call_method(m, o);
1095 /* set ThreadMXBean variables */
1097 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1098 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1100 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1101 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1102 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1103 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1105 /* call passed function, e.g. finalizer_thread */
1110 DEBUGTHREADS("stopping", thread);
1112 #if defined(ENABLE_JVMTI)
1113 /* fire thread end event */
1116 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1119 /* We ignore the return value. */
1121 (void) threads_detach_thread(thread);
1123 /* set ThreadMXBean variables */
1125 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1131 /* threads_impl_thread_start ***************************************************
1133 Start a thread in the JVM. Both (vm internal and java) thread
1137 thread....the thread object
1138 f.........function to run in the new thread. NULL means that the
1139 "run" method of the object `t` should be called
1141 ******************************************************************************/
1143 void threads_impl_thread_start(threadobject *thread, functionptr f)
1147 pthread_attr_t attr;
1148 startupinfo startup;
1151 /* fill startupinfo structure passed by pthread_create to
1152 * threads_startup_thread */
1154 startup.thread = thread;
1155 startup.function = f; /* maybe we don't call Thread.run()V */
1156 startup.psem = &sem;
1157 startup.psem_first = &sem_first;
1159 threads_sem_init(&sem, 0, 0);
1160 threads_sem_init(&sem_first, 0, 0);
1162 /* Initialize thread attributes. */
1164 result = pthread_attr_init(&attr);
1167 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
1169 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1172 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
1174 /* initialize thread stacksize */
1176 result = pthread_attr_setstacksize(&attr, opt_stacksize);
1179 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
1181 /* create the thread */
1183 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1186 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1188 /* destroy the thread attributes */
1190 result = pthread_attr_destroy(&attr);
1193 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1195 /* signal that pthread_create has returned, so thread->tid is valid */
1197 threads_sem_post(&sem_first);
1199 /* wait here until the thread has entered itself into the thread list */
1201 threads_sem_wait(&sem);
1206 sem_destroy(&sem_first);
1210 /* threads_set_thread_priority *************************************************
1212 Set the priority of the given thread.
1215 tid..........thread id
1216 priority.....priority to set
1218 ******************************************************************************/
1220 void threads_set_thread_priority(pthread_t tid, int priority)
1222 struct sched_param schedp;
1225 pthread_getschedparam(tid, &policy, &schedp);
1226 schedp.sched_priority = priority;
1227 pthread_setschedparam(tid, policy, &schedp);
1231 /* threads_detach_thread *******************************************************
1233 Detaches the passed thread from the VM. Used in JNI.
1235 *******************************************************************************/
1237 bool threads_detach_thread(threadobject *t)
1240 java_lang_Thread *object;
1242 #if defined(ENABLE_JAVASE)
1243 java_lang_ThreadGroup *group;
1250 /* If the given thread has already been detached, this operation
1253 result = thread_is_attached(t);
1255 if (result == false)
1258 DEBUGTHREADS("detaching", t);
1260 object = (java_lang_Thread *) thread_get_object(t);
1262 #if defined(ENABLE_JAVASE)
1263 LLNI_field_get_ref(object, group, group);
1265 /* If there's an uncaught exception, call uncaughtException on the
1266 thread's exception handler, or the thread's group if this is
1269 e = exceptions_get_and_clear_exception();
1272 /* We use the type void* for handler here, as it's not trivial
1273 to build the java_lang_Thread_UncaughtExceptionHandler
1274 header file with cacaoh. */
1276 # if defined(WITH_CLASSPATH_GNU)
1277 LLNI_field_get_ref(object, exceptionHandler, handler);
1278 # elif defined(WITH_CLASSPATH_SUN)
1279 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1282 if (handler != NULL) {
1283 LLNI_class_get(handler, c);
1284 o = (java_handle_t *) handler;
1287 LLNI_class_get(group, c);
1288 o = (java_handle_t *) group;
1291 m = class_resolveclassmethod(c,
1292 utf_uncaughtException,
1293 utf_java_lang_Thread_java_lang_Throwable__V,
1300 (void) vm_call_method(m, o, object, e);
1302 if (exceptions_get_exception())
1306 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1308 /* Remove thread from the thread group. */
1310 if (group != NULL) {
1311 LLNI_class_get(group, c);
1313 # if defined(WITH_CLASSPATH_GNU)
1314 m = class_resolveclassmethod(c,
1316 utf_java_lang_Thread__V,
1317 class_java_lang_ThreadGroup,
1319 # elif defined(WITH_CLASSPATH_SUN)
1320 m = class_resolveclassmethod(c,
1322 utf_java_lang_Thread__V,
1323 class_java_lang_ThreadGroup,
1326 # error unknown classpath configuration
1332 o = (java_handle_t *) group;
1334 (void) vm_call_method(m, o, object);
1336 if (exceptions_get_exception())
1341 /* Thread has terminated. */
1343 threads_thread_state_terminated(t);
1345 /* Notify all threads waiting on this thread. These are joining
1348 o = (java_handle_t *) object;
1350 /* XXX Care about exceptions? */
1351 (void) lock_monitor_enter(o);
1353 lock_notify_all_object(o);
1355 /* XXX Care about exceptions? */
1356 (void) lock_monitor_exit(o);
1358 /* Enter the join-mutex before calling thread_free, so
1359 threads_join_all_threads gets the correct number of non-daemon
1362 threads_mutex_join_lock();
1364 /* Free the internal thread data-structure. */
1368 /* Signal that this thread has finished and leave the mutex. */
1370 pthread_cond_signal(&cond_join);
1371 threads_mutex_join_unlock();
1377 /* threads_suspend_thread ******************************************************
1379 Suspend the passed thread. Execution stops until the thread
1380 is explicitly resumend again.
1383 reason.....Reason for suspending this thread.
1385 *******************************************************************************/
1387 bool threads_suspend_thread(threadobject *thread, s4 reason)
1389 /* acquire the suspendmutex */
1390 mutex_lock(&(thread->suspendmutex));
1392 if (thread->suspended) {
1393 mutex_unlock(&(thread->suspendmutex));
1397 /* set the reason for the suspension */
1398 thread->suspend_reason = reason;
1400 /* send the suspend signal to the thread */
1401 assert(thread != THREADOBJECT);
1402 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1403 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1406 /* REMEMBER: do not release the suspendmutex, this is done
1407 by the thread itself in threads_suspend_ack(). */
1413 /* threads_suspend_ack *********************************************************
1415 Acknowledges the suspension of the current thread.
1418 pc.....The PC where the thread suspended its execution.
1419 sp.....The SP before the thread suspended its execution.
1421 *******************************************************************************/
1423 void threads_suspend_ack(u1* pc, u1* sp)
1425 threadobject *thread;
1427 thread = THREADOBJECT;
1429 assert(thread->suspend_reason != 0);
1431 /* TODO: remember dump memory size */
1433 #if defined(ENABLE_GC_CACAO)
1434 /* inform the GC about the suspension */
1435 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1437 /* check if the GC wants to leave the thread running */
1438 if (!gc_suspend(thread, pc, sp)) {
1440 /* REMEMBER: we do not unlock the suspendmutex because the thread
1441 will suspend itself again at a later time */
1448 /* mark this thread as suspended and remember the PC */
1450 thread->suspended = true;
1452 /* if we are stopping the world, we should send a global ack */
1453 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1454 threads_sem_post(&suspend_ack);
1457 DEBUGTHREADS("suspending", thread);
1459 /* release the suspension mutex and wait till we are resumed */
1460 pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1462 DEBUGTHREADS("resuming", thread);
1464 /* if we are stopping the world, we should send a global ack */
1465 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1466 threads_sem_post(&suspend_ack);
1469 /* TODO: free dump memory */
1471 /* release the suspendmutex */
1472 mutex_unlock(&(thread->suspendmutex));
1476 /* threads_resume_thread *******************************************************
1478 Resumes the execution of the passed thread.
1480 *******************************************************************************/
1482 bool threads_resume_thread(threadobject *thread)
1484 /* acquire the suspendmutex */
1485 mutex_lock(&(thread->suspendmutex));
1487 if (!thread->suspended) {
1488 mutex_unlock(&(thread->suspendmutex));
1492 thread->suspended = false;
1494 /* tell everyone that the thread should resume */
1495 assert(thread != THREADOBJECT);
1496 pthread_cond_broadcast(&(thread->suspendcond));
1498 /* release the suspendmutex */
1499 mutex_unlock(&(thread->suspendmutex));
1505 /* threads_join_all_threads ****************************************************
1507 Join all non-daemon threads.
1509 *******************************************************************************/
1511 void threads_join_all_threads(void)
1515 /* get current thread */
1519 /* this thread is waiting for all non-daemon threads to exit */
1521 threads_thread_state_waiting(t);
1523 /* enter join mutex */
1525 threads_mutex_join_lock();
1527 /* Wait for condition as long as we have non-daemon threads. We
1528 compare against 1 because the current (main thread) is also a
1529 non-daemon thread. */
1531 while (threadlist_get_non_daemons() > 1)
1532 pthread_cond_wait(&cond_join, &mutex_join);
1534 /* leave join mutex */
1536 threads_mutex_join_unlock();
1540 /* threads_timespec_earlier ****************************************************
1542 Return true if timespec tv1 is earlier than timespec tv2.
1545 tv1..........first timespec
1546 tv2..........second timespec
1549 true, if the first timespec is earlier
1551 *******************************************************************************/
1553 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1554 const struct timespec *tv2)
1556 return (tv1->tv_sec < tv2->tv_sec)
1558 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1562 /* threads_current_time_is_earlier_than ****************************************
1564 Check if the current time is earlier than the given timespec.
1567 tv...........the timespec to compare against
1570 true, if the current time is earlier
1572 *******************************************************************************/
1574 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1576 struct timeval tvnow;
1577 struct timespec tsnow;
1579 /* get current time */
1581 if (gettimeofday(&tvnow, NULL) != 0)
1582 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1584 /* convert it to a timespec */
1586 tsnow.tv_sec = tvnow.tv_sec;
1587 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1589 /* compare current time with the given timespec */
1591 return threads_timespec_earlier(&tsnow, tv);
1595 /* threads_wait_with_timeout ***************************************************
1597 Wait until the given point in time on a monitor until either
1598 we are notified, we are interrupted, or the time is up.
1601 t............the current thread
1602 wakeupTime...absolute (latest) wakeup time
1603 If both tv_sec and tv_nsec are zero, this function
1604 waits for an unlimited amount of time.
1606 *******************************************************************************/
1608 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1610 /* acquire the waitmutex */
1612 mutex_lock(&t->waitmutex);
1614 /* mark us as sleeping */
1618 /* wait on waitcond */
1620 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1622 while (!t->interrupted && !t->signaled
1623 && threads_current_time_is_earlier_than(wakeupTime))
1625 threads_thread_state_timed_waiting(t);
1627 pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
1630 threads_thread_state_runnable(t);
1635 while (!t->interrupted && !t->signaled) {
1636 threads_thread_state_waiting(t);
1638 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1640 threads_thread_state_runnable(t);
1644 t->sleeping = false;
1646 /* release the waitmutex */
1648 mutex_unlock(&t->waitmutex);
1652 /* threads_wait_with_timeout_relative ******************************************
1654 Wait for the given maximum amount of time on a monitor until either
1655 we are notified, we are interrupted, or the time is up.
1658 t............the current thread
1659 millis.......milliseconds to wait
1660 nanos........nanoseconds to wait
1662 *******************************************************************************/
1664 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1667 struct timespec wakeupTime;
1669 /* calculate the the (latest) wakeup time */
1671 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1675 threads_wait_with_timeout(thread, &wakeupTime);
1679 /* threads_calc_absolute_time **************************************************
1681 Calculate the absolute point in time a given number of ms and ns from now.
1684 millis............milliseconds from now
1685 nanos.............nanoseconds from now
1688 *tm...............receives the timespec of the absolute point in time
1690 *******************************************************************************/
1692 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1694 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1697 gettimeofday(&tv, NULL);
1698 tv.tv_sec += millis / 1000;
1700 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1701 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1702 tm->tv_nsec = nsec % 1000000000;
1711 /* threads_thread_interrupt ****************************************************
1713 Interrupt the given thread.
1715 The thread gets the "waitcond" signal and
1716 its interrupted flag is set to true.
1719 thread............the thread to interrupt
1721 *******************************************************************************/
1723 void threads_thread_interrupt(threadobject *thread)
1725 /* Signal the thread a "waitcond" and tell it that it has been
1728 mutex_lock(&thread->waitmutex);
1730 DEBUGTHREADS("interrupted", thread);
1732 /* Interrupt blocking system call using a signal. */
1734 pthread_kill(thread->tid, SIGHUP);
1736 if (thread->sleeping)
1737 pthread_cond_signal(&thread->waitcond);
1739 thread->interrupted = true;
1741 mutex_unlock(&thread->waitmutex);
1745 /* threads_check_if_interrupted_and_reset **************************************
1747 Check if the current thread has been interrupted and reset the
1751 true, if the current thread had been interrupted
1753 *******************************************************************************/
1755 bool threads_check_if_interrupted_and_reset(void)
1757 threadobject *thread;
1760 thread = THREADOBJECT;
1762 mutex_lock(&thread->waitmutex);
1764 /* get interrupted flag */
1766 intr = thread->interrupted;
1768 /* reset interrupted flag */
1770 thread->interrupted = false;
1772 mutex_unlock(&thread->waitmutex);
1778 /* threads_thread_has_been_interrupted *****************************************
1780 Check if the given thread has been interrupted
1783 t............the thread to check
1786 true, if the given thread had been interrupted
1788 *******************************************************************************/
1790 bool threads_thread_has_been_interrupted(threadobject *thread)
1792 return thread->interrupted;
1796 /* threads_sleep ***************************************************************
1798 Sleep the current thread for the specified amount of time.
1800 *******************************************************************************/
1802 void threads_sleep(s8 millis, s4 nanos)
1804 threadobject *thread;
1805 struct timespec wakeupTime;
1806 bool wasinterrupted;
1808 thread = THREADOBJECT;
1810 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1812 threads_wait_with_timeout(thread, &wakeupTime);
1814 wasinterrupted = threads_check_if_interrupted_and_reset();
1817 exceptions_throw_interruptedexception();
1821 /* threads_yield ***************************************************************
1823 Yield to the scheduler.
1825 *******************************************************************************/
1827 void threads_yield(void)
1834 * These are local overrides for various environment variables in Emacs.
1835 * Please do not remove this and leave it at the end of the file, where
1836 * Emacs will automagically detect them.
1837 * ---------------------------------------------------------------------
1840 * indent-tabs-mode: t
1844 * vim:noexpandtab:sw=4:ts=4: