1 /* src/threads/native/threads.c - native threads support
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
29 Changes: Christian Thalinger
32 $Id: threads.c 5031 2006-06-14 18:36:22Z motse $
39 /* XXX cleanup these includes */
44 #include <sys/types.h>
57 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
58 # include "machine-instr.h"
60 # include "threads/native/generic-primitives.h"
64 #include "mm/memory.h"
65 #include "native/native.h"
66 #include "native/include/java_lang_Object.h"
67 #include "native/include/java_lang_Throwable.h"
68 #include "native/include/java_lang_Thread.h"
69 #include "native/include/java_lang_ThreadGroup.h"
70 #include "native/include/java_lang_VMThread.h"
71 #include "threads/native/threads.h"
72 #include "toolbox/avl.h"
73 #include "toolbox/logging.h"
74 #include "vm/builtin.h"
75 #include "vm/exceptions.h"
76 #include "vm/global.h"
77 #include "vm/loader.h"
78 #include "vm/options.h"
79 #include "vm/stringlocal.h"
81 #include "vm/jit/asmpart.h"
83 #if !defined(__DARWIN__)
84 # if defined(__LINUX__)
85 # define GC_LINUX_THREADS
86 # elif defined(__MIPS__)
87 # define GC_IRIX_THREADS
89 # include <semaphore.h>
90 # include "boehm-gc/include/gc.h"
93 #if defined(ENABLE_JVMTI)
94 #include "native/jvmti/cacaodbg.h"
97 #if defined(__DARWIN__)
98 /* Darwin has no working semaphore implementation. This one is taken
102 This is a very simple semaphore implementation for darwin. It
103 is implemented in terms of pthreads calls so it isn't async signal
104 safe. This isn't a problem because signals aren't used to
105 suspend threads on darwin.
108 static int sem_init(sem_t *sem, int pshared, int value)
115 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
118 if (pthread_cond_init(&sem->cond, NULL) < 0)
124 static int sem_post(sem_t *sem)
126 if (pthread_mutex_lock(&sem->mutex) < 0)
131 if (pthread_cond_signal(&sem->cond) < 0) {
132 pthread_mutex_unlock(&sem->mutex);
136 if (pthread_mutex_unlock(&sem->mutex) < 0)
142 static int sem_wait(sem_t *sem)
144 if (pthread_mutex_lock(&sem->mutex) < 0)
147 while (sem->value == 0) {
148 pthread_cond_wait(&sem->cond, &sem->mutex);
153 if (pthread_mutex_unlock(&sem->mutex) < 0)
159 static int sem_destroy(sem_t *sem)
161 if (pthread_cond_destroy(&sem->cond) < 0)
164 if (pthread_mutex_destroy(&sem->mutex) < 0)
169 #endif /* defined(__DARWIN__) */
172 /* internally used constants **************************************************/
174 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
175 #define STOPWORLD_FROM_GC 1
176 #define STOPWORLD_FROM_CLASS_NUMBERING 2
178 #define THREADS_INITIAL_TABLE_SIZE 8
181 /* startupinfo *****************************************************************
183 Struct used to pass info from threads_start_thread to
184 threads_startup_thread.
186 ******************************************************************************/
189 threadobject *thread; /* threadobject for this thread */
190 functionptr function; /* function to run in the new thread */
191 sem_t *psem; /* signals when thread has been entered */
192 /* in the thread list */
193 sem_t *psem_first; /* signals when pthread_create has returned */
197 /* prototypes *****************************************************************/
199 static void threads_table_init(void);
200 static s4 threads_table_add(threadobject *thread);
201 static void threads_table_remove(threadobject *thread);
202 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
205 static void threads_table_dump(FILE *file);
208 /******************************************************************************/
209 /* GLOBAL VARIABLES */
210 /******************************************************************************/
212 /* the main thread */
213 threadobject *mainthreadobj;
215 /* the thread object of the current thread */
216 /* This is either a thread-local variable defined with __thread, or */
217 /* a thread-specific value stored with key threads_current_threadobject_key. */
218 #if defined(HAVE___THREAD)
219 __thread threadobject *threads_current_threadobject;
221 pthread_key_t threads_current_threadobject_key;
224 /* global threads table */
225 static threads_table_t threads_table;
227 /* global compiler mutex */
228 static pthread_mutex_rec_t compiler_mutex;
230 /* global mutex for changing the thread list */
231 static pthread_mutex_t threadlistlock;
233 /* global mutex for stop-the-world */
234 static pthread_mutex_t stopworldlock;
236 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
238 static volatile int stopworldwhere;
240 /* semaphore used for acknowleding thread suspension */
241 static sem_t suspend_ack;
242 #if defined(__MIPS__)
243 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
244 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
247 static pthread_attr_t threadattr;
249 /* mutexes used by the fake atomic instructions */
250 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
251 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
252 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
253 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
257 /******************************************************************************/
258 /* Recursive Mutex Implementation for Darwin */
259 /******************************************************************************/
261 #if defined(MUTEXSIM)
263 /* We need this for older MacOSX (10.1.x) */
265 void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
267 pthread_mutex_init(&m->mutex, NULL);
271 void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
273 pthread_mutex_destroy(&m->mutex);
276 void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
281 pthread_mutex_lock(&m->mutex);
282 m->owner = pthread_self();
287 if (m->owner != pthread_self()) {
288 pthread_mutex_lock(&m->mutex);
298 void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
301 pthread_mutex_unlock(&m->mutex);
304 #endif /* defined(MUTEXSIM) */
307 /* threads_sem_init ************************************************************
309 Initialize a semaphore. Checks against errors and interruptions.
312 sem..............the semaphore to initialize
313 shared...........true if this semaphore will be shared between processes
314 value............the initial value for the semaphore
316 *******************************************************************************/
318 void threads_sem_init(sem_t *sem, bool shared, int value)
325 r = sem_init(sem, shared, value);
328 } while (errno == EINTR);
330 vm_abort("sem_init failed: %s", strerror(errno));
334 /* threads_sem_wait ************************************************************
336 Wait for a semaphore, non-interruptible.
338 IMPORTANT: Always use this function instead of `sem_wait` directly, as
339 `sem_wait` may be interrupted by signals!
342 sem..............the semaphore to wait on
344 *******************************************************************************/
346 void threads_sem_wait(sem_t *sem)
356 } while (errno == EINTR);
358 vm_abort("sem_wait failed: %s", strerror(errno));
362 /* threads_sem_post ************************************************************
364 Increase the count of a semaphore. Checks for errors.
367 sem..............the semaphore to increase the count of
369 *******************************************************************************/
371 void threads_sem_post(sem_t *sem)
377 /* unlike sem_wait, sem_post is not interruptible */
383 vm_abort("sem_post failed: %s", strerror(errno));
387 /* threads_set_thread_priority *************************************************
389 Set the priority of the given thread.
392 tid..........thread id
393 priority.....priority to set
395 ******************************************************************************/
397 static void threads_set_thread_priority(pthread_t tid, int priority)
399 struct sched_param schedp;
402 pthread_getschedparam(tid, &policy, &schedp);
403 schedp.sched_priority = priority;
404 pthread_setschedparam(tid, policy, &schedp);
408 /* compiler_lock ***************************************************************
410 Enter the compiler lock.
412 ******************************************************************************/
414 void compiler_lock(void)
416 pthread_mutex_lock_rec(&compiler_mutex);
420 /* compiler_unlock *************************************************************
422 Release the compiler lock.
424 ******************************************************************************/
426 void compiler_unlock(void)
428 pthread_mutex_unlock_rec(&compiler_mutex);
432 /* lock_stopworld **************************************************************
434 Enter the stopworld lock, specifying why the world shall be stopped.
437 where........ STOPWORLD_FROM_GC (1) from within GC
438 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
440 ******************************************************************************/
442 void lock_stopworld(int where)
444 pthread_mutex_lock(&stopworldlock);
445 stopworldwhere = where;
449 /* unlock_stopworld ************************************************************
451 Release the stopworld lock.
453 ******************************************************************************/
455 void unlock_stopworld(void)
458 pthread_mutex_unlock(&stopworldlock);
461 #if !defined(__DARWIN__)
462 /* Caller must hold threadlistlock */
463 static int threads_cast_sendsignals(int sig, int count)
466 threadobject *tobj = mainthreadobj;
467 threadobject *self = THREADOBJECT;
473 } while (tobj != mainthreadobj);
476 assert(tobj == mainthreadobj);
480 pthread_kill(tobj->tid, sig);
482 } while (tobj != mainthreadobj);
489 static void threads_cast_darwinstop(void)
491 threadobject *tobj = mainthreadobj;
492 threadobject *self = THREADOBJECT;
497 thread_state_flavor_t flavor = PPC_THREAD_STATE;
498 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
499 ppc_thread_state_t thread_state;
500 mach_port_t thread = tobj->mach_thread;
503 r = thread_suspend(thread);
504 if (r != KERN_SUCCESS) {
505 log_text("thread_suspend failed");
509 r = thread_get_state(thread, flavor,
510 (natural_t*)&thread_state, &thread_state_count);
511 if (r != KERN_SUCCESS) {
512 log_text("thread_get_state failed");
516 thread_restartcriticalsection(&thread_state);
518 r = thread_set_state(thread, flavor,
519 (natural_t*)&thread_state, thread_state_count);
520 if (r != KERN_SUCCESS) {
521 log_text("thread_set_state failed");
526 } while (tobj != mainthreadobj);
529 static void threads_cast_darwinresume(void)
531 threadobject *tobj = mainthreadobj;
532 threadobject *self = THREADOBJECT;
537 mach_port_t thread = tobj->mach_thread;
540 r = thread_resume(thread);
541 if (r != KERN_SUCCESS) {
542 log_text("thread_resume failed");
547 } while (tobj != mainthreadobj);
552 #if defined(__MIPS__)
553 static void threads_cast_irixresume(void)
555 pthread_mutex_lock(&suspend_ack_lock);
556 pthread_cond_broadcast(&suspend_cond);
557 pthread_mutex_unlock(&suspend_ack_lock);
561 void threads_cast_stopworld(void)
564 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
565 pthread_mutex_lock(&threadlistlock);
566 #if defined(__DARWIN__)
567 threads_cast_darwinstop();
569 count = threads_cast_sendsignals(GC_signum1(), 0);
570 for (i=0; i<count; i++)
571 threads_sem_wait(&suspend_ack);
573 pthread_mutex_unlock(&threadlistlock);
576 void threads_cast_startworld(void)
578 pthread_mutex_lock(&threadlistlock);
579 #if defined(__DARWIN__)
580 threads_cast_darwinresume();
581 #elif defined(__MIPS__)
582 threads_cast_irixresume();
584 threads_cast_sendsignals(GC_signum2(), -1);
586 pthread_mutex_unlock(&threadlistlock);
590 #if !defined(__DARWIN__)
591 static void threads_sigsuspend_handler(ucontext_t *ctx)
596 /* XXX TWISTI: this is just a quick hack */
597 #if defined(ENABLE_JIT)
598 thread_restartcriticalsection(ctx);
601 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
602 (not POSIX async-safe). */
603 #if defined(__IRIX__)
604 pthread_mutex_lock(&suspend_ack_lock);
605 threads_sem_post(&suspend_ack);
606 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
607 pthread_mutex_unlock(&suspend_ack_lock);
609 threads_sem_post(&suspend_ack);
613 sigdelset(&sigs, sig);
618 /* This function is called from Boehm GC code. */
620 int cacao_suspendhandler(ucontext_t *ctx)
622 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
625 threads_sigsuspend_handler(ctx);
630 /* threads_set_current_threadobject ********************************************
632 Set the current thread object.
635 thread.......the thread object to set
637 *******************************************************************************/
639 static void threads_set_current_threadobject(threadobject *thread)
641 #if !defined(HAVE___THREAD)
642 pthread_setspecific(threads_current_threadobject_key, thread);
644 threads_current_threadobject = thread;
649 /* threads_get_current_threadobject ********************************************
651 Return the threadobject of the current thread.
654 the current threadobject * (an instance of java.lang.VMThread)
656 *******************************************************************************/
658 threadobject *threads_get_current_threadobject(void)
664 /* threads_preinit *************************************************************
666 Do some early initialization of stuff required.
668 *******************************************************************************/
670 void threads_preinit(void)
673 pthread_mutexattr_t mutexattr;
674 pthread_mutexattr_init(&mutexattr);
675 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
676 pthread_mutex_init(&compiler_mutex, &mutexattr);
677 pthread_mutexattr_destroy(&mutexattr);
679 pthread_mutex_init_rec(&compiler_mutex);
682 pthread_mutex_init(&threadlistlock, NULL);
683 pthread_mutex_init(&stopworldlock, NULL);
685 /* Allocate something so the garbage collector's signal handlers
687 heap_allocate(1, false, NULL);
689 mainthreadobj = NEW(threadobject);
690 mainthreadobj->tid = pthread_self();
691 mainthreadobj->index = 1;
692 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
694 #if !defined(HAVE___THREAD)
695 pthread_key_create(&threads_current_threadobject_key, NULL);
697 threads_set_current_threadobject(mainthreadobj);
699 threads_sem_init(&suspend_ack, 0, 0);
701 /* initialize the threads table */
703 threads_table_init();
705 /* initialize subsystems */
713 /* threads_init ****************************************************************
715 Initializes the threads required by the JVM: main, finalizer.
717 *******************************************************************************/
719 bool threads_init(void)
721 java_lang_String *threadname;
722 java_lang_Thread *mainthread;
723 java_lang_ThreadGroup *threadgroup;
724 threadobject *tempthread;
727 tempthread = mainthreadobj;
729 /* XXX We have to find a new way to free lock records */
730 /* with the new locking algorithm. */
731 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
733 /* This is kinda tricky, we grow the java.lang.Thread object so we
734 can keep the execution environment there. No Thread object must
735 have been created at an earlier time. */
737 class_java_lang_VMThread->instancesize = sizeof(threadobject);
739 /* create a VMThread */
741 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
743 if (mainthreadobj == NULL)
746 FREE(tempthread, threadobject);
748 threads_init_threadobject(&mainthreadobj->o);
750 threads_set_current_threadobject(mainthreadobj);
752 lock_init_execution_env(mainthreadobj);
754 mainthreadobj->next = mainthreadobj;
755 mainthreadobj->prev = mainthreadobj;
757 threads_table_add(mainthreadobj);
759 #if defined(ENABLE_INTRP)
760 /* create interpreter stack */
763 MSET(intrp_main_stack, 0, u1, opt_stacksize);
764 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
768 threadname = javastring_new(utf_new_char("main"));
770 /* allocate and init ThreadGroup */
772 threadgroup = (java_lang_ThreadGroup *)
773 native_new_and_init(class_java_lang_ThreadGroup);
776 throw_exception_exit();
778 /* create a Thread */
780 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
782 if (mainthread == NULL)
783 throw_exception_exit();
785 mainthreadobj->o.thread = mainthread;
787 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
789 method = class_resolveclassmethod(class_java_lang_Thread,
791 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
792 class_java_lang_Thread,
798 (void) vm_call_method(method, (java_objectheader *) mainthread,
799 mainthreadobj, threadname, 5, false);
804 mainthread->group = threadgroup;
806 /* add mainthread to ThreadGroup */
808 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
809 utf_new_char("addThread"),
810 utf_new_char("(Ljava/lang/Thread;)V"),
811 class_java_lang_ThreadGroup,
817 (void) vm_call_method(method, (java_objectheader *) threadgroup,
823 threads_set_thread_priority(pthread_self(), 5);
825 /* initialize the thread attribute object */
827 if (pthread_attr_init(&threadattr)) {
828 log_println("pthread_attr_init failed: %s", strerror(errno));
832 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
834 /* everything's ok */
840 /* threads_table_init *********************************************************
842 Initialize the global threads table.
844 ******************************************************************************/
846 static void threads_table_init(void)
851 size = THREADS_INITIAL_TABLE_SIZE;
853 threads_table.size = size;
854 threads_table.table = MNEW(threads_table_entry_t, size);
856 /* link the entries in a freelist */
858 for (i=0; i<size; ++i) {
859 threads_table.table[i].nextfree = i+1;
862 /* terminate the freelist */
864 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
868 /* threads_table_add **********************************************************
870 Add a thread to the global threads table. The index is entered in the
871 threadobject. The thinlock value for the thread is pre-computed.
874 thread............the thread to add
877 The table index for the newly added thread. This value has also been
878 entered in the threadobject.
881 The caller must hold the threadlistlock!
883 ******************************************************************************/
885 static s4 threads_table_add(threadobject *thread)
892 /* table[0] serves as the head of the freelist */
894 index = threads_table.table[0].nextfree;
896 /* if we got a free index, use it */
900 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
901 threads_table.table[index].thread = thread;
902 thread->index = index;
903 thread->thinlock = lock_pre_compute_thinlock(index);
907 /* we must grow the table */
909 oldsize = threads_table.size;
910 newsize = oldsize * 2;
912 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
914 threads_table.size = newsize;
916 /* link the new entries to a free list */
918 for (i=oldsize; i<newsize; ++i) {
919 threads_table.table[i].nextfree = i+1;
922 /* terminate the freelist */
924 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
926 /* use the first of the new entries */
933 /* threads_table_remove *******************************************************
935 Remove a thread from the global threads table.
938 thread............the thread to remove
941 The caller must hold the threadlistlock!
943 ******************************************************************************/
945 static void threads_table_remove(threadobject *thread)
949 index = thread->index;
951 /* put the index into the freelist */
953 threads_table.table[index] = threads_table.table[0];
954 threads_table.table[0].nextfree = index;
956 /* delete the index in the threadobject to discover bugs */
962 /* threads_init_threadobject **************************************************
964 Initialize implementation fields of a java.lang.VMThread.
967 t............the java.lang.VMThread
969 ******************************************************************************/
971 void threads_init_threadobject(java_lang_VMThread *t)
973 threadobject *thread = (threadobject*) t;
975 thread->tid = pthread_self();
979 /* TODO destroy all those things */
980 pthread_mutex_init(&(thread->joinmutex), NULL);
981 pthread_cond_init(&(thread->joincond), NULL);
983 pthread_mutex_init(&(thread->waitmutex), NULL);
984 pthread_cond_init(&(thread->waitcond), NULL);
986 thread->interrupted = false;
987 thread->signaled = false;
988 thread->sleeping = false;
992 /* threads_startup_thread ******************************************************
994 Thread startup function called by pthread_create.
996 NOTE: This function is not called directly by pthread_create. The Boehm GC
997 inserts its own GC_start_routine in between, which then calls
1001 t............the argument passed to pthread_create, ie. a pointer to
1002 a startupinfo struct. CAUTION: When the `psem` semaphore
1003 is posted, the startupinfo struct becomes invalid! (It
1004 is allocated on the stack of threads_start_thread.)
1006 ******************************************************************************/
1008 static void *threads_startup_thread(void *t)
1010 startupinfo *startup;
1011 threadobject *thread;
1013 threadobject *tnext;
1015 functionptr function;
1017 #if defined(ENABLE_INTRP)
1018 u1 *intrp_thread_stack;
1020 /* create interpreter stack */
1023 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1024 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1027 intrp_thread_stack = NULL;
1030 /* get passed startupinfo structure and the values in there */
1033 t = NULL; /* make sure it's not used wrongly */
1035 thread = startup->thread;
1036 function = startup->function;
1037 psem = startup->psem;
1039 /* Seems like we've encountered a situation where thread->tid was not set by
1040 * pthread_create. We alleviate this problem by waiting for pthread_create
1042 threads_sem_wait(startup->psem_first);
1044 /* set the thread object */
1046 #if defined(__DARWIN__)
1047 thread->mach_thread = mach_thread_self();
1049 threads_set_current_threadobject(thread);
1051 /* insert the thread into the threadlist and the threads table */
1053 pthread_mutex_lock(&threadlistlock);
1055 thread->prev = mainthreadobj;
1056 thread->next = tnext = mainthreadobj->next;
1057 mainthreadobj->next = thread;
1058 tnext->prev = thread;
1060 threads_table_add(thread);
1062 pthread_mutex_unlock(&threadlistlock);
1064 /* init data structures of this thread */
1066 lock_init_execution_env(thread);
1068 /* tell threads_startup_thread that we registered ourselves */
1069 /* CAUTION: *startup becomes invalid with this! */
1072 threads_sem_post(psem);
1074 /* set our priority */
1076 threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1078 #if defined(ENABLE_INTRP)
1079 /* set interpreter stack */
1082 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1087 #if defined(ENABLE_JVMTI)
1088 /* fire thread start event */
1089 if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1093 /* find and run the Thread.run()V method if no other function was passed */
1095 if (function == NULL) {
1096 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1099 thread->o.header.vftbl->class,
1105 (void) vm_call_method(method, (java_objectheader *) thread);
1109 /* call passed function, e.g. finalizer_thread */
1114 #if defined(ENABLE_JVMTI)
1115 /* fire thread end event */
1116 if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1120 /* Allow lock record pools to be used by other threads. They
1121 cannot be deleted so we'd better not waste them. */
1123 /* XXX We have to find a new way to free lock records */
1124 /* with the new locking algorithm. */
1125 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1127 /* remove thread from thread list and threads table, do this inside a lock */
1129 pthread_mutex_lock(&threadlistlock);
1131 thread->next->prev = thread->prev;
1132 thread->prev->next = thread->next;
1134 threads_table_remove(thread);
1136 pthread_mutex_unlock(&threadlistlock);
1138 /* reset thread id (lock on joinmutex? TWISTI) */
1140 pthread_mutex_lock(&thread->joinmutex);
1142 pthread_mutex_unlock(&thread->joinmutex);
1144 /* tell everyone that a thread has finished */
1146 pthread_cond_broadcast(&thread->joincond);
1152 /* threads_start_thread ********************************************************
1154 Start a thread in the JVM.
1157 t............the java.lang.Thread object
1158 function.....function to run in the new thread. NULL means that the
1159 "run" method of the object `t` should be called
1161 ******************************************************************************/
1163 void threads_start_thread(java_lang_Thread *t, functionptr function)
1167 pthread_attr_t attr;
1168 startupinfo startup;
1169 threadobject *thread;
1171 thread = (threadobject *) t->vmThread;
1173 /* fill startupinfo structure passed by pthread_create to
1174 * threads_startup_thread */
1176 startup.thread = thread;
1177 startup.function = function; /* maybe we don't call Thread.run()V */
1178 startup.psem = &sem;
1179 startup.psem_first = &sem_first;
1181 threads_sem_init(&sem, 0, 0);
1182 threads_sem_init(&sem_first, 0, 0);
1184 /* initialize thread attribute object */
1186 if (pthread_attr_init(&attr))
1187 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1189 /* initialize thread stacksize */
1191 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1192 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1194 /* create the thread */
1196 if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1197 vm_abort("pthread_create failed: %s", strerror(errno));
1199 /* signal that pthread_create has returned, so thread->tid is valid */
1201 threads_sem_post(&sem_first);
1203 /* wait here until the thread has entered itself into the thread list */
1205 threads_sem_wait(&sem);
1210 sem_destroy(&sem_first);
1214 /* threads_find_non_daemon_thread **********************************************
1216 Helper function used by threads_join_all_threads for finding
1217 non-daemon threads that are still running.
1219 *******************************************************************************/
1221 /* At the end of the program, we wait for all running non-daemon
1224 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1226 while (thread != mainthreadobj) {
1227 if (!thread->o.thread->daemon)
1229 thread = thread->prev;
1236 /* threads_join_all_threads ****************************************************
1238 Join all non-daemon threads.
1240 *******************************************************************************/
1242 void threads_join_all_threads(void)
1244 threadobject *thread;
1246 pthread_mutex_lock(&threadlistlock);
1248 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1250 pthread_mutex_lock(&thread->joinmutex);
1252 pthread_mutex_unlock(&threadlistlock);
1255 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1257 pthread_mutex_unlock(&thread->joinmutex);
1259 pthread_mutex_lock(&threadlistlock);
1262 pthread_mutex_unlock(&threadlistlock);
1266 /* threads_timespec_earlier ****************************************************
1268 Return true if timespec tv1 is earlier than timespec tv2.
1271 tv1..........first timespec
1272 tv2..........second timespec
1275 true, if the first timespec is earlier
1277 *******************************************************************************/
1279 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1280 const struct timespec *tv2)
1282 return (tv1->tv_sec < tv2->tv_sec)
1284 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1288 /* threads_current_time_is_earlier_than ****************************************
1290 Check if the current time is earlier than the given timespec.
1293 tv...........the timespec to compare against
1296 true, if the current time is earlier
1298 *******************************************************************************/
1300 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1302 struct timeval tvnow;
1303 struct timespec tsnow;
1305 /* get current time */
1307 if (gettimeofday(&tvnow, NULL) != 0)
1308 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1310 /* convert it to a timespec */
1312 tsnow.tv_sec = tvnow.tv_sec;
1313 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1315 /* compare current time with the given timespec */
1317 return threads_timespec_earlier(&tsnow, tv);
1321 /* threads_wait_with_timeout ***************************************************
1323 Wait until the given point in time on a monitor until either
1324 we are notified, we are interrupted, or the time is up.
1327 t............the current thread
1328 wakeupTime...absolute (latest) wakeup time
1329 If both tv_sec and tv_nsec are zero, this function
1330 waits for an unlimited amount of time.
1333 true.........if the wait has been interrupted,
1334 false........if the wait was ended by notification or timeout
1336 *******************************************************************************/
1338 static bool threads_wait_with_timeout(threadobject *t,
1339 struct timespec *wakeupTime)
1341 bool wasinterrupted;
1343 /* acquire the waitmutex */
1345 pthread_mutex_lock(&t->waitmutex);
1347 /* mark us as sleeping */
1351 /* wait on waitcond */
1353 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1355 while (!t->interrupted && !t->signaled
1356 && threads_current_time_is_earlier_than(wakeupTime))
1358 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1363 while (!t->interrupted && !t->signaled)
1364 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1367 /* check if we were interrupted */
1369 wasinterrupted = t->interrupted;
1371 /* reset all flags */
1373 t->interrupted = false;
1374 t->signaled = false;
1375 t->sleeping = false;
1377 /* release the waitmutex */
1379 pthread_mutex_unlock(&t->waitmutex);
1381 return wasinterrupted;
1385 /* threads_wait_with_timeout_relative ******************************************
1387 Wait for the given maximum amount of time on a monitor until either
1388 we are notified, we are interrupted, or the time is up.
1391 t............the current thread
1392 millis.......milliseconds to wait
1393 nanos........nanoseconds to wait
1396 true.........if the wait has been interrupted,
1397 false........if the wait was ended by notification or timeout
1399 *******************************************************************************/
1401 bool threads_wait_with_timeout_relative(threadobject *t,
1405 struct timespec wakeupTime;
1407 /* calculate the the (latest) wakeup time */
1409 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1413 return threads_wait_with_timeout(t, &wakeupTime);
1417 /* threads_calc_absolute_time **************************************************
1419 Calculate the absolute point in time a given number of ms and ns from now.
1422 millis............milliseconds from now
1423 nanos.............nanoseconds from now
1426 *tm...............receives the timespec of the absolute point in time
1428 *******************************************************************************/
1430 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1432 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1435 gettimeofday(&tv, NULL);
1436 tv.tv_sec += millis / 1000;
1438 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1439 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1440 tm->tv_nsec = nsec % 1000000000;
1449 /* threads_interrupt_thread ****************************************************
1451 Interrupt the given thread.
1453 The thread gets the "waitcond" signal and
1454 its interrupted flag is set to true.
1457 thread............the thread to interrupt
1459 *******************************************************************************/
1461 void threads_interrupt_thread(java_lang_VMThread *thread)
1463 threadobject *t = (threadobject*) thread;
1465 /* signal the thread a "waitcond" and tell it that it has been */
1468 pthread_mutex_lock(&t->waitmutex);
1470 pthread_cond_signal(&t->waitcond);
1471 t->interrupted = true;
1472 pthread_mutex_unlock(&t->waitmutex);
1476 /* threads_check_if_interrupted_and_reset **************************************
1478 Check if the current thread has been interrupted and reset the
1482 true, if the current thread had been interrupted
1484 *******************************************************************************/
1486 bool threads_check_if_interrupted_and_reset(void)
1491 t = (threadobject*) THREADOBJECT;
1493 intr = t->interrupted;
1495 t->interrupted = false;
1501 /* threads_thread_has_been_interrupted *********************************************************
1503 Check if the given thread has been interrupted
1506 t............the thread to check
1509 true, if the given thread had been interrupted
1511 *******************************************************************************/
1513 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1517 t = (threadobject*) thread;
1519 return t->interrupted;
1523 /* threads_sleep ***************************************************************
1525 Sleep the current thread for the specified amount of time.
1527 *******************************************************************************/
1529 void threads_sleep(s8 millis, s4 nanos)
1532 struct timespec wakeupTime;
1533 bool wasinterrupted;
1535 t = (threadobject *) THREADOBJECT;
1537 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1539 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1542 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1546 /* threads_yield *****************************************************************
1548 Yield to the scheduler.
1550 *******************************************************************************/
1552 void threads_yield(void)
1558 /* threads_java_lang_Thread_set_priority ***********************************************************
1560 Set the priority for the given java.lang.Thread.
1563 t............the java.lang.Thread
1564 priority.....the priority
1566 *******************************************************************************/
1568 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1570 threadobject *thread;
1572 thread = (threadobject*) t->vmThread;
1574 threads_set_thread_priority(thread->tid, priority);
1578 /* threads_dump ****************************************************************
1580 Dumps info for all threads running in the JVM. This function is
1581 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1583 *******************************************************************************/
1585 void threads_dump(void)
1588 java_lang_VMThread *vmt;
1589 java_lang_Thread *t;
1592 tobj = mainthreadobj;
1594 printf("Full thread dump CACAO "VERSION":\n");
1596 /* iterate over all started threads */
1599 /* get thread objects */
1604 /* the thread may be currently in initalization, don't print it */
1607 /* get thread name */
1609 name = javastring_toutf(t->name, false);
1612 utf_display_printable_ascii(name);
1618 #if SIZEOF_VOID_P == 8
1619 printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1621 printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1624 /* send SIGUSR1 to thread to print stacktrace */
1626 pthread_kill(tobj->tid, SIGUSR1);
1628 /* sleep this thread a bit, so the signal can reach the thread */
1630 threads_sleep(10, 0);
1634 } while (tobj && (tobj != mainthreadobj));
1638 /* threads_table_dump *********************************************************
1640 Dump the threads table for debugging purposes.
1643 file..............stream to write to
1645 ******************************************************************************/
1647 #if !defined(NDEBUG)
1648 static void threads_table_dump(FILE *file)
1654 pthread_mutex_lock(&threadlistlock);
1656 size = threads_table.size;
1658 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1660 for (i=0; i<size; ++i) {
1661 index = threads_table.table[i].nextfree;
1663 fprintf(file, "%4d: ", i);
1666 fprintf(file, "free, nextfree = %d\n", index);
1669 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1673 fprintf(file, "======== END OF THREADS TABLE ========\n");
1675 pthread_mutex_unlock(&threadlistlock);
1680 * These are local overrides for various environment variables in Emacs.
1681 * Please do not remove this and leave it at the end of the file, where
1682 * Emacs will automagically detect them.
1683 * ---------------------------------------------------------------------
1686 * indent-tabs-mode: t
1690 * vim:noexpandtab:sw=4:ts=4: