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 5255 2006-08-21 15:17:48Z twisti $
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 = MACHINE_THREAD_STATE;
498 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
499 #if defined(__I386__)
500 i386_thread_state_t thread_state;
502 ppc_thread_state_t thread_state;
504 mach_port_t thread = tobj->mach_thread;
507 r = thread_suspend(thread);
508 if (r != KERN_SUCCESS) {
509 log_text("thread_suspend failed");
513 r = thread_get_state(thread, flavor,
514 (natural_t*)&thread_state, &thread_state_count);
515 if (r != KERN_SUCCESS) {
516 log_text("thread_get_state failed");
520 thread_restartcriticalsection(&thread_state);
522 r = thread_set_state(thread, flavor,
523 (natural_t*)&thread_state, thread_state_count);
524 if (r != KERN_SUCCESS) {
525 log_text("thread_set_state failed");
530 } while (tobj != mainthreadobj);
533 static void threads_cast_darwinresume(void)
535 threadobject *tobj = mainthreadobj;
536 threadobject *self = THREADOBJECT;
541 mach_port_t thread = tobj->mach_thread;
544 r = thread_resume(thread);
545 if (r != KERN_SUCCESS) {
546 log_text("thread_resume failed");
551 } while (tobj != mainthreadobj);
556 #if defined(__MIPS__)
557 static void threads_cast_irixresume(void)
559 pthread_mutex_lock(&suspend_ack_lock);
560 pthread_cond_broadcast(&suspend_cond);
561 pthread_mutex_unlock(&suspend_ack_lock);
565 void threads_cast_stopworld(void)
568 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
569 pthread_mutex_lock(&threadlistlock);
570 #if defined(__DARWIN__)
571 threads_cast_darwinstop();
573 count = threads_cast_sendsignals(GC_signum1(), 0);
574 for (i=0; i<count; i++)
575 threads_sem_wait(&suspend_ack);
577 pthread_mutex_unlock(&threadlistlock);
580 void threads_cast_startworld(void)
582 pthread_mutex_lock(&threadlistlock);
583 #if defined(__DARWIN__)
584 threads_cast_darwinresume();
585 #elif defined(__MIPS__)
586 threads_cast_irixresume();
588 threads_cast_sendsignals(GC_signum2(), -1);
590 pthread_mutex_unlock(&threadlistlock);
594 #if !defined(__DARWIN__)
595 static void threads_sigsuspend_handler(ucontext_t *ctx)
600 /* XXX TWISTI: this is just a quick hack */
601 #if defined(ENABLE_JIT)
602 thread_restartcriticalsection(ctx);
605 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
606 (not POSIX async-safe). */
607 #if defined(__IRIX__)
608 pthread_mutex_lock(&suspend_ack_lock);
609 threads_sem_post(&suspend_ack);
610 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
611 pthread_mutex_unlock(&suspend_ack_lock);
613 threads_sem_post(&suspend_ack);
617 sigdelset(&sigs, sig);
622 /* This function is called from Boehm GC code. */
624 int cacao_suspendhandler(ucontext_t *ctx)
626 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
629 threads_sigsuspend_handler(ctx);
634 /* threads_set_current_threadobject ********************************************
636 Set the current thread object.
639 thread.......the thread object to set
641 *******************************************************************************/
643 static void threads_set_current_threadobject(threadobject *thread)
645 #if !defined(HAVE___THREAD)
646 pthread_setspecific(threads_current_threadobject_key, thread);
648 threads_current_threadobject = thread;
653 /* threads_get_current_threadobject ********************************************
655 Return the threadobject of the current thread.
658 the current threadobject * (an instance of java.lang.VMThread)
660 *******************************************************************************/
662 threadobject *threads_get_current_threadobject(void)
668 /* threads_preinit *************************************************************
670 Do some early initialization of stuff required.
672 *******************************************************************************/
674 void threads_preinit(void)
677 pthread_mutexattr_t mutexattr;
678 pthread_mutexattr_init(&mutexattr);
679 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
680 pthread_mutex_init(&compiler_mutex, &mutexattr);
681 pthread_mutexattr_destroy(&mutexattr);
683 pthread_mutex_init_rec(&compiler_mutex);
686 pthread_mutex_init(&threadlistlock, NULL);
687 pthread_mutex_init(&stopworldlock, NULL);
689 /* Allocate something so the garbage collector's signal handlers
691 heap_allocate(1, false, NULL);
693 mainthreadobj = NEW(threadobject);
694 mainthreadobj->tid = pthread_self();
695 mainthreadobj->index = 1;
696 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
698 #if !defined(HAVE___THREAD)
699 pthread_key_create(&threads_current_threadobject_key, NULL);
701 threads_set_current_threadobject(mainthreadobj);
703 threads_sem_init(&suspend_ack, 0, 0);
705 /* initialize the threads table */
707 threads_table_init();
709 /* initialize subsystems */
717 /* threads_init ****************************************************************
719 Initializes the threads required by the JVM: main, finalizer.
721 *******************************************************************************/
723 bool threads_init(void)
725 java_lang_String *threadname;
726 java_lang_Thread *mainthread;
727 java_lang_ThreadGroup *threadgroup;
728 threadobject *tempthread;
731 tempthread = mainthreadobj;
733 /* XXX We have to find a new way to free lock records */
734 /* with the new locking algorithm. */
735 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
737 /* This is kinda tricky, we grow the java.lang.Thread object so we
738 can keep the execution environment there. No Thread object must
739 have been created at an earlier time. */
741 class_java_lang_VMThread->instancesize = sizeof(threadobject);
743 /* create a VMThread */
745 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
747 if (mainthreadobj == NULL)
750 FREE(tempthread, threadobject);
752 threads_init_threadobject(&mainthreadobj->o);
754 threads_set_current_threadobject(mainthreadobj);
756 lock_init_execution_env(mainthreadobj);
758 mainthreadobj->next = mainthreadobj;
759 mainthreadobj->prev = mainthreadobj;
761 threads_table_add(mainthreadobj);
763 /* mark main thread as Java thread */
765 mainthreadobj->flags = THREAD_FLAG_JAVA;
767 #if defined(ENABLE_INTRP)
768 /* create interpreter stack */
771 MSET(intrp_main_stack, 0, u1, opt_stacksize);
772 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
776 threadname = javastring_new(utf_new_char("main"));
778 /* allocate and init ThreadGroup */
780 threadgroup = (java_lang_ThreadGroup *)
781 native_new_and_init(class_java_lang_ThreadGroup);
784 throw_exception_exit();
786 /* create a Thread */
788 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
790 if (mainthread == NULL)
791 throw_exception_exit();
793 mainthreadobj->o.thread = mainthread;
795 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
797 method = class_resolveclassmethod(class_java_lang_Thread,
799 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
800 class_java_lang_Thread,
806 (void) vm_call_method(method, (java_objectheader *) mainthread,
807 mainthreadobj, threadname, 5, false);
812 mainthread->group = threadgroup;
814 /* add mainthread to ThreadGroup */
816 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
817 utf_new_char("addThread"),
818 utf_new_char("(Ljava/lang/Thread;)V"),
819 class_java_lang_ThreadGroup,
825 (void) vm_call_method(method, (java_objectheader *) threadgroup,
831 threads_set_thread_priority(pthread_self(), 5);
833 /* initialize the thread attribute object */
835 if (pthread_attr_init(&threadattr)) {
836 log_println("pthread_attr_init failed: %s", strerror(errno));
840 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
842 /* everything's ok */
848 /* threads_table_init *********************************************************
850 Initialize the global threads table.
852 ******************************************************************************/
854 static void threads_table_init(void)
859 size = THREADS_INITIAL_TABLE_SIZE;
861 threads_table.size = size;
862 threads_table.table = MNEW(threads_table_entry_t, size);
864 /* link the entries in a freelist */
866 for (i=0; i<size; ++i) {
867 threads_table.table[i].nextfree = i+1;
870 /* terminate the freelist */
872 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
876 /* threads_table_add **********************************************************
878 Add a thread to the global threads table. The index is entered in the
879 threadobject. The thinlock value for the thread is pre-computed.
882 thread............the thread to add
885 The table index for the newly added thread. This value has also been
886 entered in the threadobject.
889 The caller must hold the threadlistlock!
891 ******************************************************************************/
893 static s4 threads_table_add(threadobject *thread)
900 /* table[0] serves as the head of the freelist */
902 index = threads_table.table[0].nextfree;
904 /* if we got a free index, use it */
908 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
909 threads_table.table[index].thread = thread;
910 thread->index = index;
911 thread->thinlock = lock_pre_compute_thinlock(index);
915 /* we must grow the table */
917 oldsize = threads_table.size;
918 newsize = oldsize * 2;
920 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
922 threads_table.size = newsize;
924 /* link the new entries to a free list */
926 for (i=oldsize; i<newsize; ++i) {
927 threads_table.table[i].nextfree = i+1;
930 /* terminate the freelist */
932 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
934 /* use the first of the new entries */
941 /* threads_table_remove *******************************************************
943 Remove a thread from the global threads table.
946 thread............the thread to remove
949 The caller must hold the threadlistlock!
951 ******************************************************************************/
953 static void threads_table_remove(threadobject *thread)
957 index = thread->index;
959 /* put the index into the freelist */
961 threads_table.table[index] = threads_table.table[0];
962 threads_table.table[0].nextfree = index;
964 /* delete the index in the threadobject to discover bugs */
970 /* threads_init_threadobject **************************************************
972 Initialize implementation fields of a java.lang.VMThread.
975 t............the java.lang.VMThread
977 ******************************************************************************/
979 void threads_init_threadobject(java_lang_VMThread *t)
981 threadobject *thread = (threadobject*) t;
983 thread->tid = pthread_self();
987 /* TODO destroy all those things */
988 pthread_mutex_init(&(thread->joinmutex), NULL);
989 pthread_cond_init(&(thread->joincond), NULL);
991 pthread_mutex_init(&(thread->waitmutex), NULL);
992 pthread_cond_init(&(thread->waitcond), NULL);
994 thread->interrupted = false;
995 thread->signaled = false;
996 thread->sleeping = false;
1000 /* threads_startup_thread ******************************************************
1002 Thread startup function called by pthread_create.
1004 Thread which have a startup.function != NULL are marked as internal
1005 threads. All other threads are threated as normal Java threads.
1007 NOTE: This function is not called directly by pthread_create. The Boehm GC
1008 inserts its own GC_start_routine in between, which then calls
1012 t............the argument passed to pthread_create, ie. a pointer to
1013 a startupinfo struct. CAUTION: When the `psem` semaphore
1014 is posted, the startupinfo struct becomes invalid! (It
1015 is allocated on the stack of threads_start_thread.)
1017 ******************************************************************************/
1019 static void *threads_startup_thread(void *t)
1021 startupinfo *startup;
1022 threadobject *thread;
1024 threadobject *tnext;
1026 functionptr function;
1028 #if defined(ENABLE_INTRP)
1029 u1 *intrp_thread_stack;
1031 /* create interpreter stack */
1034 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1035 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1038 intrp_thread_stack = NULL;
1041 /* get passed startupinfo structure and the values in there */
1044 t = NULL; /* make sure it's not used wrongly */
1046 thread = startup->thread;
1047 function = startup->function;
1048 psem = startup->psem;
1050 /* Seems like we've encountered a situation where thread->tid was not set by
1051 * pthread_create. We alleviate this problem by waiting for pthread_create
1053 threads_sem_wait(startup->psem_first);
1055 /* set the thread object */
1057 #if defined(__DARWIN__)
1058 thread->mach_thread = mach_thread_self();
1060 threads_set_current_threadobject(thread);
1062 /* insert the thread into the threadlist and the threads table */
1064 pthread_mutex_lock(&threadlistlock);
1066 thread->prev = mainthreadobj;
1067 thread->next = tnext = mainthreadobj->next;
1068 mainthreadobj->next = thread;
1069 tnext->prev = thread;
1071 threads_table_add(thread);
1073 pthread_mutex_unlock(&threadlistlock);
1075 /* init data structures of this thread */
1077 lock_init_execution_env(thread);
1079 /* tell threads_startup_thread that we registered ourselves */
1080 /* CAUTION: *startup becomes invalid with this! */
1083 threads_sem_post(psem);
1085 /* set our priority */
1087 threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1089 #if defined(ENABLE_INTRP)
1090 /* set interpreter stack */
1093 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1098 #if defined(ENABLE_JVMTI)
1099 /* fire thread start event */
1100 if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1104 /* find and run the Thread.run()V method if no other function was passed */
1106 if (function == NULL) {
1107 /* this is a normal Java thread */
1109 thread->flags |= THREAD_FLAG_JAVA;
1111 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1114 thread->o.header.vftbl->class,
1120 /* increase total started thread count */
1122 _Jv_jvm->total_started_thread_count++;
1124 (void) vm_call_method(method, (java_objectheader *) thread);
1127 /* this is an internal thread */
1129 thread->flags |= THREAD_FLAG_INTERNAL;
1131 /* increase total started thread count */
1133 _Jv_jvm->total_started_thread_count++;
1135 /* call passed function, e.g. finalizer_thread */
1140 #if defined(ENABLE_JVMTI)
1141 /* fire thread end event */
1142 if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1146 /* Allow lock record pools to be used by other threads. They
1147 cannot be deleted so we'd better not waste them. */
1149 /* XXX We have to find a new way to free lock records */
1150 /* with the new locking algorithm. */
1151 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1153 /* remove thread from thread list and threads table, do this inside a lock */
1155 pthread_mutex_lock(&threadlistlock);
1157 thread->next->prev = thread->prev;
1158 thread->prev->next = thread->next;
1160 threads_table_remove(thread);
1162 pthread_mutex_unlock(&threadlistlock);
1164 /* reset thread id (lock on joinmutex? TWISTI) */
1166 pthread_mutex_lock(&thread->joinmutex);
1168 pthread_mutex_unlock(&thread->joinmutex);
1170 /* tell everyone that a thread has finished */
1172 pthread_cond_broadcast(&thread->joincond);
1178 /* threads_start_thread ********************************************************
1180 Start a thread in the JVM.
1183 t............the java.lang.Thread object
1184 function.....function to run in the new thread. NULL means that the
1185 "run" method of the object `t` should be called
1187 ******************************************************************************/
1189 void threads_start_thread(java_lang_Thread *t, functionptr function)
1193 pthread_attr_t attr;
1194 startupinfo startup;
1195 threadobject *thread;
1197 thread = (threadobject *) t->vmThread;
1199 /* fill startupinfo structure passed by pthread_create to
1200 * threads_startup_thread */
1202 startup.thread = thread;
1203 startup.function = function; /* maybe we don't call Thread.run()V */
1204 startup.psem = &sem;
1205 startup.psem_first = &sem_first;
1207 threads_sem_init(&sem, 0, 0);
1208 threads_sem_init(&sem_first, 0, 0);
1210 /* initialize thread attribute object */
1212 if (pthread_attr_init(&attr))
1213 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1215 /* initialize thread stacksize */
1217 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1218 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1220 /* create the thread */
1222 if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1223 vm_abort("pthread_create failed: %s", strerror(errno));
1225 /* signal that pthread_create has returned, so thread->tid is valid */
1227 threads_sem_post(&sem_first);
1229 /* wait here until the thread has entered itself into the thread list */
1231 threads_sem_wait(&sem);
1236 sem_destroy(&sem_first);
1240 /* threads_find_non_daemon_thread **********************************************
1242 Helper function used by threads_join_all_threads for finding
1243 non-daemon threads that are still running.
1245 *******************************************************************************/
1247 /* At the end of the program, we wait for all running non-daemon
1250 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1252 while (thread != mainthreadobj) {
1253 if (!thread->o.thread->daemon)
1255 thread = thread->prev;
1262 /* threads_join_all_threads ****************************************************
1264 Join all non-daemon threads.
1266 *******************************************************************************/
1268 void threads_join_all_threads(void)
1270 threadobject *thread;
1272 pthread_mutex_lock(&threadlistlock);
1274 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1276 pthread_mutex_lock(&thread->joinmutex);
1278 pthread_mutex_unlock(&threadlistlock);
1281 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1283 pthread_mutex_unlock(&thread->joinmutex);
1285 pthread_mutex_lock(&threadlistlock);
1288 pthread_mutex_unlock(&threadlistlock);
1292 /* threads_timespec_earlier ****************************************************
1294 Return true if timespec tv1 is earlier than timespec tv2.
1297 tv1..........first timespec
1298 tv2..........second timespec
1301 true, if the first timespec is earlier
1303 *******************************************************************************/
1305 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1306 const struct timespec *tv2)
1308 return (tv1->tv_sec < tv2->tv_sec)
1310 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1314 /* threads_current_time_is_earlier_than ****************************************
1316 Check if the current time is earlier than the given timespec.
1319 tv...........the timespec to compare against
1322 true, if the current time is earlier
1324 *******************************************************************************/
1326 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1328 struct timeval tvnow;
1329 struct timespec tsnow;
1331 /* get current time */
1333 if (gettimeofday(&tvnow, NULL) != 0)
1334 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1336 /* convert it to a timespec */
1338 tsnow.tv_sec = tvnow.tv_sec;
1339 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1341 /* compare current time with the given timespec */
1343 return threads_timespec_earlier(&tsnow, tv);
1347 /* threads_wait_with_timeout ***************************************************
1349 Wait until the given point in time on a monitor until either
1350 we are notified, we are interrupted, or the time is up.
1353 t............the current thread
1354 wakeupTime...absolute (latest) wakeup time
1355 If both tv_sec and tv_nsec are zero, this function
1356 waits for an unlimited amount of time.
1359 true.........if the wait has been interrupted,
1360 false........if the wait was ended by notification or timeout
1362 *******************************************************************************/
1364 static bool threads_wait_with_timeout(threadobject *t,
1365 struct timespec *wakeupTime)
1367 bool wasinterrupted;
1369 /* acquire the waitmutex */
1371 pthread_mutex_lock(&t->waitmutex);
1373 /* mark us as sleeping */
1377 /* wait on waitcond */
1379 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1381 while (!t->interrupted && !t->signaled
1382 && threads_current_time_is_earlier_than(wakeupTime))
1384 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1389 while (!t->interrupted && !t->signaled)
1390 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1393 /* check if we were interrupted */
1395 wasinterrupted = t->interrupted;
1397 /* reset all flags */
1399 t->interrupted = false;
1400 t->signaled = false;
1401 t->sleeping = false;
1403 /* release the waitmutex */
1405 pthread_mutex_unlock(&t->waitmutex);
1407 return wasinterrupted;
1411 /* threads_wait_with_timeout_relative ******************************************
1413 Wait for the given maximum amount of time on a monitor until either
1414 we are notified, we are interrupted, or the time is up.
1417 t............the current thread
1418 millis.......milliseconds to wait
1419 nanos........nanoseconds to wait
1422 true.........if the wait has been interrupted,
1423 false........if the wait was ended by notification or timeout
1425 *******************************************************************************/
1427 bool threads_wait_with_timeout_relative(threadobject *t,
1431 struct timespec wakeupTime;
1433 /* calculate the the (latest) wakeup time */
1435 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1439 return threads_wait_with_timeout(t, &wakeupTime);
1443 /* threads_calc_absolute_time **************************************************
1445 Calculate the absolute point in time a given number of ms and ns from now.
1448 millis............milliseconds from now
1449 nanos.............nanoseconds from now
1452 *tm...............receives the timespec of the absolute point in time
1454 *******************************************************************************/
1456 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1458 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1461 gettimeofday(&tv, NULL);
1462 tv.tv_sec += millis / 1000;
1464 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1465 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1466 tm->tv_nsec = nsec % 1000000000;
1475 /* threads_interrupt_thread ****************************************************
1477 Interrupt the given thread.
1479 The thread gets the "waitcond" signal and
1480 its interrupted flag is set to true.
1483 thread............the thread to interrupt
1485 *******************************************************************************/
1487 void threads_interrupt_thread(java_lang_VMThread *thread)
1489 threadobject *t = (threadobject*) thread;
1491 /* signal the thread a "waitcond" and tell it that it has been */
1494 pthread_mutex_lock(&t->waitmutex);
1496 pthread_cond_signal(&t->waitcond);
1497 t->interrupted = true;
1498 pthread_mutex_unlock(&t->waitmutex);
1502 /* threads_check_if_interrupted_and_reset **************************************
1504 Check if the current thread has been interrupted and reset the
1508 true, if the current thread had been interrupted
1510 *******************************************************************************/
1512 bool threads_check_if_interrupted_and_reset(void)
1517 t = (threadobject*) THREADOBJECT;
1519 intr = t->interrupted;
1521 t->interrupted = false;
1527 /* threads_thread_has_been_interrupted *********************************************************
1529 Check if the given thread has been interrupted
1532 t............the thread to check
1535 true, if the given thread had been interrupted
1537 *******************************************************************************/
1539 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1543 t = (threadobject*) thread;
1545 return t->interrupted;
1549 /* threads_sleep ***************************************************************
1551 Sleep the current thread for the specified amount of time.
1553 *******************************************************************************/
1555 void threads_sleep(s8 millis, s4 nanos)
1558 struct timespec wakeupTime;
1559 bool wasinterrupted;
1561 t = (threadobject *) THREADOBJECT;
1563 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1565 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1568 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1572 /* threads_yield *****************************************************************
1574 Yield to the scheduler.
1576 *******************************************************************************/
1578 void threads_yield(void)
1584 /* threads_java_lang_Thread_set_priority ***********************************************************
1586 Set the priority for the given java.lang.Thread.
1589 t............the java.lang.Thread
1590 priority.....the priority
1592 *******************************************************************************/
1594 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1596 threadobject *thread;
1598 thread = (threadobject*) t->vmThread;
1600 threads_set_thread_priority(thread->tid, priority);
1604 /* threads_dump ****************************************************************
1606 Dumps info for all threads running in the JVM. This function is
1607 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1609 *******************************************************************************/
1611 void threads_dump(void)
1614 java_lang_VMThread *vmt;
1615 java_lang_Thread *t;
1618 tobj = mainthreadobj;
1620 printf("Full thread dump CACAO "VERSION":\n");
1622 /* iterate over all started threads */
1625 /* get thread objects */
1630 /* the thread may be currently in initalization, don't print it */
1633 /* get thread name */
1635 name = javastring_toutf(t->name, false);
1638 utf_display_printable_ascii(name);
1644 #if SIZEOF_VOID_P == 8
1645 printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1647 printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1650 /* send SIGUSR1 to thread to print stacktrace */
1652 pthread_kill(tobj->tid, SIGUSR1);
1654 /* sleep this thread a bit, so the signal can reach the thread */
1656 threads_sleep(10, 0);
1660 } while (tobj && (tobj != mainthreadobj));
1664 /* threads_table_dump *********************************************************
1666 Dump the threads table for debugging purposes.
1669 file..............stream to write to
1671 ******************************************************************************/
1673 #if !defined(NDEBUG)
1674 static void threads_table_dump(FILE *file)
1680 pthread_mutex_lock(&threadlistlock);
1682 size = threads_table.size;
1684 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1686 for (i=0; i<size; ++i) {
1687 index = threads_table.table[i].nextfree;
1689 fprintf(file, "%4d: ", i);
1692 fprintf(file, "free, nextfree = %d\n", index);
1695 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1699 fprintf(file, "======== END OF THREADS TABLE ========\n");
1701 pthread_mutex_unlock(&threadlistlock);
1706 * These are local overrides for various environment variables in Emacs.
1707 * Please do not remove this and leave it at the end of the file, where
1708 * Emacs will automagically detect them.
1709 * ---------------------------------------------------------------------
1712 * indent-tabs-mode: t
1716 * vim:noexpandtab:sw=4:ts=4: