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 4916 2006-05-14 22:41:34Z edwin $
39 /* XXX cleanup these includes */
44 #include <sys/types.h>
52 #include <semaphore.h>
58 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
59 #include "machine-instr.h"
61 #include "threads/native/generic-primitives.h"
65 #include "mm/memory.h"
66 #include "native/native.h"
67 #include "native/include/java_lang_Object.h"
68 #include "native/include/java_lang_Throwable.h"
69 #include "native/include/java_lang_Thread.h"
70 #include "native/include/java_lang_ThreadGroup.h"
71 #include "native/include/java_lang_VMThread.h"
72 #include "threads/native/threads.h"
73 #include "toolbox/avl.h"
74 #include "toolbox/logging.h"
75 #include "vm/builtin.h"
76 #include "vm/exceptions.h"
77 #include "vm/global.h"
78 #include "vm/loader.h"
79 #include "vm/options.h"
80 #include "vm/stringlocal.h"
82 #include "vm/jit/asmpart.h"
84 #if !defined(__DARWIN__)
85 #if defined(__LINUX__)
86 #define GC_LINUX_THREADS
87 #elif defined(__MIPS__)
88 #define GC_IRIX_THREADS
90 #include "boehm-gc/include/gc.h"
94 /* internally used constants **************************************************/
96 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
97 #define STOPWORLD_FROM_GC 1
98 #define STOPWORLD_FROM_CLASS_NUMBERING 2
100 #define THREADS_INITIAL_TABLE_SIZE 8
103 /* startupinfo *****************************************************************
105 Struct used to pass info from threads_start_thread to
106 threads_startup_thread.
108 ******************************************************************************/
111 threadobject *thread; /* threadobject for this thread */
112 functionptr function; /* function to run in the new thread */
113 sem_t *psem; /* signals when thread has been entered */
114 /* in the thread list */
115 sem_t *psem_first; /* signals when pthread_create has returned */
119 /* prototypes *****************************************************************/
121 static void threads_table_init(void);
122 static s4 threads_table_add(threadobject *thread);
123 static void threads_table_remove(threadobject *thread);
124 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
127 static void threads_table_dump(FILE *file);
130 /******************************************************************************/
131 /* GLOBAL VARIABLES */
132 /******************************************************************************/
134 /* the main thread */
135 threadobject *mainthreadobj;
137 /* the thread object of the current thread */
138 /* This is either a thread-local variable defined with __thread, or */
139 /* a thread-specific value stored with key threads_current_threadobject_key. */
140 #if defined(HAVE___THREAD)
141 __thread threadobject *threads_current_threadobject;
143 pthread_key_t threads_current_threadobject_key;
146 /* global threads table */
147 static threads_table_t threads_table;
149 /* global compiler mutex */
150 static pthread_mutex_rec_t compiler_mutex;
152 /* global mutex for changing the thread list */
153 static pthread_mutex_t threadlistlock;
155 /* global mutex for stop-the-world */
156 static pthread_mutex_t stopworldlock;
158 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
160 static volatile int stopworldwhere;
162 /* semaphore used for acknowleding thread suspension */
163 static sem_t suspend_ack;
164 #if defined(__MIPS__)
165 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
166 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
169 static pthread_attr_t threadattr;
171 /* mutexes used by the fake atomic instructions */
172 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
173 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
174 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
175 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
179 /******************************************************************************/
180 /* Recursive Mutex Implementation for Darwin */
181 /******************************************************************************/
183 #if defined(MUTEXSIM)
185 /* We need this for older MacOSX (10.1.x) */
187 void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
189 pthread_mutex_init(&m->mutex, NULL);
193 void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
195 pthread_mutex_destroy(&m->mutex);
198 void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
203 pthread_mutex_lock(&m->mutex);
204 m->owner = pthread_self();
209 if (m->owner != pthread_self()) {
210 pthread_mutex_lock(&m->mutex);
220 void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
223 pthread_mutex_unlock(&m->mutex);
226 #endif /* defined(MUTEXSIM) */
229 /* threads_sem_init ************************************************************
231 Initialize a semaphore. Checks against errors and interruptions.
234 sem..............the semaphore to initialize
235 shared...........true if this semaphore will be shared between processes
236 value............the initial value for the semaphore
238 *******************************************************************************/
240 void threads_sem_init(sem_t *sem, bool shared, int value)
247 r = sem_init(sem, shared, value);
250 } while (errno == EINTR);
252 fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
253 errno, strerror(errno));
258 /* threads_sem_wait ************************************************************
260 Wait for a semaphore, non-interruptible.
262 IMPORTANT: Always use this function instead of `sem_wait` directly, as
263 `sem_wait` may be interrupted by signals!
266 sem..............the semaphore to wait on
268 *******************************************************************************/
270 void threads_sem_wait(sem_t *sem)
280 } while (errno == EINTR);
282 fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
283 errno, strerror(errno));
288 /* threads_sem_post ************************************************************
290 Increase the count of a semaphore. Checks for errors.
293 sem..............the semaphore to increase the count of
295 *******************************************************************************/
297 void threads_sem_post(sem_t *sem)
303 /* unlike sem_wait, sem_post is not interruptible */
309 fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
310 errno, strerror(errno));
315 /* threads_set_thread_priority *************************************************
317 Set the priority of the given thread.
320 tid..........thread id
321 priority.....priority to set
323 ******************************************************************************/
325 static void threads_set_thread_priority(pthread_t tid, int priority)
327 struct sched_param schedp;
330 pthread_getschedparam(tid, &policy, &schedp);
331 schedp.sched_priority = priority;
332 pthread_setschedparam(tid, policy, &schedp);
336 /* compiler_lock ***************************************************************
338 Enter the compiler lock.
340 ******************************************************************************/
342 void compiler_lock(void)
344 pthread_mutex_lock_rec(&compiler_mutex);
348 /* compiler_unlock *************************************************************
350 Release the compiler lock.
352 ******************************************************************************/
354 void compiler_unlock(void)
356 pthread_mutex_unlock_rec(&compiler_mutex);
360 /* lock_stopworld **************************************************************
362 Enter the stopworld lock, specifying why the world shall be stopped.
365 where........ STOPWORLD_FROM_GC (1) from within GC
366 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
368 ******************************************************************************/
370 void lock_stopworld(int where)
372 pthread_mutex_lock(&stopworldlock);
373 stopworldwhere = where;
377 /* unlock_stopworld ************************************************************
379 Release the stopworld lock.
381 ******************************************************************************/
383 void unlock_stopworld(void)
386 pthread_mutex_unlock(&stopworldlock);
389 #if !defined(__DARWIN__)
390 /* Caller must hold threadlistlock */
391 static int threads_cast_sendsignals(int sig, int count)
394 threadobject *tobj = mainthreadobj;
395 threadobject *self = THREADOBJECT;
401 } while (tobj != mainthreadobj);
404 assert(tobj == mainthreadobj);
408 pthread_kill(tobj->tid, sig);
410 } while (tobj != mainthreadobj);
417 static void threads_cast_darwinstop(void)
419 threadobject *tobj = mainthreadobj;
420 threadobject *self = THREADOBJECT;
425 thread_state_flavor_t flavor = PPC_THREAD_STATE;
426 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
427 ppc_thread_state_t thread_state;
428 mach_port_t thread = tobj->mach_thread;
431 r = thread_suspend(thread);
432 if (r != KERN_SUCCESS) {
433 log_text("thread_suspend failed");
437 r = thread_get_state(thread, flavor,
438 (natural_t*)&thread_state, &thread_state_count);
439 if (r != KERN_SUCCESS) {
440 log_text("thread_get_state failed");
444 thread_restartcriticalsection(&thread_state);
446 r = thread_set_state(thread, flavor,
447 (natural_t*)&thread_state, thread_state_count);
448 if (r != KERN_SUCCESS) {
449 log_text("thread_set_state failed");
454 } while (tobj != mainthreadobj);
457 static void threads_cast_darwinresume(void)
459 threadobject *tobj = mainthreadobj;
460 threadobject *self = THREADOBJECT;
465 mach_port_t thread = tobj->mach_thread;
468 r = thread_resume(thread);
469 if (r != KERN_SUCCESS) {
470 log_text("thread_resume failed");
475 } while (tobj != mainthreadobj);
480 #if defined(__MIPS__)
481 static void threads_cast_irixresume(void)
483 pthread_mutex_lock(&suspend_ack_lock);
484 pthread_cond_broadcast(&suspend_cond);
485 pthread_mutex_unlock(&suspend_ack_lock);
489 void threads_cast_stopworld(void)
492 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
493 pthread_mutex_lock(&threadlistlock);
494 #if defined(__DARWIN__)
495 threads_cast_darwinstop();
497 count = threads_cast_sendsignals(GC_signum1(), 0);
498 for (i=0; i<count; i++)
499 threads_sem_wait(&suspend_ack);
501 pthread_mutex_unlock(&threadlistlock);
504 void threads_cast_startworld(void)
506 pthread_mutex_lock(&threadlistlock);
507 #if defined(__DARWIN__)
508 threads_cast_darwinresume();
509 #elif defined(__MIPS__)
510 threads_cast_irixresume();
512 threads_cast_sendsignals(GC_signum2(), -1);
514 pthread_mutex_unlock(&threadlistlock);
518 #if !defined(__DARWIN__)
519 static void threads_sigsuspend_handler(ucontext_t *ctx)
524 /* XXX TWISTI: this is just a quick hack */
525 #if defined(ENABLE_JIT)
526 thread_restartcriticalsection(ctx);
529 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
530 (not POSIX async-safe). */
531 #if defined(__IRIX__)
532 pthread_mutex_lock(&suspend_ack_lock);
533 threads_sem_post(&suspend_ack);
534 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
535 pthread_mutex_unlock(&suspend_ack_lock);
537 threads_sem_post(&suspend_ack);
541 sigdelset(&sigs, sig);
546 /* This function is called from Boehm GC code. */
548 int cacao_suspendhandler(ucontext_t *ctx)
550 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
553 threads_sigsuspend_handler(ctx);
559 /* threads_set_current_threadobject ********************************************
561 Set the current thread object.
564 thread.......the thread object to set
566 *******************************************************************************/
568 #if !defined(ENABLE_JVMTI)
569 static void threads_set_current_threadobject(threadobject *thread)
571 void threads_set_current_threadobject(threadobject *thread)
574 #if !defined(HAVE___THREAD)
575 pthread_setspecific(threads_current_threadobject_key, thread);
577 threads_current_threadobject = thread;
582 /* threads_get_current_threadobject ********************************************
584 Return the threadobject of the current thread.
587 the current threadobject * (an instance of java.lang.VMThread)
589 *******************************************************************************/
591 threadobject *threads_get_current_threadobject(void)
597 /* threads_preinit *************************************************************
599 Do some early initialization of stuff required.
601 *******************************************************************************/
603 void threads_preinit(void)
606 pthread_mutexattr_t mutexattr;
607 pthread_mutexattr_init(&mutexattr);
608 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
609 pthread_mutex_init(&compiler_mutex, &mutexattr);
610 pthread_mutexattr_destroy(&mutexattr);
612 pthread_mutex_init_rec(&compiler_mutex);
615 pthread_mutex_init(&threadlistlock, NULL);
616 pthread_mutex_init(&stopworldlock, NULL);
618 /* Allocate something so the garbage collector's signal handlers
620 heap_allocate(1, false, NULL);
622 mainthreadobj = NEW(threadobject);
623 mainthreadobj->tid = pthread_self();
624 mainthreadobj->index = 1;
625 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
627 #if !defined(HAVE___THREAD)
628 pthread_key_create(&threads_current_threadobject_key, NULL);
630 threads_set_current_threadobject(mainthreadobj);
632 threads_sem_init(&suspend_ack, 0, 0);
634 /* initialize the threads table */
636 threads_table_init();
638 /* initialize subsystems */
646 /* threads_init ****************************************************************
648 Initializes the threads required by the JVM: main, finalizer.
650 *******************************************************************************/
652 bool threads_init(u1 *stackbottom)
654 java_lang_String *threadname;
655 java_lang_Thread *mainthread;
656 java_lang_ThreadGroup *threadgroup;
657 threadobject *tempthread;
660 tempthread = mainthreadobj;
662 /* XXX We have to find a new way to free lock records */
663 /* with the new locking algorithm. */
664 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
666 /* This is kinda tricky, we grow the java.lang.Thread object so we
667 can keep the execution environment there. No Thread object must
668 have been created at an earlier time. */
670 class_java_lang_VMThread->instancesize = sizeof(threadobject);
672 /* create a VMThread */
674 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
679 FREE(tempthread, threadobject);
681 threads_init_threadobject(&mainthreadobj->o);
683 threads_set_current_threadobject(mainthreadobj);
685 lock_init_execution_env(mainthreadobj);
687 mainthreadobj->next = mainthreadobj;
688 mainthreadobj->prev = mainthreadobj;
690 threads_table_add(mainthreadobj);
692 #if defined(ENABLE_INTRP)
693 /* create interpreter stack */
696 MSET(intrp_main_stack, 0, u1, opt_stacksize);
697 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
701 threadname = javastring_new(utf_new_char("main"));
703 /* allocate and init ThreadGroup */
705 threadgroup = (java_lang_ThreadGroup *)
706 native_new_and_init(class_java_lang_ThreadGroup);
709 throw_exception_exit();
711 /* create a Thread */
713 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
716 throw_exception_exit();
718 mainthreadobj->o.thread = mainthread;
720 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
722 method = class_resolveclassmethod(class_java_lang_Thread,
724 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
725 class_java_lang_Thread,
731 (void) vm_call_method(method, (java_objectheader *) mainthread,
732 mainthreadobj, threadname, 5, false);
737 mainthread->group = threadgroup;
739 /* add mainthread to ThreadGroup */
741 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
742 utf_new_char("addThread"),
743 utf_new_char("(Ljava/lang/Thread;)V"),
744 class_java_lang_ThreadGroup,
750 (void) vm_call_method(method, (java_objectheader *) threadgroup,
756 threads_set_thread_priority(pthread_self(), 5);
758 pthread_attr_init(&threadattr);
759 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
761 /* everything's ok */
767 /* threads_table_init *********************************************************
769 Initialize the global threads table.
771 ******************************************************************************/
773 static void threads_table_init(void)
778 size = THREADS_INITIAL_TABLE_SIZE;
780 threads_table.size = size;
781 threads_table.table = MNEW(threads_table_entry_t, size);
783 /* link the entries in a freelist */
785 for (i=0; i<size; ++i) {
786 threads_table.table[i].nextfree = i+1;
789 /* terminate the freelist */
791 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
795 /* threads_table_add **********************************************************
797 Add a thread to the global threads table. The index is entered in the
798 threadobject. The thinlock value for the thread is pre-computed.
801 thread............the thread to add
804 The table index for the newly added thread. This value has also been
805 entered in the threadobject.
808 The caller must hold the threadlistlock!
810 ******************************************************************************/
812 static s4 threads_table_add(threadobject *thread)
819 /* table[0] serves as the head of the freelist */
821 index = threads_table.table[0].nextfree;
823 /* if we got a free index, use it */
827 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
828 threads_table.table[index].thread = thread;
829 thread->index = index;
830 thread->thinlock = lock_pre_compute_thinlock(index);
834 /* we must grow the table */
836 oldsize = threads_table.size;
837 newsize = oldsize * 2;
839 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
841 threads_table.size = newsize;
843 /* link the new entries to a free list */
845 for (i=oldsize; i<newsize; ++i) {
846 threads_table.table[i].nextfree = i+1;
849 /* terminate the freelist */
851 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
853 /* use the first of the new entries */
860 /* threads_table_remove *******************************************************
862 Remove a thread from the global threads table.
865 thread............the thread to remove
868 The caller must hold the threadlistlock!
870 ******************************************************************************/
872 static void threads_table_remove(threadobject *thread)
876 index = thread->index;
878 /* put the index into the freelist */
880 threads_table.table[index] = threads_table.table[0];
881 threads_table.table[0].nextfree = index;
883 /* delete the index in the threadobject to discover bugs */
889 /* threads_init_threadobject **************************************************
891 Initialize implementation fields of a java.lang.VMThread.
894 t............the java.lang.VMThread
896 ******************************************************************************/
898 void threads_init_threadobject(java_lang_VMThread *t)
900 threadobject *thread = (threadobject*) t;
902 thread->tid = pthread_self();
906 /* TODO destroy all those things */
907 pthread_mutex_init(&(thread->joinmutex), NULL);
908 pthread_cond_init(&(thread->joincond), NULL);
910 pthread_mutex_init(&(thread->waitmutex), NULL);
911 pthread_cond_init(&(thread->waitcond), NULL);
913 thread->interrupted = false;
914 thread->signaled = false;
915 thread->sleeping = false;
919 /* threads_startup_thread ******************************************************
921 Thread startup function called by pthread_create.
923 NOTE: This function is not called directly by pthread_create. The Boehm GC
924 inserts its own GC_start_routine in between, which then calls
928 t............the argument passed to pthread_create, ie. a pointer to
929 a startupinfo struct. CAUTION: When the `psem` semaphore
930 is posted, the startupinfo struct becomes invalid! (It
931 is allocated on the stack of threads_start_thread.)
933 ******************************************************************************/
935 static void *threads_startup_thread(void *t)
937 startupinfo *startup;
938 threadobject *thread;
942 functionptr function;
944 #if defined(ENABLE_INTRP)
945 u1 *intrp_thread_stack;
947 /* create interpreter stack */
950 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
951 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
953 intrp_thread_stack = NULL;
957 /* get passed startupinfo structure and the values in there */
960 t = NULL; /* make sure it's not used wrongly */
962 thread = startup->thread;
963 function = startup->function;
964 psem = startup->psem;
966 /* Seems like we've encountered a situation where thread->tid was not set by
967 * pthread_create. We alleviate this problem by waiting for pthread_create
969 threads_sem_wait(startup->psem_first);
971 /* set the thread object */
973 #if defined(__DARWIN__)
974 thread->mach_thread = mach_thread_self();
976 threads_set_current_threadobject(thread);
978 /* insert the thread into the threadlist and the threads table */
980 pthread_mutex_lock(&threadlistlock);
982 thread->prev = mainthreadobj;
983 thread->next = tnext = mainthreadobj->next;
984 mainthreadobj->next = thread;
985 tnext->prev = thread;
987 threads_table_add(thread);
989 pthread_mutex_unlock(&threadlistlock);
991 /* init data structures of this thread */
993 lock_init_execution_env(thread);
995 /* tell threads_startup_thread that we registered ourselves */
996 /* CAUTION: *startup becomes invalid with this! */
999 threads_sem_post(psem);
1001 /* set our priority */
1003 threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1005 #if defined(ENABLE_INTRP)
1006 /* set interpreter stack */
1009 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1012 /* find and run the Thread.run()V method if no other function was passed */
1014 if (function == NULL) {
1015 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1018 thread->o.header.vftbl->class,
1024 (void) vm_call_method(method, (java_objectheader *) thread);
1028 /* call passed function, e.g. finalizer_thread */
1033 /* Allow lock record pools to be used by other threads. They
1034 cannot be deleted so we'd better not waste them. */
1036 /* XXX We have to find a new way to free lock records */
1037 /* with the new locking algorithm. */
1038 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1040 /* remove thread from thread list and threads table, do this inside a lock */
1042 pthread_mutex_lock(&threadlistlock);
1044 thread->next->prev = thread->prev;
1045 thread->prev->next = thread->next;
1047 threads_table_remove(thread);
1049 pthread_mutex_unlock(&threadlistlock);
1051 /* reset thread id (lock on joinmutex? TWISTI) */
1053 pthread_mutex_lock(&thread->joinmutex);
1055 pthread_mutex_unlock(&thread->joinmutex);
1057 /* tell everyone that a thread has finished */
1059 pthread_cond_broadcast(&thread->joincond);
1065 /* threads_start_thread ********************************************************
1067 Start a thread in the JVM.
1070 t............the java.lang.Thread object
1071 function.....function to run in the new thread. NULL means that the
1072 "run" method of the object `t` should be called
1074 ******************************************************************************/
1076 void threads_start_thread(java_lang_Thread *t, functionptr function)
1080 startupinfo startup;
1081 threadobject *thread;
1083 thread = (threadobject *) t->vmThread;
1085 /* fill startupinfo structure passed by pthread_create to
1086 * threads_startup_thread */
1088 startup.thread = thread;
1089 startup.function = function; /* maybe we don't call Thread.run()V */
1090 startup.psem = &sem;
1091 startup.psem_first = &sem_first;
1093 threads_sem_init(&sem, 0, 0);
1094 threads_sem_init(&sem_first, 0, 0);
1096 /* create the thread */
1098 if (pthread_create(&thread->tid, &threadattr, threads_startup_thread,
1100 log_text("pthread_create failed");
1104 /* signal that pthread_create has returned, so thread->tid is valid */
1106 threads_sem_post(&sem_first);
1108 /* wait here until the thread has entered itself into the thread list */
1110 threads_sem_wait(&sem);
1115 sem_destroy(&sem_first);
1119 /* threads_find_non_daemon_thread **********************************************
1121 Helper function used by threads_join_all_threads for finding non-daemon threads
1122 that are still running.
1124 *******************************************************************************/
1126 /* At the end of the program, we wait for all running non-daemon threads to die
1129 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1131 while (thread != mainthreadobj) {
1132 if (!thread->o.thread->daemon)
1134 thread = thread->prev;
1141 /* threads_join_all_threads ****************************************************
1143 Join all non-daemon threads.
1145 *******************************************************************************/
1147 void threads_join_all_threads(void)
1149 threadobject *thread;
1151 pthread_mutex_lock(&threadlistlock);
1153 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1155 pthread_mutex_lock(&thread->joinmutex);
1157 pthread_mutex_unlock(&threadlistlock);
1160 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1162 pthread_mutex_unlock(&thread->joinmutex);
1164 pthread_mutex_lock(&threadlistlock);
1167 pthread_mutex_unlock(&threadlistlock);
1171 /* threads_timespec_earlier ****************************************************
1173 Return true if timespec tv1 is earlier than timespec tv2.
1176 tv1..........first timespec
1177 tv2..........second timespec
1180 true, if the first timespec is earlier
1182 *******************************************************************************/
1184 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1185 const struct timespec *tv2)
1187 return (tv1->tv_sec < tv2->tv_sec)
1189 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1193 /* threads_current_time_is_earlier_than ****************************************
1195 Check if the current time is earlier than the given timespec.
1198 tv...........the timespec to compare against
1201 true, if the current time is earlier
1203 *******************************************************************************/
1205 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1207 struct timeval tvnow;
1208 struct timespec tsnow;
1210 /* get current time */
1212 if (gettimeofday(&tvnow, NULL) != 0) {
1213 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1214 errno, strerror(errno));
1218 /* convert it to a timespec */
1220 tsnow.tv_sec = tvnow.tv_sec;
1221 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1223 /* compare current time with the given timespec */
1225 return threads_timespec_earlier(&tsnow, tv);
1229 /* threads_wait_with_timeout ***************************************************
1231 Wait until the given point in time on a monitor until either
1232 we are notified, we are interrupted, or the time is up.
1235 t............the current thread
1236 wakeupTime...absolute (latest) wakeup time
1237 If both tv_sec and tv_nsec are zero, this function
1238 waits for an unlimited amount of time.
1241 true.........if the wait has been interrupted,
1242 false........if the wait was ended by notification or timeout
1244 *******************************************************************************/
1246 static bool threads_wait_with_timeout(threadobject *t,
1247 struct timespec *wakeupTime)
1249 bool wasinterrupted;
1251 /* acquire the waitmutex */
1253 pthread_mutex_lock(&t->waitmutex);
1255 /* mark us as sleeping */
1259 /* wait on waitcond */
1261 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1263 while (!t->interrupted && !t->signaled
1264 && threads_current_time_is_earlier_than(wakeupTime))
1266 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1271 while (!t->interrupted && !t->signaled)
1272 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1275 /* check if we were interrupted */
1277 wasinterrupted = t->interrupted;
1279 /* reset all flags */
1281 t->interrupted = false;
1282 t->signaled = false;
1283 t->sleeping = false;
1285 /* release the waitmutex */
1287 pthread_mutex_unlock(&t->waitmutex);
1289 return wasinterrupted;
1293 /* threads_wait_with_timeout_relative ******************************************
1295 Wait for the given maximum amount of time on a monitor until either
1296 we are notified, we are interrupted, or the time is up.
1299 t............the current thread
1300 millis.......milliseconds to wait
1301 nanos........nanoseconds to wait
1304 true.........if the wait has been interrupted,
1305 false........if the wait was ended by notification or timeout
1307 *******************************************************************************/
1309 bool threads_wait_with_timeout_relative(threadobject *t,
1313 struct timespec wakeupTime;
1315 /* calculate the the (latest) wakeup time */
1317 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1321 return threads_wait_with_timeout(t, &wakeupTime);
1325 /* threads_calc_absolute_time **************************************************
1327 Calculate the absolute point in time a given number of ms and ns from now.
1330 millis............milliseconds from now
1331 nanos.............nanoseconds from now
1334 *tm...............receives the timespec of the absolute point in time
1336 *******************************************************************************/
1338 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1340 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1343 gettimeofday(&tv, NULL);
1344 tv.tv_sec += millis / 1000;
1346 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1347 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1348 tm->tv_nsec = nsec % 1000000000;
1357 /* threads_interrupt_thread ****************************************************
1359 Interrupt the given thread.
1361 The thread gets the "waitcond" signal and
1362 its interrupted flag is set to true.
1365 thread............the thread to interrupt
1367 *******************************************************************************/
1369 void threads_interrupt_thread(java_lang_VMThread *thread)
1371 threadobject *t = (threadobject*) thread;
1373 /* signal the thread a "waitcond" and tell it that it has been */
1376 pthread_mutex_lock(&t->waitmutex);
1378 pthread_cond_signal(&t->waitcond);
1379 t->interrupted = true;
1380 pthread_mutex_unlock(&t->waitmutex);
1384 /* threads_check_if_interrupted_and_reset **************************************
1386 Check if the current thread has been interrupted and reset the
1390 true, if the current thread had been interrupted
1392 *******************************************************************************/
1394 bool threads_check_if_interrupted_and_reset(void)
1399 t = (threadobject*) THREADOBJECT;
1401 intr = t->interrupted;
1403 t->interrupted = false;
1409 /* threads_thread_has_been_interrupted *********************************************************
1411 Check if the given thread has been interrupted
1414 t............the thread to check
1417 true, if the given thread had been interrupted
1419 *******************************************************************************/
1421 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1425 t = (threadobject*) thread;
1427 return t->interrupted;
1431 /* threads_sleep ***************************************************************
1433 Sleep the current thread for the specified amount of time.
1435 *******************************************************************************/
1437 void threads_sleep(s8 millis, s4 nanos)
1440 struct timespec wakeupTime;
1441 bool wasinterrupted;
1443 t = (threadobject *) THREADOBJECT;
1445 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1447 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1450 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1454 /* threads_yield *****************************************************************
1456 Yield to the scheduler.
1458 *******************************************************************************/
1460 void threads_yield(void)
1466 /* threads_java_lang_Thread_set_priority ***********************************************************
1468 Set the priority for the given java.lang.Thread.
1471 t............the java.lang.Thread
1472 priority.....the priority
1474 *******************************************************************************/
1476 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1478 threadobject *thread;
1480 thread = (threadobject*) t->vmThread;
1482 threads_set_thread_priority(thread->tid, priority);
1486 /* threads_dump ****************************************************************
1488 Dumps info for all threads running in the JVM. This function is
1489 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1491 *******************************************************************************/
1493 void threads_dump(void)
1496 java_lang_VMThread *vmt;
1497 java_lang_Thread *t;
1500 tobj = mainthreadobj;
1502 printf("Full thread dump CACAO "VERSION":\n");
1504 /* iterate over all started threads */
1507 /* get thread objects */
1512 /* the thread may be currently in initalization, don't print it */
1515 /* get thread name */
1517 name = javastring_toutf(t->name, false);
1520 utf_display_printable_ascii(name);
1526 #if SIZEOF_VOID_P == 8
1527 printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1529 printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1532 /* send SIGUSR1 to thread to print stacktrace */
1534 pthread_kill(tobj->tid, SIGUSR1);
1536 /* sleep this thread a bit, so the signal can reach the thread */
1538 threads_sleep(10, 0);
1542 } while (tobj && (tobj != mainthreadobj));
1546 /* threads_table_dump *********************************************************
1548 Dump the threads table for debugging purposes.
1551 file..............stream to write to
1553 ******************************************************************************/
1555 #if !defined(NDEBUG)
1556 static void threads_table_dump(FILE *file)
1562 pthread_mutex_lock(&threadlistlock);
1564 size = threads_table.size;
1566 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1568 for (i=0; i<size; ++i) {
1569 index = threads_table.table[i].nextfree;
1571 fprintf(file, "%4d: ", i);
1574 fprintf(file, "free, nextfree = %d\n", index);
1577 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1581 fprintf(file, "======== END OF THREADS TABLE ========\n");
1583 pthread_mutex_unlock(&threadlistlock);
1588 * These are local overrides for various environment variables in Emacs.
1589 * Please do not remove this and leave it at the end of the file, where
1590 * Emacs will automagically detect them.
1591 * ---------------------------------------------------------------------
1594 * indent-tabs-mode: t
1598 * vim:noexpandtab:sw=4:ts=4: