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 4921 2006-05-15 14:24:36Z 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 fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
328 errno, strerror(errno));
333 /* threads_sem_wait ************************************************************
335 Wait for a semaphore, non-interruptible.
337 IMPORTANT: Always use this function instead of `sem_wait` directly, as
338 `sem_wait` may be interrupted by signals!
341 sem..............the semaphore to wait on
343 *******************************************************************************/
345 void threads_sem_wait(sem_t *sem)
355 } while (errno == EINTR);
357 fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
358 errno, strerror(errno));
363 /* threads_sem_post ************************************************************
365 Increase the count of a semaphore. Checks for errors.
368 sem..............the semaphore to increase the count of
370 *******************************************************************************/
372 void threads_sem_post(sem_t *sem)
378 /* unlike sem_wait, sem_post is not interruptible */
384 fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
385 errno, strerror(errno));
390 /* threads_set_thread_priority *************************************************
392 Set the priority of the given thread.
395 tid..........thread id
396 priority.....priority to set
398 ******************************************************************************/
400 static void threads_set_thread_priority(pthread_t tid, int priority)
402 struct sched_param schedp;
405 pthread_getschedparam(tid, &policy, &schedp);
406 schedp.sched_priority = priority;
407 pthread_setschedparam(tid, policy, &schedp);
411 /* compiler_lock ***************************************************************
413 Enter the compiler lock.
415 ******************************************************************************/
417 void compiler_lock(void)
419 pthread_mutex_lock_rec(&compiler_mutex);
423 /* compiler_unlock *************************************************************
425 Release the compiler lock.
427 ******************************************************************************/
429 void compiler_unlock(void)
431 pthread_mutex_unlock_rec(&compiler_mutex);
435 /* lock_stopworld **************************************************************
437 Enter the stopworld lock, specifying why the world shall be stopped.
440 where........ STOPWORLD_FROM_GC (1) from within GC
441 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
443 ******************************************************************************/
445 void lock_stopworld(int where)
447 pthread_mutex_lock(&stopworldlock);
448 stopworldwhere = where;
452 /* unlock_stopworld ************************************************************
454 Release the stopworld lock.
456 ******************************************************************************/
458 void unlock_stopworld(void)
461 pthread_mutex_unlock(&stopworldlock);
464 #if !defined(__DARWIN__)
465 /* Caller must hold threadlistlock */
466 static int threads_cast_sendsignals(int sig, int count)
469 threadobject *tobj = mainthreadobj;
470 threadobject *self = THREADOBJECT;
476 } while (tobj != mainthreadobj);
479 assert(tobj == mainthreadobj);
483 pthread_kill(tobj->tid, sig);
485 } while (tobj != mainthreadobj);
492 static void threads_cast_darwinstop(void)
494 threadobject *tobj = mainthreadobj;
495 threadobject *self = THREADOBJECT;
500 thread_state_flavor_t flavor = PPC_THREAD_STATE;
501 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
502 ppc_thread_state_t thread_state;
503 mach_port_t thread = tobj->mach_thread;
506 r = thread_suspend(thread);
507 if (r != KERN_SUCCESS) {
508 log_text("thread_suspend failed");
512 r = thread_get_state(thread, flavor,
513 (natural_t*)&thread_state, &thread_state_count);
514 if (r != KERN_SUCCESS) {
515 log_text("thread_get_state failed");
519 thread_restartcriticalsection(&thread_state);
521 r = thread_set_state(thread, flavor,
522 (natural_t*)&thread_state, thread_state_count);
523 if (r != KERN_SUCCESS) {
524 log_text("thread_set_state failed");
529 } while (tobj != mainthreadobj);
532 static void threads_cast_darwinresume(void)
534 threadobject *tobj = mainthreadobj;
535 threadobject *self = THREADOBJECT;
540 mach_port_t thread = tobj->mach_thread;
543 r = thread_resume(thread);
544 if (r != KERN_SUCCESS) {
545 log_text("thread_resume failed");
550 } while (tobj != mainthreadobj);
555 #if defined(__MIPS__)
556 static void threads_cast_irixresume(void)
558 pthread_mutex_lock(&suspend_ack_lock);
559 pthread_cond_broadcast(&suspend_cond);
560 pthread_mutex_unlock(&suspend_ack_lock);
564 void threads_cast_stopworld(void)
567 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
568 pthread_mutex_lock(&threadlistlock);
569 #if defined(__DARWIN__)
570 threads_cast_darwinstop();
572 count = threads_cast_sendsignals(GC_signum1(), 0);
573 for (i=0; i<count; i++)
574 threads_sem_wait(&suspend_ack);
576 pthread_mutex_unlock(&threadlistlock);
579 void threads_cast_startworld(void)
581 pthread_mutex_lock(&threadlistlock);
582 #if defined(__DARWIN__)
583 threads_cast_darwinresume();
584 #elif defined(__MIPS__)
585 threads_cast_irixresume();
587 threads_cast_sendsignals(GC_signum2(), -1);
589 pthread_mutex_unlock(&threadlistlock);
593 #if !defined(__DARWIN__)
594 static void threads_sigsuspend_handler(ucontext_t *ctx)
599 /* XXX TWISTI: this is just a quick hack */
600 #if defined(ENABLE_JIT)
601 thread_restartcriticalsection(ctx);
604 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
605 (not POSIX async-safe). */
606 #if defined(__IRIX__)
607 pthread_mutex_lock(&suspend_ack_lock);
608 threads_sem_post(&suspend_ack);
609 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
610 pthread_mutex_unlock(&suspend_ack_lock);
612 threads_sem_post(&suspend_ack);
616 sigdelset(&sigs, sig);
621 /* This function is called from Boehm GC code. */
623 int cacao_suspendhandler(ucontext_t *ctx)
625 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
628 threads_sigsuspend_handler(ctx);
634 /* threads_set_current_threadobject ********************************************
636 Set the current thread object.
639 thread.......the thread object to set
641 *******************************************************************************/
643 #if !defined(ENABLE_JVMTI)
644 static void threads_set_current_threadobject(threadobject *thread)
646 void threads_set_current_threadobject(threadobject *thread)
649 #if !defined(HAVE___THREAD)
650 pthread_setspecific(threads_current_threadobject_key, thread);
652 threads_current_threadobject = thread;
657 /* threads_get_current_threadobject ********************************************
659 Return the threadobject of the current thread.
662 the current threadobject * (an instance of java.lang.VMThread)
664 *******************************************************************************/
666 threadobject *threads_get_current_threadobject(void)
672 /* threads_preinit *************************************************************
674 Do some early initialization of stuff required.
676 *******************************************************************************/
678 void threads_preinit(void)
681 pthread_mutexattr_t mutexattr;
682 pthread_mutexattr_init(&mutexattr);
683 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
684 pthread_mutex_init(&compiler_mutex, &mutexattr);
685 pthread_mutexattr_destroy(&mutexattr);
687 pthread_mutex_init_rec(&compiler_mutex);
690 pthread_mutex_init(&threadlistlock, NULL);
691 pthread_mutex_init(&stopworldlock, NULL);
693 /* Allocate something so the garbage collector's signal handlers
695 heap_allocate(1, false, NULL);
697 mainthreadobj = NEW(threadobject);
698 mainthreadobj->tid = pthread_self();
699 mainthreadobj->index = 1;
700 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
702 #if !defined(HAVE___THREAD)
703 pthread_key_create(&threads_current_threadobject_key, NULL);
705 threads_set_current_threadobject(mainthreadobj);
707 threads_sem_init(&suspend_ack, 0, 0);
709 /* initialize the threads table */
711 threads_table_init();
713 /* initialize subsystems */
721 /* threads_init ****************************************************************
723 Initializes the threads required by the JVM: main, finalizer.
725 *******************************************************************************/
727 bool threads_init(void)
729 java_lang_String *threadname;
730 java_lang_Thread *mainthread;
731 java_lang_ThreadGroup *threadgroup;
732 threadobject *tempthread;
735 tempthread = mainthreadobj;
737 /* XXX We have to find a new way to free lock records */
738 /* with the new locking algorithm. */
739 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
741 /* This is kinda tricky, we grow the java.lang.Thread object so we
742 can keep the execution environment there. No Thread object must
743 have been created at an earlier time. */
745 class_java_lang_VMThread->instancesize = sizeof(threadobject);
747 /* create a VMThread */
749 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
754 FREE(tempthread, threadobject);
756 threads_init_threadobject(&mainthreadobj->o);
758 threads_set_current_threadobject(mainthreadobj);
760 lock_init_execution_env(mainthreadobj);
762 mainthreadobj->next = mainthreadobj;
763 mainthreadobj->prev = mainthreadobj;
765 threads_table_add(mainthreadobj);
767 #if defined(ENABLE_INTRP)
768 /* create interpreter stack */
771 MSET(intrp_main_stack, 0, u1, opt_stacksize);
772 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
776 threadname = javastring_new(utf_new_char("main"));
778 /* allocate and init ThreadGroup */
780 threadgroup = (java_lang_ThreadGroup *)
781 native_new_and_init(class_java_lang_ThreadGroup);
784 throw_exception_exit();
786 /* create a Thread */
788 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
791 throw_exception_exit();
793 mainthreadobj->o.thread = mainthread;
795 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
797 method = class_resolveclassmethod(class_java_lang_Thread,
799 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
800 class_java_lang_Thread,
806 (void) vm_call_method(method, (java_objectheader *) mainthread,
807 mainthreadobj, threadname, 5, false);
812 mainthread->group = threadgroup;
814 /* add mainthread to ThreadGroup */
816 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
817 utf_new_char("addThread"),
818 utf_new_char("(Ljava/lang/Thread;)V"),
819 class_java_lang_ThreadGroup,
825 (void) vm_call_method(method, (java_objectheader *) threadgroup,
831 threads_set_thread_priority(pthread_self(), 5);
833 pthread_attr_init(&threadattr);
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 startupinfo startup;
1156 threadobject *thread;
1158 thread = (threadobject *) t->vmThread;
1160 /* fill startupinfo structure passed by pthread_create to
1161 * threads_startup_thread */
1163 startup.thread = thread;
1164 startup.function = function; /* maybe we don't call Thread.run()V */
1165 startup.psem = &sem;
1166 startup.psem_first = &sem_first;
1168 threads_sem_init(&sem, 0, 0);
1169 threads_sem_init(&sem_first, 0, 0);
1171 /* create the thread */
1173 if (pthread_create(&thread->tid, &threadattr, threads_startup_thread,
1175 log_text("pthread_create failed");
1179 /* signal that pthread_create has returned, so thread->tid is valid */
1181 threads_sem_post(&sem_first);
1183 /* wait here until the thread has entered itself into the thread list */
1185 threads_sem_wait(&sem);
1190 sem_destroy(&sem_first);
1194 /* threads_find_non_daemon_thread **********************************************
1196 Helper function used by threads_join_all_threads for finding non-daemon threads
1197 that are still running.
1199 *******************************************************************************/
1201 /* At the end of the program, we wait for all running non-daemon threads to die
1204 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1206 while (thread != mainthreadobj) {
1207 if (!thread->o.thread->daemon)
1209 thread = thread->prev;
1216 /* threads_join_all_threads ****************************************************
1218 Join all non-daemon threads.
1220 *******************************************************************************/
1222 void threads_join_all_threads(void)
1224 threadobject *thread;
1226 pthread_mutex_lock(&threadlistlock);
1228 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1230 pthread_mutex_lock(&thread->joinmutex);
1232 pthread_mutex_unlock(&threadlistlock);
1235 pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1237 pthread_mutex_unlock(&thread->joinmutex);
1239 pthread_mutex_lock(&threadlistlock);
1242 pthread_mutex_unlock(&threadlistlock);
1246 /* threads_timespec_earlier ****************************************************
1248 Return true if timespec tv1 is earlier than timespec tv2.
1251 tv1..........first timespec
1252 tv2..........second timespec
1255 true, if the first timespec is earlier
1257 *******************************************************************************/
1259 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1260 const struct timespec *tv2)
1262 return (tv1->tv_sec < tv2->tv_sec)
1264 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1268 /* threads_current_time_is_earlier_than ****************************************
1270 Check if the current time is earlier than the given timespec.
1273 tv...........the timespec to compare against
1276 true, if the current time is earlier
1278 *******************************************************************************/
1280 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1282 struct timeval tvnow;
1283 struct timespec tsnow;
1285 /* get current time */
1287 if (gettimeofday(&tvnow, NULL) != 0) {
1288 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1289 errno, strerror(errno));
1293 /* convert it to a timespec */
1295 tsnow.tv_sec = tvnow.tv_sec;
1296 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1298 /* compare current time with the given timespec */
1300 return threads_timespec_earlier(&tsnow, tv);
1304 /* threads_wait_with_timeout ***************************************************
1306 Wait until the given point in time on a monitor until either
1307 we are notified, we are interrupted, or the time is up.
1310 t............the current thread
1311 wakeupTime...absolute (latest) wakeup time
1312 If both tv_sec and tv_nsec are zero, this function
1313 waits for an unlimited amount of time.
1316 true.........if the wait has been interrupted,
1317 false........if the wait was ended by notification or timeout
1319 *******************************************************************************/
1321 static bool threads_wait_with_timeout(threadobject *t,
1322 struct timespec *wakeupTime)
1324 bool wasinterrupted;
1326 /* acquire the waitmutex */
1328 pthread_mutex_lock(&t->waitmutex);
1330 /* mark us as sleeping */
1334 /* wait on waitcond */
1336 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1338 while (!t->interrupted && !t->signaled
1339 && threads_current_time_is_earlier_than(wakeupTime))
1341 pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1346 while (!t->interrupted && !t->signaled)
1347 pthread_cond_wait(&t->waitcond, &t->waitmutex);
1350 /* check if we were interrupted */
1352 wasinterrupted = t->interrupted;
1354 /* reset all flags */
1356 t->interrupted = false;
1357 t->signaled = false;
1358 t->sleeping = false;
1360 /* release the waitmutex */
1362 pthread_mutex_unlock(&t->waitmutex);
1364 return wasinterrupted;
1368 /* threads_wait_with_timeout_relative ******************************************
1370 Wait for the given maximum amount of time on a monitor until either
1371 we are notified, we are interrupted, or the time is up.
1374 t............the current thread
1375 millis.......milliseconds to wait
1376 nanos........nanoseconds to wait
1379 true.........if the wait has been interrupted,
1380 false........if the wait was ended by notification or timeout
1382 *******************************************************************************/
1384 bool threads_wait_with_timeout_relative(threadobject *t,
1388 struct timespec wakeupTime;
1390 /* calculate the the (latest) wakeup time */
1392 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1396 return threads_wait_with_timeout(t, &wakeupTime);
1400 /* threads_calc_absolute_time **************************************************
1402 Calculate the absolute point in time a given number of ms and ns from now.
1405 millis............milliseconds from now
1406 nanos.............nanoseconds from now
1409 *tm...............receives the timespec of the absolute point in time
1411 *******************************************************************************/
1413 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1415 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1418 gettimeofday(&tv, NULL);
1419 tv.tv_sec += millis / 1000;
1421 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1422 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1423 tm->tv_nsec = nsec % 1000000000;
1432 /* threads_interrupt_thread ****************************************************
1434 Interrupt the given thread.
1436 The thread gets the "waitcond" signal and
1437 its interrupted flag is set to true.
1440 thread............the thread to interrupt
1442 *******************************************************************************/
1444 void threads_interrupt_thread(java_lang_VMThread *thread)
1446 threadobject *t = (threadobject*) thread;
1448 /* signal the thread a "waitcond" and tell it that it has been */
1451 pthread_mutex_lock(&t->waitmutex);
1453 pthread_cond_signal(&t->waitcond);
1454 t->interrupted = true;
1455 pthread_mutex_unlock(&t->waitmutex);
1459 /* threads_check_if_interrupted_and_reset **************************************
1461 Check if the current thread has been interrupted and reset the
1465 true, if the current thread had been interrupted
1467 *******************************************************************************/
1469 bool threads_check_if_interrupted_and_reset(void)
1474 t = (threadobject*) THREADOBJECT;
1476 intr = t->interrupted;
1478 t->interrupted = false;
1484 /* threads_thread_has_been_interrupted *********************************************************
1486 Check if the given thread has been interrupted
1489 t............the thread to check
1492 true, if the given thread had been interrupted
1494 *******************************************************************************/
1496 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1500 t = (threadobject*) thread;
1502 return t->interrupted;
1506 /* threads_sleep ***************************************************************
1508 Sleep the current thread for the specified amount of time.
1510 *******************************************************************************/
1512 void threads_sleep(s8 millis, s4 nanos)
1515 struct timespec wakeupTime;
1516 bool wasinterrupted;
1518 t = (threadobject *) THREADOBJECT;
1520 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1522 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1525 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1529 /* threads_yield *****************************************************************
1531 Yield to the scheduler.
1533 *******************************************************************************/
1535 void threads_yield(void)
1541 /* threads_java_lang_Thread_set_priority ***********************************************************
1543 Set the priority for the given java.lang.Thread.
1546 t............the java.lang.Thread
1547 priority.....the priority
1549 *******************************************************************************/
1551 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1553 threadobject *thread;
1555 thread = (threadobject*) t->vmThread;
1557 threads_set_thread_priority(thread->tid, priority);
1561 /* threads_dump ****************************************************************
1563 Dumps info for all threads running in the JVM. This function is
1564 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1566 *******************************************************************************/
1568 void threads_dump(void)
1571 java_lang_VMThread *vmt;
1572 java_lang_Thread *t;
1575 tobj = mainthreadobj;
1577 printf("Full thread dump CACAO "VERSION":\n");
1579 /* iterate over all started threads */
1582 /* get thread objects */
1587 /* the thread may be currently in initalization, don't print it */
1590 /* get thread name */
1592 name = javastring_toutf(t->name, false);
1595 utf_display_printable_ascii(name);
1601 #if SIZEOF_VOID_P == 8
1602 printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1604 printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1607 /* send SIGUSR1 to thread to print stacktrace */
1609 pthread_kill(tobj->tid, SIGUSR1);
1611 /* sleep this thread a bit, so the signal can reach the thread */
1613 threads_sleep(10, 0);
1617 } while (tobj && (tobj != mainthreadobj));
1621 /* threads_table_dump *********************************************************
1623 Dump the threads table for debugging purposes.
1626 file..............stream to write to
1628 ******************************************************************************/
1630 #if !defined(NDEBUG)
1631 static void threads_table_dump(FILE *file)
1637 pthread_mutex_lock(&threadlistlock);
1639 size = threads_table.size;
1641 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1643 for (i=0; i<size; ++i) {
1644 index = threads_table.table[i].nextfree;
1646 fprintf(file, "%4d: ", i);
1649 fprintf(file, "free, nextfree = %d\n", index);
1652 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1656 fprintf(file, "======== END OF THREADS TABLE ========\n");
1658 pthread_mutex_unlock(&threadlistlock);
1663 * These are local overrides for various environment variables in Emacs.
1664 * Please do not remove this and leave it at the end of the file, where
1665 * Emacs will automagically detect them.
1666 * ---------------------------------------------------------------------
1669 * indent-tabs-mode: t
1673 * vim:noexpandtab:sw=4:ts=4: