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 5805 2006-10-19 09:32:29Z 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 static methodinfo *method_thread_init;
216 static methodinfo *method_threadgroup_add;
218 /* the thread object of the current thread */
219 /* This is either a thread-local variable defined with __thread, or */
220 /* a thread-specific value stored with key threads_current_threadobject_key. */
221 #if defined(HAVE___THREAD)
222 __thread threadobject *threads_current_threadobject;
224 pthread_key_t threads_current_threadobject_key;
227 /* global threads table */
228 static threads_table_t threads_table;
230 /* global compiler mutex */
231 static pthread_mutex_rec_t compiler_mutex;
233 /* global mutex for changing the thread list */
234 static pthread_mutex_t threadlistlock;
236 /* global mutex for stop-the-world */
237 static pthread_mutex_t stopworldlock;
239 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
241 static volatile int stopworldwhere;
243 /* semaphore used for acknowleding thread suspension */
244 static sem_t suspend_ack;
245 #if defined(__MIPS__)
246 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
247 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
250 static pthread_attr_t threadattr;
252 /* mutexes used by the fake atomic instructions */
253 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
254 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
255 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
256 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
260 /******************************************************************************/
261 /* Recursive Mutex Implementation for Darwin */
262 /******************************************************************************/
264 #if defined(MUTEXSIM)
266 /* We need this for older MacOSX (10.1.x) */
268 void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
270 pthread_mutex_init(&m->mutex, NULL);
274 void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
276 pthread_mutex_destroy(&m->mutex);
279 void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
284 pthread_mutex_lock(&m->mutex);
285 m->owner = pthread_self();
290 if (m->owner != pthread_self()) {
291 pthread_mutex_lock(&m->mutex);
301 void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
304 pthread_mutex_unlock(&m->mutex);
307 #endif /* defined(MUTEXSIM) */
310 /* threads_sem_init ************************************************************
312 Initialize a semaphore. Checks against errors and interruptions.
315 sem..............the semaphore to initialize
316 shared...........true if this semaphore will be shared between processes
317 value............the initial value for the semaphore
319 *******************************************************************************/
321 void threads_sem_init(sem_t *sem, bool shared, int value)
328 r = sem_init(sem, shared, value);
331 } while (errno == EINTR);
333 vm_abort("sem_init failed: %s", strerror(errno));
337 /* threads_sem_wait ************************************************************
339 Wait for a semaphore, non-interruptible.
341 IMPORTANT: Always use this function instead of `sem_wait` directly, as
342 `sem_wait` may be interrupted by signals!
345 sem..............the semaphore to wait on
347 *******************************************************************************/
349 void threads_sem_wait(sem_t *sem)
359 } while (errno == EINTR);
361 vm_abort("sem_wait failed: %s", strerror(errno));
365 /* threads_sem_post ************************************************************
367 Increase the count of a semaphore. Checks for errors.
370 sem..............the semaphore to increase the count of
372 *******************************************************************************/
374 void threads_sem_post(sem_t *sem)
380 /* unlike sem_wait, sem_post is not interruptible */
386 vm_abort("sem_post failed: %s", strerror(errno));
390 /* threads_set_thread_priority *************************************************
392 Set the priority of the given thread.
395 tid..........thread id
396 priority.....priority to set
398 ******************************************************************************/
400 static void threads_set_thread_priority(pthread_t tid, int priority)
402 struct sched_param schedp;
405 pthread_getschedparam(tid, &policy, &schedp);
406 schedp.sched_priority = priority;
407 pthread_setschedparam(tid, policy, &schedp);
411 /* compiler_lock ***************************************************************
413 Enter the compiler lock.
415 ******************************************************************************/
417 void compiler_lock(void)
419 pthread_mutex_lock_rec(&compiler_mutex);
423 /* compiler_unlock *************************************************************
425 Release the compiler lock.
427 ******************************************************************************/
429 void compiler_unlock(void)
431 pthread_mutex_unlock_rec(&compiler_mutex);
435 /* lock_stopworld **************************************************************
437 Enter the stopworld lock, specifying why the world shall be stopped.
440 where........ STOPWORLD_FROM_GC (1) from within GC
441 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
443 ******************************************************************************/
445 void lock_stopworld(int where)
447 pthread_mutex_lock(&stopworldlock);
448 stopworldwhere = where;
452 /* unlock_stopworld ************************************************************
454 Release the stopworld lock.
456 ******************************************************************************/
458 void unlock_stopworld(void)
461 pthread_mutex_unlock(&stopworldlock);
464 #if !defined(__DARWIN__)
465 /* Caller must hold threadlistlock */
466 static int threads_cast_sendsignals(int sig, int count)
469 threadobject *tobj = mainthreadobj;
470 threadobject *self = THREADOBJECT;
476 } while (tobj != mainthreadobj);
479 assert(tobj == mainthreadobj);
483 pthread_kill(tobj->tid, sig);
485 } while (tobj != mainthreadobj);
492 static void threads_cast_darwinstop(void)
494 threadobject *tobj = mainthreadobj;
495 threadobject *self = THREADOBJECT;
500 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
501 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
502 #if defined(__I386__)
503 i386_thread_state_t thread_state;
505 ppc_thread_state_t thread_state;
507 mach_port_t thread = tobj->mach_thread;
510 r = thread_suspend(thread);
511 if (r != KERN_SUCCESS) {
512 log_text("thread_suspend failed");
516 r = thread_get_state(thread, flavor,
517 (natural_t*)&thread_state, &thread_state_count);
518 if (r != KERN_SUCCESS) {
519 log_text("thread_get_state failed");
523 thread_restartcriticalsection(&thread_state);
525 r = thread_set_state(thread, flavor,
526 (natural_t*)&thread_state, thread_state_count);
527 if (r != KERN_SUCCESS) {
528 log_text("thread_set_state failed");
533 } while (tobj != mainthreadobj);
536 static void threads_cast_darwinresume(void)
538 threadobject *tobj = mainthreadobj;
539 threadobject *self = THREADOBJECT;
544 mach_port_t thread = tobj->mach_thread;
547 r = thread_resume(thread);
548 if (r != KERN_SUCCESS) {
549 log_text("thread_resume failed");
554 } while (tobj != mainthreadobj);
559 #if defined(__MIPS__)
560 static void threads_cast_irixresume(void)
562 pthread_mutex_lock(&suspend_ack_lock);
563 pthread_cond_broadcast(&suspend_cond);
564 pthread_mutex_unlock(&suspend_ack_lock);
568 void threads_cast_stopworld(void)
571 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
572 pthread_mutex_lock(&threadlistlock);
573 #if defined(__DARWIN__)
574 threads_cast_darwinstop();
575 #elif defined(__CYGWIN__)
579 count = threads_cast_sendsignals(GC_signum1(), 0);
580 for (i=0; i<count; i++)
581 threads_sem_wait(&suspend_ack);
583 pthread_mutex_unlock(&threadlistlock);
586 void threads_cast_startworld(void)
588 pthread_mutex_lock(&threadlistlock);
589 #if defined(__DARWIN__)
590 threads_cast_darwinresume();
591 #elif defined(__MIPS__)
592 threads_cast_irixresume();
593 #elif defined(__CYGWIN__)
597 threads_cast_sendsignals(GC_signum2(), -1);
599 pthread_mutex_unlock(&threadlistlock);
603 #if !defined(__DARWIN__)
604 static void threads_sigsuspend_handler(ucontext_t *ctx)
609 /* XXX TWISTI: this is just a quick hack */
610 #if defined(ENABLE_JIT)
611 thread_restartcriticalsection(ctx);
614 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
615 (not POSIX async-safe). */
616 #if defined(__IRIX__)
617 pthread_mutex_lock(&suspend_ack_lock);
618 threads_sem_post(&suspend_ack);
619 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
620 pthread_mutex_unlock(&suspend_ack_lock);
621 #elif defined(__CYGWIN__)
625 threads_sem_post(&suspend_ack);
629 sigdelset(&sigs, sig);
634 /* This function is called from Boehm GC code. */
636 int cacao_suspendhandler(ucontext_t *ctx)
638 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
641 threads_sigsuspend_handler(ctx);
647 /* threads_set_current_threadobject ********************************************
649 Set the current thread object.
652 thread.......the thread object to set
654 *******************************************************************************/
656 static void threads_set_current_threadobject(threadobject *thread)
658 #if !defined(HAVE___THREAD)
659 pthread_setspecific(threads_current_threadobject_key, thread);
661 threads_current_threadobject = thread;
666 /* threads_get_current_threadobject ********************************************
668 Return the threadobject of the current thread.
671 the current threadobject * (an instance of java.lang.VMThread)
673 *******************************************************************************/
675 threadobject *threads_get_current_threadobject(void)
681 /* threads_preinit *************************************************************
683 Do some early initialization of stuff required.
685 *******************************************************************************/
687 void threads_preinit(void)
690 pthread_mutexattr_t mutexattr;
691 pthread_mutexattr_init(&mutexattr);
692 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
693 pthread_mutex_init(&compiler_mutex, &mutexattr);
694 pthread_mutexattr_destroy(&mutexattr);
696 pthread_mutex_init_rec(&compiler_mutex);
699 pthread_mutex_init(&threadlistlock, NULL);
700 pthread_mutex_init(&stopworldlock, NULL);
702 /* Allocate something so the garbage collector's signal handlers
704 heap_allocate(1, false, NULL);
706 mainthreadobj = NEW(threadobject);
707 mainthreadobj->tid = pthread_self();
708 mainthreadobj->index = 1;
709 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
711 #if !defined(HAVE___THREAD)
712 pthread_key_create(&threads_current_threadobject_key, NULL);
714 threads_set_current_threadobject(mainthreadobj);
716 threads_sem_init(&suspend_ack, 0, 0);
718 /* initialize the threads table */
720 threads_table_init();
722 /* initialize subsystems */
730 /* threads_init ****************************************************************
732 Initializes the threads required by the JVM: main, finalizer.
734 *******************************************************************************/
736 bool threads_init(void)
738 java_lang_String *threadname;
739 java_lang_Thread *mainthread;
740 java_lang_ThreadGroup *threadgroup;
741 threadobject *tempthread;
743 tempthread = mainthreadobj;
745 /* XXX We have to find a new way to free lock records */
746 /* with the new locking algorithm. */
747 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
749 /* This is kinda tricky, we grow the java.lang.Thread object so we
750 can keep the execution environment there. No Thread object must
751 have been created at an earlier time. */
753 class_java_lang_VMThread->instancesize = sizeof(threadobject);
755 /* get methods we need in this file */
758 class_resolveclassmethod(class_java_lang_Thread,
760 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
761 class_java_lang_Thread,
764 if (method_thread_init == NULL)
767 method_threadgroup_add =
768 class_resolveclassmethod(class_java_lang_ThreadGroup,
769 utf_new_char("addThread"),
770 utf_new_char("(Ljava/lang/Thread;)V"),
771 class_java_lang_ThreadGroup,
774 if (method_threadgroup_add == NULL)
777 /* create a VMThread */
779 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
781 if (mainthreadobj == NULL)
784 FREE(tempthread, threadobject);
786 threads_init_threadobject(&mainthreadobj->o);
788 threads_set_current_threadobject(mainthreadobj);
790 lock_init_execution_env(mainthreadobj);
792 mainthreadobj->next = mainthreadobj;
793 mainthreadobj->prev = mainthreadobj;
795 threads_table_add(mainthreadobj);
797 /* mark main thread as Java thread */
799 mainthreadobj->flags = THREAD_FLAG_JAVA;
801 #if defined(ENABLE_INTRP)
802 /* create interpreter stack */
805 MSET(intrp_main_stack, 0, u1, opt_stacksize);
806 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
810 threadname = javastring_new(utf_new_char("main"));
812 /* allocate and init ThreadGroup */
814 threadgroup = (java_lang_ThreadGroup *)
815 native_new_and_init(class_java_lang_ThreadGroup);
818 throw_exception_exit();
820 /* create a Thread */
822 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
824 if (mainthread == NULL)
825 throw_exception_exit();
827 mainthreadobj->o.thread = mainthread;
829 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
831 (void) vm_call_method(method_thread_init, (java_objectheader *) mainthread,
832 mainthreadobj, threadname, NORM_PRIORITY, false);
837 mainthread->group = threadgroup;
839 /* add mainthread to ThreadGroup */
841 (void) vm_call_method(method_threadgroup_add,
842 (java_objectheader *) threadgroup,
848 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
850 /* initialize the thread attribute object */
852 if (pthread_attr_init(&threadattr)) {
853 log_println("pthread_attr_init failed: %s", strerror(errno));
857 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
859 /* everything's ok */
865 /* threads_table_init *********************************************************
867 Initialize the global threads table.
869 ******************************************************************************/
871 static void threads_table_init(void)
876 size = THREADS_INITIAL_TABLE_SIZE;
878 threads_table.size = size;
879 threads_table.table = MNEW(threads_table_entry_t, size);
881 /* link the entries in a freelist */
883 for (i=0; i<size; ++i) {
884 threads_table.table[i].nextfree = i+1;
887 /* terminate the freelist */
889 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
893 /* threads_table_add **********************************************************
895 Add a thread to the global threads table. The index is entered in the
896 threadobject. The thinlock value for the thread is pre-computed.
899 thread............the thread to add
902 The table index for the newly added thread. This value has also been
903 entered in the threadobject.
906 The caller must hold the threadlistlock!
908 ******************************************************************************/
910 static s4 threads_table_add(threadobject *thread)
917 /* table[0] serves as the head of the freelist */
919 index = threads_table.table[0].nextfree;
921 /* if we got a free index, use it */
925 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
926 threads_table.table[index].thread = thread;
927 thread->index = index;
928 thread->thinlock = lock_pre_compute_thinlock(index);
932 /* we must grow the table */
934 oldsize = threads_table.size;
935 newsize = oldsize * 2;
937 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
939 threads_table.size = newsize;
941 /* link the new entries to a free list */
943 for (i=oldsize; i<newsize; ++i) {
944 threads_table.table[i].nextfree = i+1;
947 /* terminate the freelist */
949 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
951 /* use the first of the new entries */
958 /* threads_table_remove *******************************************************
960 Remove a thread from the global threads table.
963 thread............the thread to remove
966 The caller must hold the threadlistlock!
968 ******************************************************************************/
970 static void threads_table_remove(threadobject *thread)
974 index = thread->index;
976 /* put the index into the freelist */
978 threads_table.table[index] = threads_table.table[0];
979 threads_table.table[0].nextfree = index;
981 /* delete the index in the threadobject to discover bugs */
987 /* threads_init_threadobject **************************************************
989 Initialize implementation fields of a java.lang.VMThread.
992 t............the java.lang.VMThread
994 ******************************************************************************/
996 void threads_init_threadobject(java_lang_VMThread *t)
998 threadobject *thread = (threadobject*) t;
1000 thread->tid = pthread_self();
1004 /* TODO destroy all those things */
1005 pthread_mutex_init(&(thread->joinmutex), NULL);
1006 pthread_cond_init(&(thread->joincond), NULL);
1008 pthread_mutex_init(&(thread->waitmutex), NULL);
1009 pthread_cond_init(&(thread->waitcond), NULL);
1011 thread->interrupted = false;
1012 thread->signaled = false;
1013 thread->sleeping = false;
1017 /* threads_startup_thread ******************************************************
1019 Thread startup function called by pthread_create.
1021 Thread which have a startup.function != NULL are marked as internal
1022 threads. All other threads are threated as normal Java threads.
1024 NOTE: This function is not called directly by pthread_create. The Boehm GC
1025 inserts its own GC_start_routine in between, which then calls
1029 t............the argument passed to pthread_create, ie. a pointer to
1030 a startupinfo struct. CAUTION: When the `psem` semaphore
1031 is posted, the startupinfo struct becomes invalid! (It
1032 is allocated on the stack of threads_start_thread.)
1034 ******************************************************************************/
1036 static void *threads_startup_thread(void *t)
1038 startupinfo *startup;
1039 threadobject *thread;
1041 threadobject *tnext;
1043 functionptr function;
1045 #if defined(ENABLE_INTRP)
1046 u1 *intrp_thread_stack;
1048 /* create interpreter stack */
1051 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1052 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1055 intrp_thread_stack = NULL;
1058 /* get passed startupinfo structure and the values in there */
1061 t = NULL; /* make sure it's not used wrongly */
1063 thread = startup->thread;
1064 function = startup->function;
1065 psem = startup->psem;
1067 /* Seems like we've encountered a situation where thread->tid was not set by
1068 * pthread_create. We alleviate this problem by waiting for pthread_create
1070 threads_sem_wait(startup->psem_first);
1072 /* set the thread object */
1074 #if defined(__DARWIN__)
1075 thread->mach_thread = mach_thread_self();
1077 threads_set_current_threadobject(thread);
1079 /* insert the thread into the threadlist and the threads table */
1081 pthread_mutex_lock(&threadlistlock);
1083 thread->prev = mainthreadobj;
1084 thread->next = tnext = mainthreadobj->next;
1085 mainthreadobj->next = thread;
1086 tnext->prev = thread;
1088 threads_table_add(thread);
1090 pthread_mutex_unlock(&threadlistlock);
1092 /* init data structures of this thread */
1094 lock_init_execution_env(thread);
1096 /* tell threads_startup_thread that we registered ourselves */
1097 /* CAUTION: *startup becomes invalid with this! */
1100 threads_sem_post(psem);
1102 /* set our priority */
1104 threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1106 #if defined(ENABLE_INTRP)
1107 /* set interpreter stack */
1110 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1113 #if defined(ENABLE_JVMTI)
1114 /* fire thread start event */
1117 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1120 /* find and run the Thread.run()V method if no other function was passed */
1122 if (function == NULL) {
1123 /* this is a normal Java thread */
1125 thread->flags |= THREAD_FLAG_JAVA;
1127 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1130 thread->o.header.vftbl->class,
1136 /* increase total started thread count */
1138 _Jv_jvm->total_started_thread_count++;
1140 (void) vm_call_method(method, (java_objectheader *) thread);
1143 /* this is an internal thread */
1145 thread->flags |= THREAD_FLAG_INTERNAL;
1147 /* increase total started thread count */
1149 _Jv_jvm->total_started_thread_count++;
1151 /* call passed function, e.g. finalizer_thread */
1156 #if defined(ENABLE_JVMTI)
1157 /* fire thread end event */
1160 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1163 threads_detach_thread(thread);
1169 /* threads_start_thread ********************************************************
1171 Start a thread in the JVM.
1174 t............the java.lang.Thread object
1175 function.....function to run in the new thread. NULL means that the
1176 "run" method of the object `t` should be called
1178 ******************************************************************************/
1180 void threads_start_thread(java_lang_Thread *t, functionptr function)
1184 pthread_attr_t attr;
1185 startupinfo startup;
1186 threadobject *thread;
1188 thread = (threadobject *) t->vmThread;
1190 /* fill startupinfo structure passed by pthread_create to
1191 * threads_startup_thread */
1193 startup.thread = thread;
1194 startup.function = function; /* maybe we don't call Thread.run()V */
1195 startup.psem = &sem;
1196 startup.psem_first = &sem_first;
1198 threads_sem_init(&sem, 0, 0);
1199 threads_sem_init(&sem_first, 0, 0);
1201 /* initialize thread attribute object */
1203 if (pthread_attr_init(&attr))
1204 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1206 /* initialize thread stacksize */
1208 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1209 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1211 /* create the thread */
1213 if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1214 vm_abort("pthread_create failed: %s", strerror(errno));
1216 /* signal that pthread_create has returned, so thread->tid is valid */
1218 threads_sem_post(&sem_first);
1220 /* wait here until the thread has entered itself into the thread list */
1222 threads_sem_wait(&sem);
1227 sem_destroy(&sem_first);
1231 /* threads_attach_current_thread ***********************************************
1233 Attaches the current thread to the VM. Used in JNI.
1235 *******************************************************************************/
1237 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1239 threadobject *thread;
1240 java_lang_Thread *t;
1242 java_lang_String *s;
1243 java_lang_ThreadGroup *group;
1244 java_objectheader *o;
1246 /* create a java.lang.VMThread object */
1248 thread = (threadobject *) builtin_new(class_java_lang_VMThread);
1253 threads_init_threadobject(&thread->o);
1254 threads_set_current_threadobject(thread);
1255 lock_init_execution_env(thread);
1257 /* insert the thread into the threadlist and the threads table */
1259 pthread_mutex_lock(&threadlistlock);
1261 thread->prev = mainthreadobj;
1262 thread->next = mainthreadobj->next;
1263 mainthreadobj->next = thread;
1264 thread->next->prev = thread;
1266 threads_table_add(thread);
1268 pthread_mutex_unlock(&threadlistlock);
1270 /* mark main thread as Java thread */
1272 thread->flags = THREAD_FLAG_JAVA;
1274 #if defined(ENABLE_INTRP)
1275 /* create interpreter stack */
1278 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1279 thread->_global_sp = intrp_main_stack + opt_stacksize;
1283 /* create a java.lang.Thread object */
1285 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1290 thread->o.thread = t;
1292 if (vm_aargs != NULL) {
1293 u = utf_new_char(vm_aargs->name);
1294 group = (java_lang_ThreadGroup *) vm_aargs->group;
1298 group = mainthreadobj->o.thread->group;
1301 s = javastring_new(u);
1303 o = (java_objectheader *) t;
1305 (void) vm_call_method(method_thread_init, o, thread, s, NORM_PRIORITY,
1311 /* store the thread group in the object */
1315 o = (java_objectheader *) group;
1317 (void) vm_call_method(method_threadgroup_add, o, t);
1326 /* threads_detach_thread *******************************************************
1328 Detaches the passed thread from the VM. Used in JNI.
1330 *******************************************************************************/
1332 bool threads_detach_thread(threadobject *thread)
1334 java_lang_Thread *t;
1335 java_lang_ThreadGroup *group;
1337 java_objectheader *o;
1339 /* Allow lock record pools to be used by other threads. They
1340 cannot be deleted so we'd better not waste them. */
1342 /* XXX We have to find a new way to free lock records */
1343 /* with the new locking algorithm. */
1344 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1346 /* XXX implement uncaught exception stuff (like JamVM does) */
1348 /* remove thread from the thread group */
1350 t = thread->o.thread;
1353 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1355 if (group != NULL) {
1356 m = class_resolveclassmethod(group->header.vftbl->class,
1358 utf_java_lang_Thread__V,
1359 class_java_lang_ThreadGroup,
1365 o = (java_objectheader *) group;
1367 (void) vm_call_method(m, o, t);
1373 /* remove thread from thread list and threads table, do this
1376 pthread_mutex_lock(&threadlistlock);
1378 thread->next->prev = thread->prev;
1379 thread->prev->next = thread->next;
1381 threads_table_remove(thread);
1383 pthread_mutex_unlock(&threadlistlock);
1385 /* reset thread id (lock on joinmutex? TWISTI) */
1387 pthread_mutex_lock(&thread->joinmutex);
1389 pthread_mutex_unlock(&thread->joinmutex);
1391 /* tell everyone that a thread has finished */
1393 pthread_cond_broadcast(&thread->joincond);
1399 /* threads_find_non_daemon_thread **********************************************
1401 Helper function used by threads_join_all_threads for finding
1402 non-daemon threads that are still running.
1404 *******************************************************************************/
1406 /* At the end of the program, we wait for all running non-daemon
1409 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1411 while (thread != mainthreadobj) {
1412 if (!thread->o.thread->daemon)
1414 thread = thread->prev;
1421 /* threads_join_all_threads ****************************************************
1423 Join all non-daemon threads.
1425 *******************************************************************************/
1427 void threads_join_all_threads(void)
1429 threadobject *thread;
1431 pthread_mutex_lock(&threadlistlock);
1433 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1435 pthread_mutex_lock(&thread->joinmutex);
1437 pthread_mutex_unlock(&threadlistlock);
1440 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1442 pthread_mutex_unlock(&thread->joinmutex);
1444 pthread_mutex_lock(&threadlistlock);
1447 pthread_mutex_unlock(&threadlistlock);
1451 /* threads_timespec_earlier ****************************************************
1453 Return true if timespec tv1 is earlier than timespec tv2.
1456 tv1..........first timespec
1457 tv2..........second timespec
1460 true, if the first timespec is earlier
1462 *******************************************************************************/
1464 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1465 const struct timespec *tv2)
1467 return (tv1->tv_sec < tv2->tv_sec)
1469 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1473 /* threads_current_time_is_earlier_than ****************************************
1475 Check if the current time is earlier than the given timespec.
1478 tv...........the timespec to compare against
1481 true, if the current time is earlier
1483 *******************************************************************************/
1485 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1487 struct timeval tvnow;
1488 struct timespec tsnow;
1490 /* get current time */
1492 if (gettimeofday(&tvnow, NULL) != 0)
1493 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1495 /* convert it to a timespec */
1497 tsnow.tv_sec = tvnow.tv_sec;
1498 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1500 /* compare current time with the given timespec */
1502 return threads_timespec_earlier(&tsnow, tv);
1506 /* threads_wait_with_timeout ***************************************************
1508 Wait until the given point in time on a monitor until either
1509 we are notified, we are interrupted, or the time is up.
1512 t............the current thread
1513 wakeupTime...absolute (latest) wakeup time
1514 If both tv_sec and tv_nsec are zero, this function
1515 waits for an unlimited amount of time.
1518 true.........if the wait has been interrupted,
1519 false........if the wait was ended by notification or timeout
1521 *******************************************************************************/
1523 static bool threads_wait_with_timeout(threadobject *t,
1524 struct timespec *wakeupTime)
1526 bool wasinterrupted;
1528 /* acquire the waitmutex */
1530 pthread_mutex_lock(&t->waitmutex);
1532 /* mark us as sleeping */
1536 /* wait on waitcond */
1538 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1540 while (!t->interrupted && !t->signaled
1541 && threads_current_time_is_earlier_than(wakeupTime))
1543 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1548 while (!t->interrupted && !t->signaled)
1549 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1552 /* check if we were interrupted */
1554 wasinterrupted = t->interrupted;
1556 /* reset all flags */
1558 t->interrupted = false;
1559 t->signaled = false;
1560 t->sleeping = false;
1562 /* release the waitmutex */
1564 pthread_mutex_unlock(&t->waitmutex);
1566 return wasinterrupted;
1570 /* threads_wait_with_timeout_relative ******************************************
1572 Wait for the given maximum amount of time on a monitor until either
1573 we are notified, we are interrupted, or the time is up.
1576 t............the current thread
1577 millis.......milliseconds to wait
1578 nanos........nanoseconds to wait
1581 true.........if the wait has been interrupted,
1582 false........if the wait was ended by notification or timeout
1584 *******************************************************************************/
1586 bool threads_wait_with_timeout_relative(threadobject *t,
1590 struct timespec wakeupTime;
1592 /* calculate the the (latest) wakeup time */
1594 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1598 return threads_wait_with_timeout(t, &wakeupTime);
1602 /* threads_calc_absolute_time **************************************************
1604 Calculate the absolute point in time a given number of ms and ns from now.
1607 millis............milliseconds from now
1608 nanos.............nanoseconds from now
1611 *tm...............receives the timespec of the absolute point in time
1613 *******************************************************************************/
1615 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1617 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1620 gettimeofday(&tv, NULL);
1621 tv.tv_sec += millis / 1000;
1623 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1624 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1625 tm->tv_nsec = nsec % 1000000000;
1634 /* threads_interrupt_thread ****************************************************
1636 Interrupt the given thread.
1638 The thread gets the "waitcond" signal and
1639 its interrupted flag is set to true.
1642 thread............the thread to interrupt
1644 *******************************************************************************/
1646 void threads_interrupt_thread(java_lang_VMThread *thread)
1648 threadobject *t = (threadobject*) thread;
1650 /* signal the thread a "waitcond" and tell it that it has been */
1653 pthread_mutex_lock(&t->waitmutex);
1655 pthread_cond_signal(&t->waitcond);
1656 t->interrupted = true;
1657 pthread_mutex_unlock(&t->waitmutex);
1661 /* threads_check_if_interrupted_and_reset **************************************
1663 Check if the current thread has been interrupted and reset the
1667 true, if the current thread had been interrupted
1669 *******************************************************************************/
1671 bool threads_check_if_interrupted_and_reset(void)
1676 t = (threadobject*) THREADOBJECT;
1678 intr = t->interrupted;
1680 t->interrupted = false;
1686 /* threads_thread_has_been_interrupted *********************************************************
1688 Check if the given thread has been interrupted
1691 t............the thread to check
1694 true, if the given thread had been interrupted
1696 *******************************************************************************/
1698 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1702 t = (threadobject*) thread;
1704 return t->interrupted;
1708 /* threads_sleep ***************************************************************
1710 Sleep the current thread for the specified amount of time.
1712 *******************************************************************************/
1714 void threads_sleep(s8 millis, s4 nanos)
1717 struct timespec wakeupTime;
1718 bool wasinterrupted;
1720 t = (threadobject *) THREADOBJECT;
1722 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1724 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1727 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1731 /* threads_yield *****************************************************************
1733 Yield to the scheduler.
1735 *******************************************************************************/
1737 void threads_yield(void)
1743 /* threads_java_lang_Thread_set_priority ***********************************************************
1745 Set the priority for the given java.lang.Thread.
1748 t............the java.lang.Thread
1749 priority.....the priority
1751 *******************************************************************************/
1753 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1755 threadobject *thread;
1757 thread = (threadobject*) t->vmThread;
1759 threads_set_thread_priority(thread->tid, priority);
1763 /* threads_dump ****************************************************************
1765 Dumps info for all threads running in the JVM. This function is
1766 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1768 *******************************************************************************/
1770 void threads_dump(void)
1772 threadobject *thread;
1773 java_lang_VMThread *vmt;
1774 java_lang_Thread *t;
1777 thread = mainthreadobj;
1779 /* XXX we should stop the world here */
1781 printf("Full thread dump CACAO "VERSION":\n");
1783 /* iterate over all started threads */
1786 /* get thread objects */
1791 /* the thread may be currently in initalization, don't print it */
1794 /* get thread name */
1796 name = javastring_toutf(t->name, false);
1799 utf_display_printable_ascii(name);
1805 #if SIZEOF_VOID_P == 8
1806 printf("prio=%d tid=0x%016lx\n", t->priority, thread->tid);
1808 printf("prio=%d tid=0x%08lx\n", t->priority, thread->tid);
1811 /* send SIGUSR1 to thread to print stacktrace */
1813 /* pthread_kill(thread->tid, SIGUSR1); */
1814 stacktrace_dump_trace(thread);
1816 /* sleep this thread a bit, so the signal can reach the thread */
1818 threads_sleep(10, 0);
1821 thread = thread->next;
1822 } while ((thread != NULL) && (thread != mainthreadobj));
1826 /* threads_table_dump *********************************************************
1828 Dump the threads table for debugging purposes.
1831 file..............stream to write to
1833 ******************************************************************************/
1835 #if !defined(NDEBUG)
1836 static void threads_table_dump(FILE *file)
1842 pthread_mutex_lock(&threadlistlock);
1844 size = threads_table.size;
1846 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1848 for (i=0; i<size; ++i) {
1849 index = threads_table.table[i].nextfree;
1851 fprintf(file, "%4d: ", i);
1854 fprintf(file, "free, nextfree = %d\n", index);
1857 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1861 fprintf(file, "======== END OF THREADS TABLE ========\n");
1863 pthread_mutex_unlock(&threadlistlock);
1868 * These are local overrides for various environment variables in Emacs.
1869 * Please do not remove this and leave it at the end of the file, where
1870 * Emacs will automagically detect them.
1871 * ---------------------------------------------------------------------
1874 * indent-tabs-mode: t
1878 * vim:noexpandtab:sw=4:ts=4: