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 4948 2006-05-24 14:11:16Z 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"
94 #if defined(__DARWIN__)
95 /* Darwin has no working semaphore implementation. This one is taken
99 This is a very simple semaphore implementation for darwin. It
100 is implemented in terms of pthreads calls so it isn't async signal
101 safe. This isn't a problem because signals aren't used to
102 suspend threads on darwin.
105 static int sem_init(sem_t *sem, int pshared, int value)
112 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
115 if (pthread_cond_init(&sem->cond, NULL) < 0)
121 static int sem_post(sem_t *sem)
123 if (pthread_mutex_lock(&sem->mutex) < 0)
128 if (pthread_cond_signal(&sem->cond) < 0) {
129 pthread_mutex_unlock(&sem->mutex);
133 if (pthread_mutex_unlock(&sem->mutex) < 0)
139 static int sem_wait(sem_t *sem)
141 if (pthread_mutex_lock(&sem->mutex) < 0)
144 while (sem->value == 0) {
145 pthread_cond_wait(&sem->cond, &sem->mutex);
150 if (pthread_mutex_unlock(&sem->mutex) < 0)
156 static int sem_destroy(sem_t *sem)
158 if (pthread_cond_destroy(&sem->cond) < 0)
161 if (pthread_mutex_destroy(&sem->mutex) < 0)
166 #endif /* defined(__DARWIN__) */
169 /* internally used constants **************************************************/
171 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
172 #define STOPWORLD_FROM_GC 1
173 #define STOPWORLD_FROM_CLASS_NUMBERING 2
175 #define THREADS_INITIAL_TABLE_SIZE 8
178 /* startupinfo *****************************************************************
180 Struct used to pass info from threads_start_thread to
181 threads_startup_thread.
183 ******************************************************************************/
186 threadobject *thread; /* threadobject for this thread */
187 functionptr function; /* function to run in the new thread */
188 sem_t *psem; /* signals when thread has been entered */
189 /* in the thread list */
190 sem_t *psem_first; /* signals when pthread_create has returned */
194 /* prototypes *****************************************************************/
196 static void threads_table_init(void);
197 static s4 threads_table_add(threadobject *thread);
198 static void threads_table_remove(threadobject *thread);
199 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
202 static void threads_table_dump(FILE *file);
205 /******************************************************************************/
206 /* GLOBAL VARIABLES */
207 /******************************************************************************/
209 /* the main thread */
210 threadobject *mainthreadobj;
212 /* the thread object of the current thread */
213 /* This is either a thread-local variable defined with __thread, or */
214 /* a thread-specific value stored with key threads_current_threadobject_key. */
215 #if defined(HAVE___THREAD)
216 __thread threadobject *threads_current_threadobject;
218 pthread_key_t threads_current_threadobject_key;
221 /* global threads table */
222 static threads_table_t threads_table;
224 /* global compiler mutex */
225 static pthread_mutex_rec_t compiler_mutex;
227 /* global mutex for changing the thread list */
228 static pthread_mutex_t threadlistlock;
230 /* global mutex for stop-the-world */
231 static pthread_mutex_t stopworldlock;
233 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
235 static volatile int stopworldwhere;
237 /* semaphore used for acknowleding thread suspension */
238 static sem_t suspend_ack;
239 #if defined(__MIPS__)
240 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
241 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
244 static pthread_attr_t threadattr;
246 /* mutexes used by the fake atomic instructions */
247 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
248 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
249 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
250 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
254 /******************************************************************************/
255 /* Recursive Mutex Implementation for Darwin */
256 /******************************************************************************/
258 #if defined(MUTEXSIM)
260 /* We need this for older MacOSX (10.1.x) */
262 void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
264 pthread_mutex_init(&m->mutex, NULL);
268 void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
270 pthread_mutex_destroy(&m->mutex);
273 void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
278 pthread_mutex_lock(&m->mutex);
279 m->owner = pthread_self();
284 if (m->owner != pthread_self()) {
285 pthread_mutex_lock(&m->mutex);
295 void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
298 pthread_mutex_unlock(&m->mutex);
301 #endif /* defined(MUTEXSIM) */
304 /* threads_sem_init ************************************************************
306 Initialize a semaphore. Checks against errors and interruptions.
309 sem..............the semaphore to initialize
310 shared...........true if this semaphore will be shared between processes
311 value............the initial value for the semaphore
313 *******************************************************************************/
315 void threads_sem_init(sem_t *sem, bool shared, int value)
322 r = sem_init(sem, shared, value);
325 } while (errno == EINTR);
327 vm_abort("sem_init failed: %s", strerror(errno));
331 /* threads_sem_wait ************************************************************
333 Wait for a semaphore, non-interruptible.
335 IMPORTANT: Always use this function instead of `sem_wait` directly, as
336 `sem_wait` may be interrupted by signals!
339 sem..............the semaphore to wait on
341 *******************************************************************************/
343 void threads_sem_wait(sem_t *sem)
353 } while (errno == EINTR);
355 vm_abort("sem_wait failed: %s", strerror(errno));
359 /* threads_sem_post ************************************************************
361 Increase the count of a semaphore. Checks for errors.
364 sem..............the semaphore to increase the count of
366 *******************************************************************************/
368 void threads_sem_post(sem_t *sem)
374 /* unlike sem_wait, sem_post is not interruptible */
380 vm_abort("sem_post failed: %s", strerror(errno));
384 /* threads_set_thread_priority *************************************************
386 Set the priority of the given thread.
389 tid..........thread id
390 priority.....priority to set
392 ******************************************************************************/
394 static void threads_set_thread_priority(pthread_t tid, int priority)
396 struct sched_param schedp;
399 pthread_getschedparam(tid, &policy, &schedp);
400 schedp.sched_priority = priority;
401 pthread_setschedparam(tid, policy, &schedp);
405 /* compiler_lock ***************************************************************
407 Enter the compiler lock.
409 ******************************************************************************/
411 void compiler_lock(void)
413 pthread_mutex_lock_rec(&compiler_mutex);
417 /* compiler_unlock *************************************************************
419 Release the compiler lock.
421 ******************************************************************************/
423 void compiler_unlock(void)
425 pthread_mutex_unlock_rec(&compiler_mutex);
429 /* lock_stopworld **************************************************************
431 Enter the stopworld lock, specifying why the world shall be stopped.
434 where........ STOPWORLD_FROM_GC (1) from within GC
435 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
437 ******************************************************************************/
439 void lock_stopworld(int where)
441 pthread_mutex_lock(&stopworldlock);
442 stopworldwhere = where;
446 /* unlock_stopworld ************************************************************
448 Release the stopworld lock.
450 ******************************************************************************/
452 void unlock_stopworld(void)
455 pthread_mutex_unlock(&stopworldlock);
458 #if !defined(__DARWIN__)
459 /* Caller must hold threadlistlock */
460 static int threads_cast_sendsignals(int sig, int count)
463 threadobject *tobj = mainthreadobj;
464 threadobject *self = THREADOBJECT;
470 } while (tobj != mainthreadobj);
473 assert(tobj == mainthreadobj);
477 pthread_kill(tobj->tid, sig);
479 } while (tobj != mainthreadobj);
486 static void threads_cast_darwinstop(void)
488 threadobject *tobj = mainthreadobj;
489 threadobject *self = THREADOBJECT;
494 thread_state_flavor_t flavor = PPC_THREAD_STATE;
495 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
496 ppc_thread_state_t thread_state;
497 mach_port_t thread = tobj->mach_thread;
500 r = thread_suspend(thread);
501 if (r != KERN_SUCCESS) {
502 log_text("thread_suspend failed");
506 r = thread_get_state(thread, flavor,
507 (natural_t*)&thread_state, &thread_state_count);
508 if (r != KERN_SUCCESS) {
509 log_text("thread_get_state failed");
513 thread_restartcriticalsection(&thread_state);
515 r = thread_set_state(thread, flavor,
516 (natural_t*)&thread_state, thread_state_count);
517 if (r != KERN_SUCCESS) {
518 log_text("thread_set_state failed");
523 } while (tobj != mainthreadobj);
526 static void threads_cast_darwinresume(void)
528 threadobject *tobj = mainthreadobj;
529 threadobject *self = THREADOBJECT;
534 mach_port_t thread = tobj->mach_thread;
537 r = thread_resume(thread);
538 if (r != KERN_SUCCESS) {
539 log_text("thread_resume failed");
544 } while (tobj != mainthreadobj);
549 #if defined(__MIPS__)
550 static void threads_cast_irixresume(void)
552 pthread_mutex_lock(&suspend_ack_lock);
553 pthread_cond_broadcast(&suspend_cond);
554 pthread_mutex_unlock(&suspend_ack_lock);
558 void threads_cast_stopworld(void)
561 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
562 pthread_mutex_lock(&threadlistlock);
563 #if defined(__DARWIN__)
564 threads_cast_darwinstop();
566 count = threads_cast_sendsignals(GC_signum1(), 0);
567 for (i=0; i<count; i++)
568 threads_sem_wait(&suspend_ack);
570 pthread_mutex_unlock(&threadlistlock);
573 void threads_cast_startworld(void)
575 pthread_mutex_lock(&threadlistlock);
576 #if defined(__DARWIN__)
577 threads_cast_darwinresume();
578 #elif defined(__MIPS__)
579 threads_cast_irixresume();
581 threads_cast_sendsignals(GC_signum2(), -1);
583 pthread_mutex_unlock(&threadlistlock);
587 #if !defined(__DARWIN__)
588 static void threads_sigsuspend_handler(ucontext_t *ctx)
593 /* XXX TWISTI: this is just a quick hack */
594 #if defined(ENABLE_JIT)
595 thread_restartcriticalsection(ctx);
598 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
599 (not POSIX async-safe). */
600 #if defined(__IRIX__)
601 pthread_mutex_lock(&suspend_ack_lock);
602 threads_sem_post(&suspend_ack);
603 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
604 pthread_mutex_unlock(&suspend_ack_lock);
606 threads_sem_post(&suspend_ack);
610 sigdelset(&sigs, sig);
615 /* This function is called from Boehm GC code. */
617 int cacao_suspendhandler(ucontext_t *ctx)
619 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
622 threads_sigsuspend_handler(ctx);
627 /* threads_set_current_threadobject ********************************************
629 Set the current thread object.
632 thread.......the thread object to set
634 *******************************************************************************/
636 static void threads_set_current_threadobject(threadobject *thread)
638 #if !defined(HAVE___THREAD)
639 pthread_setspecific(threads_current_threadobject_key, thread);
641 threads_current_threadobject = thread;
646 /* threads_get_current_threadobject ********************************************
648 Return the threadobject of the current thread.
651 the current threadobject * (an instance of java.lang.VMThread)
653 *******************************************************************************/
655 threadobject *threads_get_current_threadobject(void)
661 /* threads_preinit *************************************************************
663 Do some early initialization of stuff required.
665 *******************************************************************************/
667 void threads_preinit(void)
670 pthread_mutexattr_t mutexattr;
671 pthread_mutexattr_init(&mutexattr);
672 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
673 pthread_mutex_init(&compiler_mutex, &mutexattr);
674 pthread_mutexattr_destroy(&mutexattr);
676 pthread_mutex_init_rec(&compiler_mutex);
679 pthread_mutex_init(&threadlistlock, NULL);
680 pthread_mutex_init(&stopworldlock, NULL);
682 /* Allocate something so the garbage collector's signal handlers
684 heap_allocate(1, false, NULL);
686 mainthreadobj = NEW(threadobject);
687 mainthreadobj->tid = pthread_self();
688 mainthreadobj->index = 1;
689 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
691 #if !defined(HAVE___THREAD)
692 pthread_key_create(&threads_current_threadobject_key, NULL);
694 threads_set_current_threadobject(mainthreadobj);
696 threads_sem_init(&suspend_ack, 0, 0);
698 /* initialize the threads table */
700 threads_table_init();
702 /* initialize subsystems */
710 /* threads_init ****************************************************************
712 Initializes the threads required by the JVM: main, finalizer.
714 *******************************************************************************/
716 bool threads_init(void)
718 java_lang_String *threadname;
719 java_lang_Thread *mainthread;
720 java_lang_ThreadGroup *threadgroup;
721 threadobject *tempthread;
724 tempthread = mainthreadobj;
726 /* XXX We have to find a new way to free lock records */
727 /* with the new locking algorithm. */
728 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
730 /* This is kinda tricky, we grow the java.lang.Thread object so we
731 can keep the execution environment there. No Thread object must
732 have been created at an earlier time. */
734 class_java_lang_VMThread->instancesize = sizeof(threadobject);
736 /* create a VMThread */
738 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
740 if (mainthreadobj == NULL)
743 FREE(tempthread, threadobject);
745 threads_init_threadobject(&mainthreadobj->o);
747 threads_set_current_threadobject(mainthreadobj);
749 lock_init_execution_env(mainthreadobj);
751 mainthreadobj->next = mainthreadobj;
752 mainthreadobj->prev = mainthreadobj;
754 threads_table_add(mainthreadobj);
756 #if defined(ENABLE_INTRP)
757 /* create interpreter stack */
760 MSET(intrp_main_stack, 0, u1, opt_stacksize);
761 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
765 threadname = javastring_new(utf_new_char("main"));
767 /* allocate and init ThreadGroup */
769 threadgroup = (java_lang_ThreadGroup *)
770 native_new_and_init(class_java_lang_ThreadGroup);
773 throw_exception_exit();
775 /* create a Thread */
777 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
779 if (mainthread == NULL)
780 throw_exception_exit();
782 mainthreadobj->o.thread = mainthread;
784 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
786 method = class_resolveclassmethod(class_java_lang_Thread,
788 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
789 class_java_lang_Thread,
795 (void) vm_call_method(method, (java_objectheader *) mainthread,
796 mainthreadobj, threadname, 5, false);
801 mainthread->group = threadgroup;
803 /* add mainthread to ThreadGroup */
805 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
806 utf_new_char("addThread"),
807 utf_new_char("(Ljava/lang/Thread;)V"),
808 class_java_lang_ThreadGroup,
814 (void) vm_call_method(method, (java_objectheader *) threadgroup,
820 threads_set_thread_priority(pthread_self(), 5);
822 /* initialize the thread attribute object */
824 if (pthread_attr_init(&threadattr)) {
825 log_println("pthread_attr_init failed: %s", strerror(errno));
829 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
831 /* everything's ok */
837 /* threads_table_init *********************************************************
839 Initialize the global threads table.
841 ******************************************************************************/
843 static void threads_table_init(void)
848 size = THREADS_INITIAL_TABLE_SIZE;
850 threads_table.size = size;
851 threads_table.table = MNEW(threads_table_entry_t, size);
853 /* link the entries in a freelist */
855 for (i=0; i<size; ++i) {
856 threads_table.table[i].nextfree = i+1;
859 /* terminate the freelist */
861 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
865 /* threads_table_add **********************************************************
867 Add a thread to the global threads table. The index is entered in the
868 threadobject. The thinlock value for the thread is pre-computed.
871 thread............the thread to add
874 The table index for the newly added thread. This value has also been
875 entered in the threadobject.
878 The caller must hold the threadlistlock!
880 ******************************************************************************/
882 static s4 threads_table_add(threadobject *thread)
889 /* table[0] serves as the head of the freelist */
891 index = threads_table.table[0].nextfree;
893 /* if we got a free index, use it */
897 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
898 threads_table.table[index].thread = thread;
899 thread->index = index;
900 thread->thinlock = lock_pre_compute_thinlock(index);
904 /* we must grow the table */
906 oldsize = threads_table.size;
907 newsize = oldsize * 2;
909 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
911 threads_table.size = newsize;
913 /* link the new entries to a free list */
915 for (i=oldsize; i<newsize; ++i) {
916 threads_table.table[i].nextfree = i+1;
919 /* terminate the freelist */
921 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
923 /* use the first of the new entries */
930 /* threads_table_remove *******************************************************
932 Remove a thread from the global threads table.
935 thread............the thread to remove
938 The caller must hold the threadlistlock!
940 ******************************************************************************/
942 static void threads_table_remove(threadobject *thread)
946 index = thread->index;
948 /* put the index into the freelist */
950 threads_table.table[index] = threads_table.table[0];
951 threads_table.table[0].nextfree = index;
953 /* delete the index in the threadobject to discover bugs */
959 /* threads_init_threadobject **************************************************
961 Initialize implementation fields of a java.lang.VMThread.
964 t............the java.lang.VMThread
966 ******************************************************************************/
968 void threads_init_threadobject(java_lang_VMThread *t)
970 threadobject *thread = (threadobject*) t;
972 thread->tid = pthread_self();
976 /* TODO destroy all those things */
977 pthread_mutex_init(&(thread->joinmutex), NULL);
978 pthread_cond_init(&(thread->joincond), NULL);
980 pthread_mutex_init(&(thread->waitmutex), NULL);
981 pthread_cond_init(&(thread->waitcond), NULL);
983 thread->interrupted = false;
984 thread->signaled = false;
985 thread->sleeping = false;
989 /* threads_startup_thread ******************************************************
991 Thread startup function called by pthread_create.
993 NOTE: This function is not called directly by pthread_create. The Boehm GC
994 inserts its own GC_start_routine in between, which then calls
998 t............the argument passed to pthread_create, ie. a pointer to
999 a startupinfo struct. CAUTION: When the `psem` semaphore
1000 is posted, the startupinfo struct becomes invalid! (It
1001 is allocated on the stack of threads_start_thread.)
1003 ******************************************************************************/
1005 static void *threads_startup_thread(void *t)
1007 startupinfo *startup;
1008 threadobject *thread;
1010 threadobject *tnext;
1012 functionptr function;
1014 #if defined(ENABLE_INTRP)
1015 u1 *intrp_thread_stack;
1017 /* create interpreter stack */
1020 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1021 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1024 intrp_thread_stack = NULL;
1027 /* get passed startupinfo structure and the values in there */
1030 t = NULL; /* make sure it's not used wrongly */
1032 thread = startup->thread;
1033 function = startup->function;
1034 psem = startup->psem;
1036 /* Seems like we've encountered a situation where thread->tid was not set by
1037 * pthread_create. We alleviate this problem by waiting for pthread_create
1039 threads_sem_wait(startup->psem_first);
1041 /* set the thread object */
1043 #if defined(__DARWIN__)
1044 thread->mach_thread = mach_thread_self();
1046 threads_set_current_threadobject(thread);
1048 /* insert the thread into the threadlist and the threads table */
1050 pthread_mutex_lock(&threadlistlock);
1052 thread->prev = mainthreadobj;
1053 thread->next = tnext = mainthreadobj->next;
1054 mainthreadobj->next = thread;
1055 tnext->prev = thread;
1057 threads_table_add(thread);
1059 pthread_mutex_unlock(&threadlistlock);
1061 /* init data structures of this thread */
1063 lock_init_execution_env(thread);
1065 /* tell threads_startup_thread that we registered ourselves */
1066 /* CAUTION: *startup becomes invalid with this! */
1069 threads_sem_post(psem);
1071 /* set our priority */
1073 threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1075 #if defined(ENABLE_INTRP)
1076 /* set interpreter stack */
1079 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1084 #if defined(ENABLE_JVMTI)
1085 /* breakpoint for thread start event */
1086 __asm__("threadstart:");
1090 /* find and run the Thread.run()V method if no other function was passed */
1092 if (function == NULL) {
1093 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1096 thread->o.header.vftbl->class,
1102 (void) vm_call_method(method, (java_objectheader *) thread);
1106 /* call passed function, e.g. finalizer_thread */
1111 #if defined(ENABLE_JVMTI)
1112 /* breakpoint for thread end event */
1113 __asm__("threadend:");
1117 /* Allow lock record pools to be used by other threads. They
1118 cannot be deleted so we'd better not waste them. */
1120 /* XXX We have to find a new way to free lock records */
1121 /* with the new locking algorithm. */
1122 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1124 /* remove thread from thread list and threads table, do this inside a lock */
1126 pthread_mutex_lock(&threadlistlock);
1128 thread->next->prev = thread->prev;
1129 thread->prev->next = thread->next;
1131 threads_table_remove(thread);
1133 pthread_mutex_unlock(&threadlistlock);
1135 /* reset thread id (lock on joinmutex? TWISTI) */
1137 pthread_mutex_lock(&thread->joinmutex);
1139 pthread_mutex_unlock(&thread->joinmutex);
1141 /* tell everyone that a thread has finished */
1143 pthread_cond_broadcast(&thread->joincond);
1149 /* threads_start_thread ********************************************************
1151 Start a thread in the JVM.
1154 t............the java.lang.Thread object
1155 function.....function to run in the new thread. NULL means that the
1156 "run" method of the object `t` should be called
1158 ******************************************************************************/
1160 void threads_start_thread(java_lang_Thread *t, functionptr function)
1164 pthread_attr_t attr;
1165 startupinfo startup;
1166 threadobject *thread;
1168 thread = (threadobject *) t->vmThread;
1170 /* fill startupinfo structure passed by pthread_create to
1171 * threads_startup_thread */
1173 startup.thread = thread;
1174 startup.function = function; /* maybe we don't call Thread.run()V */
1175 startup.psem = &sem;
1176 startup.psem_first = &sem_first;
1178 threads_sem_init(&sem, 0, 0);
1179 threads_sem_init(&sem_first, 0, 0);
1181 /* initialize thread attribute object */
1183 if (pthread_attr_init(&attr))
1184 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1186 /* initialize thread stacksize */
1188 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1189 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1191 /* create the thread */
1193 if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1194 vm_abort("pthread_create failed: %s", strerror(errno));
1196 /* signal that pthread_create has returned, so thread->tid is valid */
1198 threads_sem_post(&sem_first);
1200 /* wait here until the thread has entered itself into the thread list */
1202 threads_sem_wait(&sem);
1207 sem_destroy(&sem_first);
1211 /* threads_find_non_daemon_thread **********************************************
1213 Helper function used by threads_join_all_threads for finding non-daemon threads
1214 that are still running.
1216 *******************************************************************************/
1218 /* At the end of the program, we wait for all running non-daemon threads to die
1221 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1223 while (thread != mainthreadobj) {
1224 if (!thread->o.thread->daemon)
1226 thread = thread->prev;
1233 /* threads_join_all_threads ****************************************************
1235 Join all non-daemon threads.
1237 *******************************************************************************/
1239 void threads_join_all_threads(void)
1241 threadobject *thread;
1243 pthread_mutex_lock(&threadlistlock);
1245 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1247 pthread_mutex_lock(&thread->joinmutex);
1249 pthread_mutex_unlock(&threadlistlock);
1252 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1254 pthread_mutex_unlock(&thread->joinmutex);
1256 pthread_mutex_lock(&threadlistlock);
1259 pthread_mutex_unlock(&threadlistlock);
1263 /* threads_timespec_earlier ****************************************************
1265 Return true if timespec tv1 is earlier than timespec tv2.
1268 tv1..........first timespec
1269 tv2..........second timespec
1272 true, if the first timespec is earlier
1274 *******************************************************************************/
1276 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1277 const struct timespec *tv2)
1279 return (tv1->tv_sec < tv2->tv_sec)
1281 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1285 /* threads_current_time_is_earlier_than ****************************************
1287 Check if the current time is earlier than the given timespec.
1290 tv...........the timespec to compare against
1293 true, if the current time is earlier
1295 *******************************************************************************/
1297 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1299 struct timeval tvnow;
1300 struct timespec tsnow;
1302 /* get current time */
1304 if (gettimeofday(&tvnow, NULL) != 0)
1305 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1307 /* convert it to a timespec */
1309 tsnow.tv_sec = tvnow.tv_sec;
1310 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1312 /* compare current time with the given timespec */
1314 return threads_timespec_earlier(&tsnow, tv);
1318 /* threads_wait_with_timeout ***************************************************
1320 Wait until the given point in time on a monitor until either
1321 we are notified, we are interrupted, or the time is up.
1324 t............the current thread
1325 wakeupTime...absolute (latest) wakeup time
1326 If both tv_sec and tv_nsec are zero, this function
1327 waits for an unlimited amount of time.
1330 true.........if the wait has been interrupted,
1331 false........if the wait was ended by notification or timeout
1333 *******************************************************************************/
1335 static bool threads_wait_with_timeout(threadobject *t,
1336 struct timespec *wakeupTime)
1338 bool wasinterrupted;
1340 /* acquire the waitmutex */
1342 pthread_mutex_lock(&t->waitmutex);
1344 /* mark us as sleeping */
1348 /* wait on waitcond */
1350 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1352 while (!t->interrupted && !t->signaled
1353 && threads_current_time_is_earlier_than(wakeupTime))
1355 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1360 while (!t->interrupted && !t->signaled)
1361 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1364 /* check if we were interrupted */
1366 wasinterrupted = t->interrupted;
1368 /* reset all flags */
1370 t->interrupted = false;
1371 t->signaled = false;
1372 t->sleeping = false;
1374 /* release the waitmutex */
1376 pthread_mutex_unlock(&t->waitmutex);
1378 return wasinterrupted;
1382 /* threads_wait_with_timeout_relative ******************************************
1384 Wait for the given maximum amount of time on a monitor until either
1385 we are notified, we are interrupted, or the time is up.
1388 t............the current thread
1389 millis.......milliseconds to wait
1390 nanos........nanoseconds to wait
1393 true.........if the wait has been interrupted,
1394 false........if the wait was ended by notification or timeout
1396 *******************************************************************************/
1398 bool threads_wait_with_timeout_relative(threadobject *t,
1402 struct timespec wakeupTime;
1404 /* calculate the the (latest) wakeup time */
1406 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1410 return threads_wait_with_timeout(t, &wakeupTime);
1414 /* threads_calc_absolute_time **************************************************
1416 Calculate the absolute point in time a given number of ms and ns from now.
1419 millis............milliseconds from now
1420 nanos.............nanoseconds from now
1423 *tm...............receives the timespec of the absolute point in time
1425 *******************************************************************************/
1427 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1429 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1432 gettimeofday(&tv, NULL);
1433 tv.tv_sec += millis / 1000;
1435 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1436 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1437 tm->tv_nsec = nsec % 1000000000;
1446 /* threads_interrupt_thread ****************************************************
1448 Interrupt the given thread.
1450 The thread gets the "waitcond" signal and
1451 its interrupted flag is set to true.
1454 thread............the thread to interrupt
1456 *******************************************************************************/
1458 void threads_interrupt_thread(java_lang_VMThread *thread)
1460 threadobject *t = (threadobject*) thread;
1462 /* signal the thread a "waitcond" and tell it that it has been */
1465 pthread_mutex_lock(&t->waitmutex);
1467 pthread_cond_signal(&t->waitcond);
1468 t->interrupted = true;
1469 pthread_mutex_unlock(&t->waitmutex);
1473 /* threads_check_if_interrupted_and_reset **************************************
1475 Check if the current thread has been interrupted and reset the
1479 true, if the current thread had been interrupted
1481 *******************************************************************************/
1483 bool threads_check_if_interrupted_and_reset(void)
1488 t = (threadobject*) THREADOBJECT;
1490 intr = t->interrupted;
1492 t->interrupted = false;
1498 /* threads_thread_has_been_interrupted *********************************************************
1500 Check if the given thread has been interrupted
1503 t............the thread to check
1506 true, if the given thread had been interrupted
1508 *******************************************************************************/
1510 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1514 t = (threadobject*) thread;
1516 return t->interrupted;
1520 /* threads_sleep ***************************************************************
1522 Sleep the current thread for the specified amount of time.
1524 *******************************************************************************/
1526 void threads_sleep(s8 millis, s4 nanos)
1529 struct timespec wakeupTime;
1530 bool wasinterrupted;
1532 t = (threadobject *) THREADOBJECT;
1534 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1536 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1539 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1543 /* threads_yield *****************************************************************
1545 Yield to the scheduler.
1547 *******************************************************************************/
1549 void threads_yield(void)
1555 /* threads_java_lang_Thread_set_priority ***********************************************************
1557 Set the priority for the given java.lang.Thread.
1560 t............the java.lang.Thread
1561 priority.....the priority
1563 *******************************************************************************/
1565 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1567 threadobject *thread;
1569 thread = (threadobject*) t->vmThread;
1571 threads_set_thread_priority(thread->tid, priority);
1575 /* threads_dump ****************************************************************
1577 Dumps info for all threads running in the JVM. This function is
1578 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1580 *******************************************************************************/
1582 void threads_dump(void)
1585 java_lang_VMThread *vmt;
1586 java_lang_Thread *t;
1589 tobj = mainthreadobj;
1591 printf("Full thread dump CACAO "VERSION":\n");
1593 /* iterate over all started threads */
1596 /* get thread objects */
1601 /* the thread may be currently in initalization, don't print it */
1604 /* get thread name */
1606 name = javastring_toutf(t->name, false);
1609 utf_display_printable_ascii(name);
1615 #if SIZEOF_VOID_P == 8
1616 printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1618 printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1621 /* send SIGUSR1 to thread to print stacktrace */
1623 pthread_kill(tobj->tid, SIGUSR1);
1625 /* sleep this thread a bit, so the signal can reach the thread */
1627 threads_sleep(10, 0);
1631 } while (tobj && (tobj != mainthreadobj));
1635 /* threads_table_dump *********************************************************
1637 Dump the threads table for debugging purposes.
1640 file..............stream to write to
1642 ******************************************************************************/
1644 #if !defined(NDEBUG)
1645 static void threads_table_dump(FILE *file)
1651 pthread_mutex_lock(&threadlistlock);
1653 size = threads_table.size;
1655 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1657 for (i=0; i<size; ++i) {
1658 index = threads_table.table[i].nextfree;
1660 fprintf(file, "%4d: ", i);
1663 fprintf(file, "free, nextfree = %d\n", index);
1666 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1670 fprintf(file, "======== END OF THREADS TABLE ========\n");
1672 pthread_mutex_unlock(&threadlistlock);
1677 #if defined(ENABLE_JVMTI)
1678 /* jvmti_get_threads_breakpoints ***********************************************
1680 gets all breakpoints from this file
1682 *******************************************************************************/
1684 void jvmti_get_threads_breakpoints(void **brks) {
1685 __asm__ ("movl $threadstart,%0;" :"=m"(brks[0]));
1686 __asm__ ("movl $threadend,%0;" :"=m"(brks[1]));
1691 * These are local overrides for various environment variables in Emacs.
1692 * Please do not remove this and leave it at the end of the file, where
1693 * Emacs will automagically detect them.
1694 * ---------------------------------------------------------------------
1697 * indent-tabs-mode: t
1701 * vim:noexpandtab:sw=4:ts=4: