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);
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;
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 */
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 t->mach_thread = mach_thread_self();
1010 /* Now that we are in the new thread, we can store the internal
1011 thread data-structure in the TSD. */
1013 thread_set_current(t);
1015 /* get the java.lang.Thread object for this thread */
1017 object = (java_lang_Thread *) thread_get_object(t);
1019 /* set our priority */
1021 threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
1023 /* Thread is completely initialized. */
1025 thread_set_state_runnable(t);
1027 /* tell threads_startup_thread that we registered ourselves */
1028 /* CAUTION: *startup becomes invalid with this! */
1031 threads_sem_post(psem);
1033 #if defined(ENABLE_INTRP)
1034 /* set interpreter stack */
1037 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1040 #if defined(ENABLE_JVMTI)
1041 /* fire thread start event */
1044 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1047 DEBUGTHREADS("starting", t);
1049 /* find and run the Thread.run()V method if no other function was passed */
1051 if (function == NULL) {
1052 #if defined(WITH_CLASSPATH_GNU)
1053 /* We need to start the run method of
1054 java.lang.VMThread. Since this is a final class, we can use
1055 the class object directly. */
1057 c = class_java_lang_VMThread;
1058 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1059 LLNI_class_get(object, c);
1061 # error unknown classpath configuration
1064 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1067 vm_abort("threads_startup_thread: run() method not found in class");
1069 /* set ThreadMXBean variables */
1071 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1072 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1074 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1075 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1076 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1077 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1079 #if defined(WITH_CLASSPATH_GNU)
1080 /* we need to start the run method of java.lang.VMThread */
1082 LLNI_field_get_ref(object, vmThread, vmt);
1083 o = (java_handle_t *) vmt;
1085 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1086 o = (java_handle_t *) object;
1088 # error unknown classpath configuration
1091 /* Run the thread. */
1093 (void) vm_call_method(m, o);
1096 /* set ThreadMXBean variables */
1098 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1099 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1101 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1102 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1103 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1104 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1106 /* call passed function, e.g. finalizer_thread */
1111 DEBUGTHREADS("stopping", t);
1113 #if defined(ENABLE_JVMTI)
1114 /* fire thread end event */
1117 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1120 /* We ignore the return value. */
1122 (void) threads_detach_thread(t);
1124 /* set ThreadMXBean variables */
1126 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1132 /* threads_impl_thread_start ***************************************************
1134 Start a thread in the JVM. Both (vm internal and java) thread
1138 thread....the thread object
1139 f.........function to run in the new thread. NULL means that the
1140 "run" method of the object `t` should be called
1142 ******************************************************************************/
1144 void threads_impl_thread_start(threadobject *thread, functionptr f)
1148 pthread_attr_t attr;
1149 startupinfo startup;
1152 /* fill startupinfo structure passed by pthread_create to
1153 * threads_startup_thread */
1155 startup.thread = thread;
1156 startup.function = f; /* maybe we don't call Thread.run()V */
1157 startup.psem = &sem;
1158 startup.psem_first = &sem_first;
1160 threads_sem_init(&sem, 0, 0);
1161 threads_sem_init(&sem_first, 0, 0);
1163 /* Initialize thread attributes. */
1165 result = pthread_attr_init(&attr);
1168 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
1170 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1173 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
1175 /* initialize thread stacksize */
1177 result = pthread_attr_setstacksize(&attr, opt_stacksize);
1180 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
1182 /* create the thread */
1184 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1187 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1189 /* destroy the thread attributes */
1191 result = pthread_attr_destroy(&attr);
1194 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1196 /* signal that pthread_create has returned, so thread->tid is valid */
1198 threads_sem_post(&sem_first);
1200 /* wait here until the thread has entered itself into the thread list */
1202 threads_sem_wait(&sem);
1207 sem_destroy(&sem_first);
1211 /* threads_set_thread_priority *************************************************
1213 Set the priority of the given thread.
1216 tid..........thread id
1217 priority.....priority to set
1219 ******************************************************************************/
1221 void threads_set_thread_priority(pthread_t tid, int priority)
1223 struct sched_param schedp;
1226 pthread_getschedparam(tid, &policy, &schedp);
1227 schedp.sched_priority = priority;
1228 pthread_setschedparam(tid, policy, &schedp);
1232 /* threads_detach_thread *******************************************************
1234 Detaches the passed thread from the VM. Used in JNI.
1236 *******************************************************************************/
1238 bool threads_detach_thread(threadobject *t)
1241 java_lang_Thread *object;
1243 #if defined(ENABLE_JAVASE)
1244 java_lang_ThreadGroup *group;
1251 /* If the given thread has already been detached, this operation
1254 result = thread_is_attached(t);
1256 if (result == false)
1259 DEBUGTHREADS("detaching", t);
1261 object = (java_lang_Thread *) thread_get_object(t);
1263 #if defined(ENABLE_JAVASE)
1264 LLNI_field_get_ref(object, group, group);
1266 /* If there's an uncaught exception, call uncaughtException on the
1267 thread's exception handler, or the thread's group if this is
1270 e = exceptions_get_and_clear_exception();
1273 /* We use the type void* for handler here, as it's not trivial
1274 to build the java_lang_Thread_UncaughtExceptionHandler
1275 header file with cacaoh. */
1277 # if defined(WITH_CLASSPATH_GNU)
1278 LLNI_field_get_ref(object, exceptionHandler, handler);
1279 # elif defined(WITH_CLASSPATH_SUN)
1280 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1283 if (handler != NULL) {
1284 LLNI_class_get(handler, c);
1285 o = (java_handle_t *) handler;
1288 LLNI_class_get(group, c);
1289 o = (java_handle_t *) group;
1292 m = class_resolveclassmethod(c,
1293 utf_uncaughtException,
1294 utf_java_lang_Thread_java_lang_Throwable__V,
1301 (void) vm_call_method(m, o, object, e);
1303 if (exceptions_get_exception())
1307 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1309 /* Remove thread from the thread group. */
1311 if (group != NULL) {
1312 LLNI_class_get(group, c);
1314 # if defined(WITH_CLASSPATH_GNU)
1315 m = class_resolveclassmethod(c,
1317 utf_java_lang_Thread__V,
1318 class_java_lang_ThreadGroup,
1320 # elif defined(WITH_CLASSPATH_SUN)
1321 m = class_resolveclassmethod(c,
1323 utf_java_lang_Thread__V,
1324 class_java_lang_ThreadGroup,
1327 # error unknown classpath configuration
1333 o = (java_handle_t *) group;
1335 (void) vm_call_method(m, o, object);
1337 if (exceptions_get_exception())
1340 /* Reset the threadgroup in the Java thread object (Mauve
1341 test: gnu/testlet/java/lang/Thread/getThreadGroup). */
1343 LLNI_field_set_ref(object, group, NULL);
1347 /* Thread has terminated. */
1349 thread_set_state_terminated(t);
1351 /* Notify all threads waiting on this thread. These are joining
1354 o = (java_handle_t *) object;
1356 /* XXX Care about exceptions? */
1357 (void) lock_monitor_enter(o);
1359 lock_notify_all_object(o);
1361 /* XXX Care about exceptions? */
1362 (void) lock_monitor_exit(o);
1364 /* Enter the join-mutex before calling thread_free, so
1365 threads_join_all_threads gets the correct number of non-daemon
1368 threads_mutex_join_lock();
1370 /* Free the internal thread data-structure. */
1374 /* Signal that this thread has finished and leave the mutex. */
1376 pthread_cond_signal(&cond_join);
1377 threads_mutex_join_unlock();
1383 /* threads_suspend_thread ******************************************************
1385 Suspend the passed thread. Execution stops until the thread
1386 is explicitly resumend again.
1389 reason.....Reason for suspending this thread.
1391 *******************************************************************************/
1393 bool threads_suspend_thread(threadobject *thread, s4 reason)
1395 /* acquire the suspendmutex */
1396 mutex_lock(&(thread->suspendmutex));
1398 if (thread->suspended) {
1399 mutex_unlock(&(thread->suspendmutex));
1403 /* set the reason for the suspension */
1404 thread->suspend_reason = reason;
1406 /* send the suspend signal to the thread */
1407 assert(thread != THREADOBJECT);
1408 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1409 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1412 /* REMEMBER: do not release the suspendmutex, this is done
1413 by the thread itself in threads_suspend_ack(). */
1419 /* threads_suspend_ack *********************************************************
1421 Acknowledges the suspension of the current thread.
1424 pc.....The PC where the thread suspended its execution.
1425 sp.....The SP before the thread suspended its execution.
1427 *******************************************************************************/
1429 void threads_suspend_ack(u1* pc, u1* sp)
1431 threadobject *thread;
1433 thread = THREADOBJECT;
1435 assert(thread->suspend_reason != 0);
1437 /* TODO: remember dump memory size */
1439 #if defined(ENABLE_GC_CACAO)
1440 /* inform the GC about the suspension */
1441 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1443 /* check if the GC wants to leave the thread running */
1444 if (!gc_suspend(thread, pc, sp)) {
1446 /* REMEMBER: we do not unlock the suspendmutex because the thread
1447 will suspend itself again at a later time */
1454 /* mark this thread as suspended and remember the PC */
1456 thread->suspended = true;
1458 /* if we are stopping the world, we should send a global ack */
1459 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1460 threads_sem_post(&suspend_ack);
1463 DEBUGTHREADS("suspending", thread);
1465 /* release the suspension mutex and wait till we are resumed */
1466 pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1468 DEBUGTHREADS("resuming", thread);
1470 /* if we are stopping the world, we should send a global ack */
1471 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1472 threads_sem_post(&suspend_ack);
1475 /* TODO: free dump memory */
1477 /* release the suspendmutex */
1478 mutex_unlock(&(thread->suspendmutex));
1482 /* threads_resume_thread *******************************************************
1484 Resumes the execution of the passed thread.
1486 *******************************************************************************/
1488 bool threads_resume_thread(threadobject *thread)
1490 /* acquire the suspendmutex */
1491 mutex_lock(&(thread->suspendmutex));
1493 if (!thread->suspended) {
1494 mutex_unlock(&(thread->suspendmutex));
1498 thread->suspended = false;
1500 /* tell everyone that the thread should resume */
1501 assert(thread != THREADOBJECT);
1502 pthread_cond_broadcast(&(thread->suspendcond));
1504 /* release the suspendmutex */
1505 mutex_unlock(&(thread->suspendmutex));
1511 /* threads_join_all_threads ****************************************************
1513 Join all non-daemon threads.
1515 *******************************************************************************/
1517 void threads_join_all_threads(void)
1521 /* get current thread */
1525 /* This thread is waiting for all non-daemon threads to exit. */
1527 thread_set_state_waiting(t);
1529 /* enter join mutex */
1531 threads_mutex_join_lock();
1533 /* Wait for condition as long as we have non-daemon threads. We
1534 compare against 1 because the current (main thread) is also a
1535 non-daemon thread. */
1537 while (threadlist_get_non_daemons() > 1)
1538 pthread_cond_wait(&cond_join, &mutex_join);
1540 /* leave join mutex */
1542 threads_mutex_join_unlock();
1546 /* threads_timespec_earlier ****************************************************
1548 Return true if timespec tv1 is earlier than timespec tv2.
1551 tv1..........first timespec
1552 tv2..........second timespec
1555 true, if the first timespec is earlier
1557 *******************************************************************************/
1559 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1560 const struct timespec *tv2)
1562 return (tv1->tv_sec < tv2->tv_sec)
1564 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1568 /* threads_current_time_is_earlier_than ****************************************
1570 Check if the current time is earlier than the given timespec.
1573 tv...........the timespec to compare against
1576 true, if the current time is earlier
1578 *******************************************************************************/
1580 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1582 struct timeval tvnow;
1583 struct timespec tsnow;
1585 /* get current time */
1587 if (gettimeofday(&tvnow, NULL) != 0)
1588 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1590 /* convert it to a timespec */
1592 tsnow.tv_sec = tvnow.tv_sec;
1593 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1595 /* compare current time with the given timespec */
1597 return threads_timespec_earlier(&tsnow, tv);
1601 /* threads_wait_with_timeout ***************************************************
1603 Wait until the given point in time on a monitor until either
1604 we are notified, we are interrupted, or the time is up.
1607 t............the current thread
1608 wakeupTime...absolute (latest) wakeup time
1609 If both tv_sec and tv_nsec are zero, this function
1610 waits for an unlimited amount of time.
1612 *******************************************************************************/
1614 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
1616 /* acquire the waitmutex */
1618 mutex_lock(&t->waitmutex);
1620 /* mark us as sleeping */
1624 /* wait on waitcond */
1626 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1628 while (!t->interrupted && !t->signaled
1629 && threads_current_time_is_earlier_than(wakeupTime))
1631 thread_set_state_timed_waiting(t);
1633 pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
1636 thread_set_state_runnable(t);
1641 while (!t->interrupted && !t->signaled) {
1642 thread_set_state_waiting(t);
1644 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1646 thread_set_state_runnable(t);
1650 t->sleeping = false;
1652 /* release the waitmutex */
1654 mutex_unlock(&t->waitmutex);
1658 /* threads_wait_with_timeout_relative ******************************************
1660 Wait for the given maximum amount of time on a monitor until either
1661 we are notified, we are interrupted, or the time is up.
1664 t............the current thread
1665 millis.......milliseconds to wait
1666 nanos........nanoseconds to wait
1668 *******************************************************************************/
1670 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1673 struct timespec wakeupTime;
1675 /* calculate the the (latest) wakeup time */
1677 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1681 threads_wait_with_timeout(thread, &wakeupTime);
1685 /* threads_calc_absolute_time **************************************************
1687 Calculate the absolute point in time a given number of ms and ns from now.
1690 millis............milliseconds from now
1691 nanos.............nanoseconds from now
1694 *tm...............receives the timespec of the absolute point in time
1696 *******************************************************************************/
1698 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1700 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1703 gettimeofday(&tv, NULL);
1704 tv.tv_sec += millis / 1000;
1706 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1707 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1708 tm->tv_nsec = nsec % 1000000000;
1717 /* threads_thread_interrupt ****************************************************
1719 Interrupt the given thread.
1721 The thread gets the "waitcond" signal and
1722 its interrupted flag is set to true.
1725 thread............the thread to interrupt
1727 *******************************************************************************/
1729 void threads_thread_interrupt(threadobject *thread)
1731 /* Signal the thread a "waitcond" and tell it that it has been
1734 mutex_lock(&thread->waitmutex);
1736 DEBUGTHREADS("interrupted", thread);
1738 /* Interrupt blocking system call using a signal. */
1740 pthread_kill(thread->tid, SIGHUP);
1742 if (thread->sleeping)
1743 pthread_cond_signal(&thread->waitcond);
1745 thread->interrupted = true;
1747 mutex_unlock(&thread->waitmutex);
1751 /* threads_sleep ***************************************************************
1753 Sleep the current thread for the specified amount of time.
1755 *******************************************************************************/
1757 void threads_sleep(int64_t millis, int32_t nanos)
1760 struct timespec wakeupTime;
1764 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1765 exceptions_throw_illegalargumentexception();
1769 t = thread_get_current();
1771 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1772 /* Clear interrupted flag (Mauve test:
1773 gnu/testlet/java/lang/Thread/interrupt). */
1775 thread_set_interrupted(t, false);
1777 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1778 exceptions_throw_interruptedexception();
1782 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1784 threads_wait_with_timeout(t, &wakeupTime);
1786 interrupted = thread_is_interrupted(t);
1789 thread_set_interrupted(t, false);
1791 /* An other exception could have been thrown
1792 (e.g. ThreadDeathException). */
1794 if (!exceptions_get_exception())
1795 exceptions_throw_interruptedexception();
1800 /* threads_yield ***************************************************************
1802 Yield to the scheduler.
1804 *******************************************************************************/
1806 void threads_yield(void)
1813 * These are local overrides for various environment variables in Emacs.
1814 * Please do not remove this and leave it at the end of the file, where
1815 * Emacs will automagically detect them.
1816 * ---------------------------------------------------------------------
1819 * indent-tabs-mode: t
1823 * vim:noexpandtab:sw=4:ts=4: