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 4938 2006-05-22 09:06:44Z 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);
628 /* threads_set_current_threadobject ********************************************
630 Set the current thread object.
633 thread.......the thread object to set
635 *******************************************************************************/
637 #if !defined(ENABLE_JVMTI)
638 static void threads_set_current_threadobject(threadobject *thread)
640 void threads_set_current_threadobject(threadobject *thread)
643 #if !defined(HAVE___THREAD)
644 pthread_setspecific(threads_current_threadobject_key, thread);
646 threads_current_threadobject = thread;
651 /* threads_get_current_threadobject ********************************************
653 Return the threadobject of the current thread.
656 the current threadobject * (an instance of java.lang.VMThread)
658 *******************************************************************************/
660 threadobject *threads_get_current_threadobject(void)
666 /* threads_preinit *************************************************************
668 Do some early initialization of stuff required.
670 *******************************************************************************/
672 void threads_preinit(void)
675 pthread_mutexattr_t mutexattr;
676 pthread_mutexattr_init(&mutexattr);
677 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
678 pthread_mutex_init(&compiler_mutex, &mutexattr);
679 pthread_mutexattr_destroy(&mutexattr);
681 pthread_mutex_init_rec(&compiler_mutex);
684 pthread_mutex_init(&threadlistlock, NULL);
685 pthread_mutex_init(&stopworldlock, NULL);
687 /* Allocate something so the garbage collector's signal handlers
689 heap_allocate(1, false, NULL);
691 mainthreadobj = NEW(threadobject);
692 mainthreadobj->tid = pthread_self();
693 mainthreadobj->index = 1;
694 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
696 #if !defined(HAVE___THREAD)
697 pthread_key_create(&threads_current_threadobject_key, NULL);
699 threads_set_current_threadobject(mainthreadobj);
701 threads_sem_init(&suspend_ack, 0, 0);
703 /* initialize the threads table */
705 threads_table_init();
707 /* initialize subsystems */
715 /* threads_init ****************************************************************
717 Initializes the threads required by the JVM: main, finalizer.
719 *******************************************************************************/
721 bool threads_init(void)
723 java_lang_String *threadname;
724 java_lang_Thread *mainthread;
725 java_lang_ThreadGroup *threadgroup;
726 threadobject *tempthread;
729 tempthread = mainthreadobj;
731 /* XXX We have to find a new way to free lock records */
732 /* with the new locking algorithm. */
733 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
735 /* This is kinda tricky, we grow the java.lang.Thread object so we
736 can keep the execution environment there. No Thread object must
737 have been created at an earlier time. */
739 class_java_lang_VMThread->instancesize = sizeof(threadobject);
741 /* create a VMThread */
743 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
745 if (mainthreadobj == NULL)
748 FREE(tempthread, threadobject);
750 threads_init_threadobject(&mainthreadobj->o);
752 threads_set_current_threadobject(mainthreadobj);
754 lock_init_execution_env(mainthreadobj);
756 mainthreadobj->next = mainthreadobj;
757 mainthreadobj->prev = mainthreadobj;
759 threads_table_add(mainthreadobj);
761 #if defined(ENABLE_INTRP)
762 /* create interpreter stack */
765 MSET(intrp_main_stack, 0, u1, opt_stacksize);
766 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
770 threadname = javastring_new(utf_new_char("main"));
772 /* allocate and init ThreadGroup */
774 threadgroup = (java_lang_ThreadGroup *)
775 native_new_and_init(class_java_lang_ThreadGroup);
778 throw_exception_exit();
780 /* create a Thread */
782 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
784 if (mainthread == NULL)
785 throw_exception_exit();
787 mainthreadobj->o.thread = mainthread;
789 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
791 method = class_resolveclassmethod(class_java_lang_Thread,
793 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
794 class_java_lang_Thread,
800 (void) vm_call_method(method, (java_objectheader *) mainthread,
801 mainthreadobj, threadname, 5, false);
806 mainthread->group = threadgroup;
808 /* add mainthread to ThreadGroup */
810 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
811 utf_new_char("addThread"),
812 utf_new_char("(Ljava/lang/Thread;)V"),
813 class_java_lang_ThreadGroup,
819 (void) vm_call_method(method, (java_objectheader *) threadgroup,
825 threads_set_thread_priority(pthread_self(), 5);
827 /* initialize the thread attribute object */
829 if (pthread_attr_init(&threadattr)) {
830 log_println("pthread_attr_init failed: %s", strerror(errno));
834 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
836 /* everything's ok */
842 /* threads_table_init *********************************************************
844 Initialize the global threads table.
846 ******************************************************************************/
848 static void threads_table_init(void)
853 size = THREADS_INITIAL_TABLE_SIZE;
855 threads_table.size = size;
856 threads_table.table = MNEW(threads_table_entry_t, size);
858 /* link the entries in a freelist */
860 for (i=0; i<size; ++i) {
861 threads_table.table[i].nextfree = i+1;
864 /* terminate the freelist */
866 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
870 /* threads_table_add **********************************************************
872 Add a thread to the global threads table. The index is entered in the
873 threadobject. The thinlock value for the thread is pre-computed.
876 thread............the thread to add
879 The table index for the newly added thread. This value has also been
880 entered in the threadobject.
883 The caller must hold the threadlistlock!
885 ******************************************************************************/
887 static s4 threads_table_add(threadobject *thread)
894 /* table[0] serves as the head of the freelist */
896 index = threads_table.table[0].nextfree;
898 /* if we got a free index, use it */
902 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
903 threads_table.table[index].thread = thread;
904 thread->index = index;
905 thread->thinlock = lock_pre_compute_thinlock(index);
909 /* we must grow the table */
911 oldsize = threads_table.size;
912 newsize = oldsize * 2;
914 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
916 threads_table.size = newsize;
918 /* link the new entries to a free list */
920 for (i=oldsize; i<newsize; ++i) {
921 threads_table.table[i].nextfree = i+1;
924 /* terminate the freelist */
926 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
928 /* use the first of the new entries */
935 /* threads_table_remove *******************************************************
937 Remove a thread from the global threads table.
940 thread............the thread to remove
943 The caller must hold the threadlistlock!
945 ******************************************************************************/
947 static void threads_table_remove(threadobject *thread)
951 index = thread->index;
953 /* put the index into the freelist */
955 threads_table.table[index] = threads_table.table[0];
956 threads_table.table[0].nextfree = index;
958 /* delete the index in the threadobject to discover bugs */
964 /* threads_init_threadobject **************************************************
966 Initialize implementation fields of a java.lang.VMThread.
969 t............the java.lang.VMThread
971 ******************************************************************************/
973 void threads_init_threadobject(java_lang_VMThread *t)
975 threadobject *thread = (threadobject*) t;
977 thread->tid = pthread_self();
981 /* TODO destroy all those things */
982 pthread_mutex_init(&(thread->joinmutex), NULL);
983 pthread_cond_init(&(thread->joincond), NULL);
985 pthread_mutex_init(&(thread->waitmutex), NULL);
986 pthread_cond_init(&(thread->waitcond), NULL);
988 thread->interrupted = false;
989 thread->signaled = false;
990 thread->sleeping = false;
994 /* threads_startup_thread ******************************************************
996 Thread startup function called by pthread_create.
998 NOTE: This function is not called directly by pthread_create. The Boehm GC
999 inserts its own GC_start_routine in between, which then calls
1003 t............the argument passed to pthread_create, ie. a pointer to
1004 a startupinfo struct. CAUTION: When the `psem` semaphore
1005 is posted, the startupinfo struct becomes invalid! (It
1006 is allocated on the stack of threads_start_thread.)
1008 ******************************************************************************/
1010 static void *threads_startup_thread(void *t)
1012 startupinfo *startup;
1013 threadobject *thread;
1015 threadobject *tnext;
1017 functionptr function;
1019 #if defined(ENABLE_INTRP)
1020 u1 *intrp_thread_stack;
1022 /* create interpreter stack */
1025 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
1026 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1028 intrp_thread_stack = NULL;
1032 /* get passed startupinfo structure and the values in there */
1035 t = NULL; /* make sure it's not used wrongly */
1037 thread = startup->thread;
1038 function = startup->function;
1039 psem = startup->psem;
1041 /* Seems like we've encountered a situation where thread->tid was not set by
1042 * pthread_create. We alleviate this problem by waiting for pthread_create
1044 threads_sem_wait(startup->psem_first);
1046 /* set the thread object */
1048 #if defined(__DARWIN__)
1049 thread->mach_thread = mach_thread_self();
1051 threads_set_current_threadobject(thread);
1053 /* insert the thread into the threadlist and the threads table */
1055 pthread_mutex_lock(&threadlistlock);
1057 thread->prev = mainthreadobj;
1058 thread->next = tnext = mainthreadobj->next;
1059 mainthreadobj->next = thread;
1060 tnext->prev = thread;
1062 threads_table_add(thread);
1064 pthread_mutex_unlock(&threadlistlock);
1066 /* init data structures of this thread */
1068 lock_init_execution_env(thread);
1070 /* tell threads_startup_thread that we registered ourselves */
1071 /* CAUTION: *startup becomes invalid with this! */
1074 threads_sem_post(psem);
1076 /* set our priority */
1078 threads_set_thread_priority(thread->tid, thread->o.thread->priority);
1080 #if defined(ENABLE_INTRP)
1081 /* set interpreter stack */
1084 thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
1087 /* find and run the Thread.run()V method if no other function was passed */
1089 if (function == NULL) {
1090 method = class_resolveclassmethod(thread->o.header.vftbl->class,
1093 thread->o.header.vftbl->class,
1099 (void) vm_call_method(method, (java_objectheader *) thread);
1103 /* call passed function, e.g. finalizer_thread */
1108 /* Allow lock record pools to be used by other threads. They
1109 cannot be deleted so we'd better not waste them. */
1111 /* XXX We have to find a new way to free lock records */
1112 /* with the new locking algorithm. */
1113 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1115 /* remove thread from thread list and threads table, do this inside a lock */
1117 pthread_mutex_lock(&threadlistlock);
1119 thread->next->prev = thread->prev;
1120 thread->prev->next = thread->next;
1122 threads_table_remove(thread);
1124 pthread_mutex_unlock(&threadlistlock);
1126 /* reset thread id (lock on joinmutex? TWISTI) */
1128 pthread_mutex_lock(&thread->joinmutex);
1130 pthread_mutex_unlock(&thread->joinmutex);
1132 /* tell everyone that a thread has finished */
1134 pthread_cond_broadcast(&thread->joincond);
1140 /* threads_start_thread ********************************************************
1142 Start a thread in the JVM.
1145 t............the java.lang.Thread object
1146 function.....function to run in the new thread. NULL means that the
1147 "run" method of the object `t` should be called
1149 ******************************************************************************/
1151 void threads_start_thread(java_lang_Thread *t, functionptr function)
1155 pthread_attr_t attr;
1156 startupinfo startup;
1157 threadobject *thread;
1159 thread = (threadobject *) t->vmThread;
1161 /* fill startupinfo structure passed by pthread_create to
1162 * threads_startup_thread */
1164 startup.thread = thread;
1165 startup.function = function; /* maybe we don't call Thread.run()V */
1166 startup.psem = &sem;
1167 startup.psem_first = &sem_first;
1169 threads_sem_init(&sem, 0, 0);
1170 threads_sem_init(&sem_first, 0, 0);
1172 /* initialize thread attribute object */
1174 if (pthread_attr_init(&attr))
1175 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1177 /* initialize thread stacksize */
1179 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1180 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1182 /* create the thread */
1184 if (pthread_create(&thread->tid, &attr, threads_startup_thread, &startup))
1185 vm_abort("pthread_create failed: %s", strerror(errno));
1187 /* signal that pthread_create has returned, so thread->tid is valid */
1189 threads_sem_post(&sem_first);
1191 /* wait here until the thread has entered itself into the thread list */
1193 threads_sem_wait(&sem);
1198 sem_destroy(&sem_first);
1202 /* threads_find_non_daemon_thread **********************************************
1204 Helper function used by threads_join_all_threads for finding non-daemon threads
1205 that are still running.
1207 *******************************************************************************/
1209 /* At the end of the program, we wait for all running non-daemon threads to die
1212 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1214 while (thread != mainthreadobj) {
1215 if (!thread->o.thread->daemon)
1217 thread = thread->prev;
1224 /* threads_join_all_threads ****************************************************
1226 Join all non-daemon threads.
1228 *******************************************************************************/
1230 void threads_join_all_threads(void)
1232 threadobject *thread;
1234 pthread_mutex_lock(&threadlistlock);
1236 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1238 pthread_mutex_lock(&thread->joinmutex);
1240 pthread_mutex_unlock(&threadlistlock);
1243 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1245 pthread_mutex_unlock(&thread->joinmutex);
1247 pthread_mutex_lock(&threadlistlock);
1250 pthread_mutex_unlock(&threadlistlock);
1254 /* threads_timespec_earlier ****************************************************
1256 Return true if timespec tv1 is earlier than timespec tv2.
1259 tv1..........first timespec
1260 tv2..........second timespec
1263 true, if the first timespec is earlier
1265 *******************************************************************************/
1267 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1268 const struct timespec *tv2)
1270 return (tv1->tv_sec < tv2->tv_sec)
1272 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1276 /* threads_current_time_is_earlier_than ****************************************
1278 Check if the current time is earlier than the given timespec.
1281 tv...........the timespec to compare against
1284 true, if the current time is earlier
1286 *******************************************************************************/
1288 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1290 struct timeval tvnow;
1291 struct timespec tsnow;
1293 /* get current time */
1295 if (gettimeofday(&tvnow, NULL) != 0)
1296 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1298 /* convert it to a timespec */
1300 tsnow.tv_sec = tvnow.tv_sec;
1301 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1303 /* compare current time with the given timespec */
1305 return threads_timespec_earlier(&tsnow, tv);
1309 /* threads_wait_with_timeout ***************************************************
1311 Wait until the given point in time on a monitor until either
1312 we are notified, we are interrupted, or the time is up.
1315 t............the current thread
1316 wakeupTime...absolute (latest) wakeup time
1317 If both tv_sec and tv_nsec are zero, this function
1318 waits for an unlimited amount of time.
1321 true.........if the wait has been interrupted,
1322 false........if the wait was ended by notification or timeout
1324 *******************************************************************************/
1326 static bool threads_wait_with_timeout(threadobject *t,
1327 struct timespec *wakeupTime)
1329 bool wasinterrupted;
1331 /* acquire the waitmutex */
1333 pthread_mutex_lock(&t->waitmutex);
1335 /* mark us as sleeping */
1339 /* wait on waitcond */
1341 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1343 while (!t->interrupted && !t->signaled
1344 && threads_current_time_is_earlier_than(wakeupTime))
1346 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1351 while (!t->interrupted && !t->signaled)
1352 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1355 /* check if we were interrupted */
1357 wasinterrupted = t->interrupted;
1359 /* reset all flags */
1361 t->interrupted = false;
1362 t->signaled = false;
1363 t->sleeping = false;
1365 /* release the waitmutex */
1367 pthread_mutex_unlock(&t->waitmutex);
1369 return wasinterrupted;
1373 /* threads_wait_with_timeout_relative ******************************************
1375 Wait for the given maximum amount of time on a monitor until either
1376 we are notified, we are interrupted, or the time is up.
1379 t............the current thread
1380 millis.......milliseconds to wait
1381 nanos........nanoseconds to wait
1384 true.........if the wait has been interrupted,
1385 false........if the wait was ended by notification or timeout
1387 *******************************************************************************/
1389 bool threads_wait_with_timeout_relative(threadobject *t,
1393 struct timespec wakeupTime;
1395 /* calculate the the (latest) wakeup time */
1397 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1401 return threads_wait_with_timeout(t, &wakeupTime);
1405 /* threads_calc_absolute_time **************************************************
1407 Calculate the absolute point in time a given number of ms and ns from now.
1410 millis............milliseconds from now
1411 nanos.............nanoseconds from now
1414 *tm...............receives the timespec of the absolute point in time
1416 *******************************************************************************/
1418 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1420 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1423 gettimeofday(&tv, NULL);
1424 tv.tv_sec += millis / 1000;
1426 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1427 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1428 tm->tv_nsec = nsec % 1000000000;
1437 /* threads_interrupt_thread ****************************************************
1439 Interrupt the given thread.
1441 The thread gets the "waitcond" signal and
1442 its interrupted flag is set to true.
1445 thread............the thread to interrupt
1447 *******************************************************************************/
1449 void threads_interrupt_thread(java_lang_VMThread *thread)
1451 threadobject *t = (threadobject*) thread;
1453 /* signal the thread a "waitcond" and tell it that it has been */
1456 pthread_mutex_lock(&t->waitmutex);
1458 pthread_cond_signal(&t->waitcond);
1459 t->interrupted = true;
1460 pthread_mutex_unlock(&t->waitmutex);
1464 /* threads_check_if_interrupted_and_reset **************************************
1466 Check if the current thread has been interrupted and reset the
1470 true, if the current thread had been interrupted
1472 *******************************************************************************/
1474 bool threads_check_if_interrupted_and_reset(void)
1479 t = (threadobject*) THREADOBJECT;
1481 intr = t->interrupted;
1483 t->interrupted = false;
1489 /* threads_thread_has_been_interrupted *********************************************************
1491 Check if the given thread has been interrupted
1494 t............the thread to check
1497 true, if the given thread had been interrupted
1499 *******************************************************************************/
1501 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1505 t = (threadobject*) thread;
1507 return t->interrupted;
1511 /* threads_sleep ***************************************************************
1513 Sleep the current thread for the specified amount of time.
1515 *******************************************************************************/
1517 void threads_sleep(s8 millis, s4 nanos)
1520 struct timespec wakeupTime;
1521 bool wasinterrupted;
1523 t = (threadobject *) THREADOBJECT;
1525 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1527 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1530 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1534 /* threads_yield *****************************************************************
1536 Yield to the scheduler.
1538 *******************************************************************************/
1540 void threads_yield(void)
1546 /* threads_java_lang_Thread_set_priority ***********************************************************
1548 Set the priority for the given java.lang.Thread.
1551 t............the java.lang.Thread
1552 priority.....the priority
1554 *******************************************************************************/
1556 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1558 threadobject *thread;
1560 thread = (threadobject*) t->vmThread;
1562 threads_set_thread_priority(thread->tid, priority);
1566 /* threads_dump ****************************************************************
1568 Dumps info for all threads running in the JVM. This function is
1569 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1571 *******************************************************************************/
1573 void threads_dump(void)
1576 java_lang_VMThread *vmt;
1577 java_lang_Thread *t;
1580 tobj = mainthreadobj;
1582 printf("Full thread dump CACAO "VERSION":\n");
1584 /* iterate over all started threads */
1587 /* get thread objects */
1592 /* the thread may be currently in initalization, don't print it */
1595 /* get thread name */
1597 name = javastring_toutf(t->name, false);
1600 utf_display_printable_ascii(name);
1606 #if SIZEOF_VOID_P == 8
1607 printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1609 printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1612 /* send SIGUSR1 to thread to print stacktrace */
1614 pthread_kill(tobj->tid, SIGUSR1);
1616 /* sleep this thread a bit, so the signal can reach the thread */
1618 threads_sleep(10, 0);
1622 } while (tobj && (tobj != mainthreadobj));
1626 /* threads_table_dump *********************************************************
1628 Dump the threads table for debugging purposes.
1631 file..............stream to write to
1633 ******************************************************************************/
1635 #if !defined(NDEBUG)
1636 static void threads_table_dump(FILE *file)
1642 pthread_mutex_lock(&threadlistlock);
1644 size = threads_table.size;
1646 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1648 for (i=0; i<size; ++i) {
1649 index = threads_table.table[i].nextfree;
1651 fprintf(file, "%4d: ", i);
1654 fprintf(file, "free, nextfree = %d\n", index);
1657 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1661 fprintf(file, "======== END OF THREADS TABLE ========\n");
1663 pthread_mutex_unlock(&threadlistlock);
1668 * These are local overrides for various environment variables in Emacs.
1669 * Please do not remove this and leave it at the end of the file, where
1670 * Emacs will automagically detect them.
1671 * ---------------------------------------------------------------------
1674 * indent-tabs-mode: t
1678 * vim:noexpandtab:sw=4:ts=4: