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 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
237 static volatile int stopworldwhere;
239 #if defined(ENABLE_GC_CACAO)
241 /* semaphore used for acknowleding thread suspension */
242 static sem_t suspend_ack;
243 #if defined(__IRIX__)
244 static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
245 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
248 #endif /* ENABLE_GC_CACAO */
250 /* mutexes used by the fake atomic instructions */
251 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
252 mutex_t _cas_lock = MUTEX_INITIALIZER;
253 mutex_t _mb_lock = MUTEX_INITIALIZER;
257 /* threads_sem_init ************************************************************
259 Initialize a semaphore. Checks against errors and interruptions.
262 sem..............the semaphore to initialize
263 shared...........true if this semaphore will be shared between processes
264 value............the initial value for the semaphore
266 *******************************************************************************/
268 void threads_sem_init(sem_t *sem, bool shared, int value)
275 r = sem_init(sem, shared, value);
278 } while (errno == EINTR);
280 vm_abort("sem_init failed: %s", strerror(errno));
284 /* threads_sem_wait ************************************************************
286 Wait for a semaphore, non-interruptible.
288 IMPORTANT: Always use this function instead of `sem_wait` directly, as
289 `sem_wait` may be interrupted by signals!
292 sem..............the semaphore to wait on
294 *******************************************************************************/
296 void threads_sem_wait(sem_t *sem)
306 } while (errno == EINTR);
308 vm_abort("sem_wait failed: %s", strerror(errno));
312 /* threads_sem_post ************************************************************
314 Increase the count of a semaphore. Checks for errors.
317 sem..............the semaphore to increase the count of
319 *******************************************************************************/
321 void threads_sem_post(sem_t *sem)
327 /* unlike sem_wait, sem_post is not interruptible */
333 vm_abort("sem_post failed: %s", strerror(errno));
337 /* lock_stopworld **************************************************************
339 Enter the stopworld lock, specifying why the world shall be stopped.
342 where........ STOPWORLD_FROM_GC (1) from within GC
343 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
345 ******************************************************************************/
347 void lock_stopworld(int where)
349 mutex_lock(&stopworldlock);
350 /* stopworldwhere = where; */
354 /* unlock_stopworld ************************************************************
356 Release the stopworld lock.
358 ******************************************************************************/
360 void unlock_stopworld(void)
362 /* stopworldwhere = 0; */
363 mutex_unlock(&stopworldlock);
366 /* XXX We disable that whole bunch of code until we have the exact-GC
367 running. Some of it may only be needed by the old Boehm-based
368 suspension handling. */
372 #if !defined(__DARWIN__)
373 /* Caller must hold threadlistlock */
374 static s4 threads_cast_sendsignals(s4 sig)
382 /* iterate over all started threads */
386 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
387 /* don't send the signal to ourself */
392 /* don't send the signal to NEW threads (because they are not
393 completely initialized) */
395 if (t->state == THREAD_STATE_NEW)
398 /* send the signal */
400 pthread_kill(t->tid, sig);
402 /* increase threads count */
412 static void threads_cast_darwinstop(void)
414 threadobject *tobj = mainthreadobj;
415 threadobject *self = THREADOBJECT;
420 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
421 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
422 #if defined(__I386__)
423 i386_thread_state_t thread_state;
425 ppc_thread_state_t thread_state;
427 mach_port_t thread = tobj->mach_thread;
430 r = thread_suspend(thread);
432 if (r != KERN_SUCCESS)
433 vm_abort("thread_suspend failed");
435 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
436 &thread_state_count);
438 if (r != KERN_SUCCESS)
439 vm_abort("thread_get_state failed");
441 md_critical_section_restart((ucontext_t *) &thread_state);
443 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
446 if (r != KERN_SUCCESS)
447 vm_abort("thread_set_state failed");
451 } while (tobj != mainthreadobj);
454 static void threads_cast_darwinresume(void)
456 threadobject *tobj = mainthreadobj;
457 threadobject *self = THREADOBJECT;
462 mach_port_t thread = tobj->mach_thread;
465 r = thread_resume(thread);
467 if (r != KERN_SUCCESS)
468 vm_abort("thread_resume failed");
472 } while (tobj != mainthreadobj);
477 #if defined(__IRIX__)
478 static void threads_cast_irixresume(void)
480 mutex_lock(&suspend_ack_lock);
481 pthread_cond_broadcast(&suspend_cond);
482 mutex_unlock(&suspend_ack_lock);
486 #if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
487 static void threads_sigsuspend_handler(ucontext_t *_uc)
492 /* XXX TWISTI: this is just a quick hack */
493 #if defined(ENABLE_JIT)
494 md_critical_section_restart(_uc);
497 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
498 (not POSIX async-safe). */
499 #if defined(__IRIX__)
500 mutex_lock(&suspend_ack_lock);
501 threads_sem_post(&suspend_ack);
502 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
503 mutex_unlock(&suspend_ack_lock);
504 #elif defined(__CYGWIN__)
511 sigdelset(&sigs, sig);
518 /* threads_stopworld ***********************************************************
520 Stops the world from turning. All threads except the calling one
521 are suspended. The function returns as soon as all threads have
522 acknowledged their suspension.
524 *******************************************************************************/
526 void threads_stopworld(void)
528 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
535 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
537 /* lock the threads lists */
541 #if defined(__DARWIN__)
542 /*threads_cast_darwinstop();*/
544 #elif defined(__CYGWIN__)
550 DEBUGTHREADS("stops World", self);
554 /* suspend all running threads */
555 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
556 /* don't send the signal to ourself */
561 /* don't send the signal to NEW threads (because they are not
562 completely initialized) */
564 if (t->state == THREAD_STATE_NEW)
567 /* send the signal */
569 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
572 /* increase threads count */
577 /* wait for all threads signaled to suspend */
578 for (i = 0; i < count; i++)
579 threads_sem_wait(&suspend_ack);
582 /* ATTENTION: Don't unlock the threads-lists here so that
583 non-signaled NEW threads can't change their state and execute
588 /* threads_startworld **********************************************************
590 Starts the world again after it has previously been stopped.
592 *******************************************************************************/
594 void threads_startworld(void)
596 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
603 #if defined(__DARWIN__)
604 /*threads_cast_darwinresume();*/
606 #elif defined(__IRIX__)
607 threads_cast_irixresume();
608 #elif defined(__CYGWIN__)
614 DEBUGTHREADS("starts World", self);
618 /* resume all thread we haltet */
619 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
620 /* don't send the signal to ourself */
625 /* don't send the signal to NEW threads (because they are not
626 completely initialized) */
628 if (t->state == THREAD_STATE_NEW)
631 /* send the signal */
633 result = threads_resume_thread(t);
636 /* increase threads count */
641 /* wait for all threads signaled to suspend */
642 for (i = 0; i < count; i++)
643 threads_sem_wait(&suspend_ack);
647 /* unlock the threads lists */
657 /* threads_impl_thread_init ****************************************************
659 Initialize OS-level locking constructs in threadobject.
662 t....the threadobject
664 *******************************************************************************/
666 void threads_impl_thread_init(threadobject *t)
670 /* initialize the mutex and the condition */
672 mutex_init(&t->flc_lock);
674 result = pthread_cond_init(&t->flc_cond, NULL);
676 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
678 mutex_init(&(t->waitmutex));
680 result = pthread_cond_init(&(t->waitcond), NULL);
682 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
684 mutex_init(&(t->suspendmutex));
686 result = pthread_cond_init(&(t->suspendcond), NULL);
688 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
691 /* threads_impl_thread_clear ***************************************************
693 Clears all fields in threadobject the way an MZERO would have
694 done. MZERO cannot be used anymore because it would mess up the
698 t....the threadobject
700 *******************************************************************************/
702 void threads_impl_thread_clear(threadobject *t)
714 #if defined(__DARWIN__)
718 t->interrupted = false;
722 t->suspended = false;
723 t->suspend_reason = 0;
727 t->_exceptionptr = NULL;
728 t->_stackframeinfo = NULL;
729 t->_localref_table = NULL;
731 #if defined(ENABLE_INTRP)
732 t->_global_sp = NULL;
735 #if defined(ENABLE_GC_CACAO)
736 t->gc_critical = false;
742 MZERO(&t->dumpinfo, dumpinfo_t, 1);
745 /* threads_impl_thread_reuse ***************************************************
747 Resets some implementation fields in threadobject. This was
748 previously done in threads_impl_thread_new.
751 t....the threadobject
753 *******************************************************************************/
755 void threads_impl_thread_reuse(threadobject *t)
757 /* get the pthread id */
759 t->tid = pthread_self();
761 #if defined(ENABLE_DEBUG_FILTER)
762 /* Initialize filter counters */
763 t->filterverbosecallctr[0] = 0;
764 t->filterverbosecallctr[1] = 0;
768 t->tracejavacallindent = 0;
769 t->tracejavacallcount = 0;
776 /* not really needed */
777 t->flc_object = NULL;
781 /* threads_impl_thread_free ****************************************************
783 Cleanup thread stuff.
786 t....the threadobject
788 *******************************************************************************/
792 void threads_impl_thread_free(threadobject *t)
796 /* Destroy the mutex and the condition. */
798 mutex_destroy(&(t->flc_lock));
800 result = pthread_cond_destroy(&(t->flc_cond));
803 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
805 mutex_destroy(&(t->waitmutex));
807 result = pthread_cond_destroy(&(t->waitcond));
810 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
812 mutex_destroy(&(t->suspendmutex));
814 result = pthread_cond_destroy(&(t->suspendcond));
817 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
822 /* threads_impl_preinit ********************************************************
824 Do some early initialization of stuff required.
826 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
827 is called AFTER this function!
829 *******************************************************************************/
831 void threads_impl_preinit(void)
835 mutex_init(&stopworldlock);
837 /* initialize exit mutex and condition (on exit we join all
840 mutex_init(&mutex_join);
842 result = pthread_cond_init(&cond_join, NULL);
844 vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
846 #if defined(ENABLE_GC_CACAO)
847 /* initialize the GC mutex & suspend semaphore */
849 mutex_init(&mutex_gc);
850 threads_sem_init(&suspend_ack, 0, 0);
853 #if !defined(HAVE___THREAD)
854 result = pthread_key_create(&thread_current_key, NULL);
856 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
861 /* threads_mutex_gc_lock *******************************************************
863 Enter the global GC mutex.
865 *******************************************************************************/
867 #if defined(ENABLE_GC_CACAO)
868 void threads_mutex_gc_lock(void)
870 mutex_lock(&mutex_gc);
875 /* threads_mutex_gc_unlock *****************************************************
877 Leave the global GC mutex.
879 *******************************************************************************/
881 #if defined(ENABLE_GC_CACAO)
882 void threads_mutex_gc_unlock(void)
884 mutex_unlock(&mutex_gc);
888 /* threads_mutex_join_lock *****************************************************
890 Enter the join mutex.
892 *******************************************************************************/
894 void threads_mutex_join_lock(void)
896 mutex_lock(&mutex_join);
900 /* threads_mutex_join_unlock ***************************************************
902 Leave the join mutex.
904 *******************************************************************************/
906 void threads_mutex_join_unlock(void)
908 mutex_unlock(&mutex_join);
912 /* threads_impl_init ***********************************************************
914 Initializes the implementation specific bits.
916 *******************************************************************************/
918 void threads_impl_init(void)
923 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
925 /* Initialize the thread attribute object. */
927 result = pthread_attr_init(&attr);
930 vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
932 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
935 vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
939 /* threads_startup_thread ******************************************************
941 Thread startup function called by pthread_create.
943 Thread which have a startup.function != NULL are marked as internal
944 threads. All other threads are threated as normal Java threads.
946 NOTE: This function is not called directly by pthread_create. The Boehm GC
947 inserts its own GC_start_routine in between, which then calls
951 arg..........the argument passed to pthread_create, ie. a pointer to
952 a startupinfo struct. CAUTION: When the `psem` semaphore
953 is posted, the startupinfo struct becomes invalid! (It
954 is allocated on the stack of threads_start_thread.)
956 ******************************************************************************/
958 static void *threads_startup_thread(void *arg)
960 startupinfo *startup;
962 java_lang_Thread *object;
963 #if defined(WITH_CLASSPATH_GNU)
964 java_lang_VMThread *vmt;
970 functionptr function;
972 #if defined(ENABLE_INTRP)
973 u1 *intrp_thread_stack;
975 /* create interpreter stack */
978 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
979 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
982 intrp_thread_stack = NULL;
985 /* get passed startupinfo structure and the values in there */
990 function = startup->function;
991 psem = startup->psem;
993 /* Seems like we've encountered a situation where thread->tid was
994 not set by pthread_create. We alleviate this problem by waiting
995 for pthread_create to return. */
997 threads_sem_wait(startup->psem_first);
999 #if defined(__DARWIN__)
1000 t->mach_thread = mach_thread_self();
1003 /* Now that we are in the new thread, we can store the internal
1004 thread data-structure in the TSD. */
1006 thread_set_current(t);
1008 /* get the java.lang.Thread object for this thread */
1010 object = (java_lang_Thread *) thread_get_object(t);
1012 /* set our priority */
1014 threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
1016 /* Thread is completely initialized. */
1018 thread_set_state_runnable(t);
1020 /* tell threads_startup_thread that we registered ourselves */
1021 /* CAUTION: *startup becomes invalid with this! */
1024 threads_sem_post(psem);
1026 #if defined(ENABLE_INTRP)
1027 /* set interpreter stack */
1030 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1033 #if defined(ENABLE_JVMTI)
1034 /* fire thread start event */
1037 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1040 DEBUGTHREADS("starting", t);
1042 /* find and run the Thread.run()V method if no other function was passed */
1044 if (function == NULL) {
1045 #if defined(WITH_CLASSPATH_GNU)
1046 /* We need to start the run method of
1047 java.lang.VMThread. Since this is a final class, we can use
1048 the class object directly. */
1050 c = class_java_lang_VMThread;
1051 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1052 LLNI_class_get(object, c);
1054 # error unknown classpath configuration
1057 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1060 vm_abort("threads_startup_thread: run() method not found in class");
1062 /* set ThreadMXBean variables */
1064 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1065 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1067 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1068 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1069 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1070 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1072 #if defined(WITH_CLASSPATH_GNU)
1073 /* we need to start the run method of java.lang.VMThread */
1075 LLNI_field_get_ref(object, vmThread, vmt);
1076 o = (java_handle_t *) vmt;
1078 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1079 o = (java_handle_t *) object;
1081 # error unknown classpath configuration
1084 /* Run the thread. */
1086 (void) vm_call_method(m, o);
1089 /* set ThreadMXBean variables */
1091 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1092 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1094 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1095 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1096 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1097 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1099 /* call passed function, e.g. finalizer_thread */
1104 DEBUGTHREADS("stopping", t);
1106 #if defined(ENABLE_JVMTI)
1107 /* fire thread end event */
1110 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1113 /* We ignore the return value. */
1115 (void) threads_detach_thread(t);
1117 /* set ThreadMXBean variables */
1119 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1125 /* threads_impl_thread_start ***************************************************
1127 Start a thread in the JVM. Both (vm internal and java) thread
1131 thread....the thread object
1132 f.........function to run in the new thread. NULL means that the
1133 "run" method of the object `t` should be called
1135 ******************************************************************************/
1137 void threads_impl_thread_start(threadobject *thread, functionptr f)
1141 pthread_attr_t attr;
1142 startupinfo startup;
1145 /* fill startupinfo structure passed by pthread_create to
1146 * threads_startup_thread */
1148 startup.thread = thread;
1149 startup.function = f; /* maybe we don't call Thread.run()V */
1150 startup.psem = &sem;
1151 startup.psem_first = &sem_first;
1153 threads_sem_init(&sem, 0, 0);
1154 threads_sem_init(&sem_first, 0, 0);
1156 /* Initialize thread attributes. */
1158 result = pthread_attr_init(&attr);
1161 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
1163 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1166 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
1168 /* initialize thread stacksize */
1170 result = pthread_attr_setstacksize(&attr, opt_stacksize);
1173 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
1175 /* create the thread */
1177 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1180 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1182 /* destroy the thread attributes */
1184 result = pthread_attr_destroy(&attr);
1187 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1189 /* signal that pthread_create has returned, so thread->tid is valid */
1191 threads_sem_post(&sem_first);
1193 /* wait here until the thread has entered itself into the thread list */
1195 threads_sem_wait(&sem);
1200 sem_destroy(&sem_first);
1204 /* threads_set_thread_priority *************************************************
1206 Set the priority of the given thread.
1209 tid..........thread id
1210 priority.....priority to set
1212 ******************************************************************************/
1214 void threads_set_thread_priority(pthread_t tid, int priority)
1216 struct sched_param schedp;
1219 pthread_getschedparam(tid, &policy, &schedp);
1220 schedp.sched_priority = priority;
1221 pthread_setschedparam(tid, policy, &schedp);
1225 /* threads_detach_thread *******************************************************
1227 Detaches the passed thread from the VM. Used in JNI.
1229 *******************************************************************************/
1231 bool threads_detach_thread(threadobject *t)
1234 java_lang_Thread *object;
1236 #if defined(ENABLE_JAVASE)
1237 java_lang_ThreadGroup *group;
1244 /* If the given thread has already been detached, this operation
1247 result = thread_is_attached(t);
1249 if (result == false)
1252 DEBUGTHREADS("detaching", t);
1254 object = (java_lang_Thread *) thread_get_object(t);
1256 #if defined(ENABLE_JAVASE)
1257 LLNI_field_get_ref(object, group, group);
1259 /* If there's an uncaught exception, call uncaughtException on the
1260 thread's exception handler, or the thread's group if this is
1263 e = exceptions_get_and_clear_exception();
1266 /* We use the type void* for handler here, as it's not trivial
1267 to build the java_lang_Thread_UncaughtExceptionHandler
1268 header file with cacaoh. */
1270 # if defined(WITH_CLASSPATH_GNU)
1271 LLNI_field_get_ref(object, exceptionHandler, handler);
1272 # elif defined(WITH_CLASSPATH_SUN)
1273 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1276 if (handler != NULL) {
1277 LLNI_class_get(handler, c);
1278 o = (java_handle_t *) handler;
1281 LLNI_class_get(group, c);
1282 o = (java_handle_t *) group;
1285 m = class_resolveclassmethod(c,
1286 utf_uncaughtException,
1287 utf_java_lang_Thread_java_lang_Throwable__V,
1294 (void) vm_call_method(m, o, object, e);
1296 if (exceptions_get_exception())
1300 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1302 /* Remove thread from the thread group. */
1304 if (group != NULL) {
1305 LLNI_class_get(group, c);
1307 # if defined(WITH_CLASSPATH_GNU)
1308 m = class_resolveclassmethod(c,
1310 utf_java_lang_Thread__V,
1311 class_java_lang_ThreadGroup,
1313 # elif defined(WITH_CLASSPATH_SUN)
1314 m = class_resolveclassmethod(c,
1316 utf_java_lang_Thread__V,
1317 class_java_lang_ThreadGroup,
1320 # error unknown classpath configuration
1326 o = (java_handle_t *) group;
1328 (void) vm_call_method(m, o, object);
1330 if (exceptions_get_exception())
1333 /* Reset the threadgroup in the Java thread object (Mauve
1334 test: gnu/testlet/java/lang/Thread/getThreadGroup). */
1336 LLNI_field_set_ref(object, group, NULL);
1340 /* Thread has terminated. */
1342 thread_set_state_terminated(t);
1344 /* Notify all threads waiting on this thread. These are joining
1347 o = (java_handle_t *) object;
1349 /* XXX Care about exceptions? */
1350 (void) lock_monitor_enter(o);
1352 lock_notify_all_object(o);
1354 /* XXX Care about exceptions? */
1355 (void) lock_monitor_exit(o);
1357 /* Enter the join-mutex before calling thread_free, so
1358 threads_join_all_threads gets the correct number of non-daemon
1361 threads_mutex_join_lock();
1363 /* Free the internal thread data-structure. */
1367 /* Signal that this thread has finished and leave the mutex. */
1369 pthread_cond_signal(&cond_join);
1370 threads_mutex_join_unlock();
1376 #if defined(ENABLE_GC_CACAO)
1378 /* threads_suspend_thread ******************************************************
1380 Suspend the passed thread. Execution stops until the thread
1381 is explicitly resumend again.
1384 reason.....Reason for suspending this thread.
1386 *******************************************************************************/
1388 bool threads_suspend_thread(threadobject *thread, s4 reason)
1390 /* acquire the suspendmutex */
1391 mutex_lock(&(thread->suspendmutex));
1393 if (thread->suspended) {
1394 mutex_unlock(&(thread->suspendmutex));
1398 /* set the reason for the suspension */
1399 thread->suspend_reason = reason;
1401 /* send the suspend signal to the thread */
1402 assert(thread != THREADOBJECT);
1403 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1404 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1407 /* REMEMBER: do not release the suspendmutex, this is done
1408 by the thread itself in threads_suspend_ack(). */
1414 /* threads_suspend_ack *********************************************************
1416 Acknowledges the suspension of the current thread.
1419 pc.....The PC where the thread suspended its execution.
1420 sp.....The SP before the thread suspended its execution.
1422 *******************************************************************************/
1424 void threads_suspend_ack(u1* pc, u1* sp)
1426 threadobject *thread;
1428 thread = THREADOBJECT;
1430 assert(thread->suspend_reason != 0);
1432 /* TODO: remember dump memory size */
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 */
1447 /* mark this thread as suspended and remember the PC */
1449 thread->suspended = true;
1451 /* if we are stopping the world, we should send a global ack */
1452 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1453 threads_sem_post(&suspend_ack);
1456 DEBUGTHREADS("suspending", thread);
1458 /* release the suspension mutex and wait till we are resumed */
1459 pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1461 DEBUGTHREADS("resuming", thread);
1463 /* if we are stopping the world, we should send a global ack */
1464 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1465 threads_sem_post(&suspend_ack);
1468 /* TODO: free dump memory */
1470 /* release the suspendmutex */
1471 mutex_unlock(&(thread->suspendmutex));
1475 /* threads_resume_thread *******************************************************
1477 Resumes the execution of the passed thread.
1479 *******************************************************************************/
1481 bool threads_resume_thread(threadobject *thread)
1483 /* acquire the suspendmutex */
1484 mutex_lock(&(thread->suspendmutex));
1486 if (!thread->suspended) {
1487 mutex_unlock(&(thread->suspendmutex));
1491 thread->suspended = false;
1493 /* tell everyone that the thread should resume */
1494 assert(thread != THREADOBJECT);
1495 pthread_cond_broadcast(&(thread->suspendcond));
1497 /* release the suspendmutex */
1498 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 thread_set_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 thread_set_state_timed_waiting(t);
1627 pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
1630 thread_set_state_runnable(t);
1635 while (!t->interrupted && !t->signaled) {
1636 thread_set_state_waiting(t);
1638 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1640 thread_set_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_sleep ***************************************************************
1747 Sleep the current thread for the specified amount of time.
1749 *******************************************************************************/
1751 void threads_sleep(int64_t millis, int32_t nanos)
1754 struct timespec wakeupTime;
1758 /* exceptions_throw_illegalargumentexception("timeout value is negative"); */
1759 exceptions_throw_illegalargumentexception();
1763 t = thread_get_current();
1765 if (thread_is_interrupted(t) && !exceptions_get_exception()) {
1766 /* Clear interrupted flag (Mauve test:
1767 gnu/testlet/java/lang/Thread/interrupt). */
1769 thread_set_interrupted(t, false);
1771 /* exceptions_throw_interruptedexception("sleep interrupted"); */
1772 exceptions_throw_interruptedexception();
1776 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1778 threads_wait_with_timeout(t, &wakeupTime);
1780 interrupted = thread_is_interrupted(t);
1783 thread_set_interrupted(t, false);
1785 /* An other exception could have been thrown
1786 (e.g. ThreadDeathException). */
1788 if (!exceptions_get_exception())
1789 exceptions_throw_interruptedexception();
1794 /* threads_yield ***************************************************************
1796 Yield to the scheduler.
1798 *******************************************************************************/
1800 void threads_yield(void)
1807 * These are local overrides for various environment variables in Emacs.
1808 * Please do not remove this and leave it at the end of the file, where
1809 * Emacs will automagically detect them.
1810 * ---------------------------------------------------------------------
1813 * indent-tabs-mode: t
1817 * vim:noexpandtab:sw=4:ts=4: