1 /* src/threads/native/threads.c - native threads support
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
29 Changes: Christian Thalinger
31 $Id: threads.c 3570 2005-11-04 16:58:36Z motse $
39 #include <sys/types.h>
47 #include <semaphore.h>
52 #ifndef USE_MD_THREAD_STUFF
53 #include "machine-instr.h"
55 #include "threads/native/generic-primitives.h"
58 #include "cacao/cacao.h"
60 #include "mm/memory.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Object.h"
63 #include "native/include/java_lang_Throwable.h"
64 #include "native/include/java_lang_Thread.h"
65 #include "native/include/java_lang_ThreadGroup.h"
66 #include "native/include/java_lang_VMThread.h"
67 #include "threads/native/threads.h"
68 #include "toolbox/avl.h"
69 #include "toolbox/logging.h"
70 #include "vm/builtin.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/loader.h"
74 #include "vm/options.h"
75 #include "vm/stringlocal.h"
76 #include "vm/tables.h"
77 #include "vm/jit/asmpart.h"
79 #if !defined(__DARWIN__)
80 #if defined(__LINUX__)
81 #define GC_LINUX_THREADS
82 #elif defined(__MIPS__)
83 #define GC_IRIX_THREADS
85 #include "boehm-gc/include/gc.h"
88 #ifdef USE_MD_THREAD_STUFF
89 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
90 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
91 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
96 /* We need this for older MacOSX (10.1.x) */
99 pthread_mutex_t mutex;
102 } pthread_mutex_rec_t;
104 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
106 pthread_mutex_init(&m->mutex, NULL);
110 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
112 pthread_mutex_destroy(&m->mutex);
115 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
120 pthread_mutex_lock(&m->mutex);
121 m->owner = pthread_self();
125 if (m->owner != pthread_self())
126 pthread_mutex_lock(&m->mutex);
135 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
138 pthread_mutex_unlock(&m->mutex);
143 #define pthread_mutex_lock_rec pthread_mutex_lock
144 #define pthread_mutex_unlock_rec pthread_mutex_unlock
145 #define pthread_mutex_rec_t pthread_mutex_t
147 #endif /* MUTEXSIM */
149 static void setPriority(pthread_t tid, int priority)
151 struct sched_param schedp;
154 pthread_getschedparam(tid, &policy, &schedp);
155 schedp.sched_priority = priority;
156 pthread_setschedparam(tid, policy, &schedp);
160 static struct avl_table *criticaltree;
161 threadobject *mainthreadobj;
163 #ifndef HAVE___THREAD
164 pthread_key_t tkey_threadinfo;
166 __thread threadobject *threadobj;
169 static pthread_mutex_rec_t compiler_mutex;
170 static pthread_mutex_rec_t tablelock;
174 pthread_mutex_lock_rec(&compiler_mutex);
177 void compiler_unlock()
179 pthread_mutex_unlock_rec(&compiler_mutex);
184 pthread_mutex_lock_rec(&tablelock);
189 pthread_mutex_unlock_rec(&tablelock);
192 static int criticalcompare(const void *pa, const void *pb, void *param)
194 const threadcritnode *na = pa;
195 const threadcritnode *nb = pb;
197 if (na->mcodebegin < nb->mcodebegin)
199 if (na->mcodebegin > nb->mcodebegin)
204 static const threadcritnode *findcritical(u1 *mcodeptr)
206 struct avl_node *n = criticaltree->avl_root;
207 const threadcritnode *m = NULL;
212 const threadcritnode *d = n->avl_data;
213 if (mcodeptr == d->mcodebegin)
215 if (mcodeptr < d->mcodebegin) {
221 if (n->avl_link[1]) {
230 void thread_registercritical(threadcritnode *n)
232 avl_insert(criticaltree, n);
235 u1 *thread_checkcritical(u1 *mcodeptr)
237 const threadcritnode *n = findcritical(mcodeptr);
238 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
241 static void thread_addstaticcritical()
243 threadcritnode *n = &asm_criticalsections;
245 while (n->mcodebegin)
246 thread_registercritical(n++);
249 static pthread_mutex_t threadlistlock;
251 static pthread_mutex_t stopworldlock;
252 volatile int stopworldwhere;
254 static sem_t suspend_ack;
255 #if defined(__MIPS__)
256 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
257 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
261 * where - 1 from within GC
264 void lock_stopworld(int where)
266 pthread_mutex_lock(&stopworldlock);
267 stopworldwhere = where;
270 void unlock_stopworld()
273 pthread_mutex_unlock(&stopworldlock);
276 #if !defined(__DARWIN__)
277 /* Caller must hold threadlistlock */
278 static int cast_sendsignals(int sig, int count)
281 threadobject *tobj = mainthreadobj;
282 nativethread *infoself = THREADINFO;
287 tobj = tobj->info.next;
288 } while (tobj != mainthreadobj);
291 nativethread *info = &tobj->info;
292 if (info != infoself)
293 pthread_kill(info->tid, sig);
294 tobj = tobj->info.next;
295 } while (tobj != mainthreadobj);
302 static void cast_darwinstop()
304 threadobject *tobj = mainthreadobj;
305 nativethread *infoself = THREADINFO;
308 nativethread *info = &tobj->info;
309 if (info != infoself)
311 thread_state_flavor_t flavor = PPC_THREAD_STATE;
312 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
313 ppc_thread_state_t thread_state;
314 mach_port_t thread = info->mach_thread;
317 r = thread_suspend(thread);
318 if (r != KERN_SUCCESS) {
319 log_text("thread_suspend failed");
323 r = thread_get_state(thread, flavor,
324 (natural_t*)&thread_state, &thread_state_count);
325 if (r != KERN_SUCCESS) {
326 log_text("thread_get_state failed");
330 thread_restartcriticalsection(&thread_state);
332 r = thread_set_state(thread, flavor,
333 (natural_t*)&thread_state, thread_state_count);
334 if (r != KERN_SUCCESS) {
335 log_text("thread_set_state failed");
339 tobj = tobj->info.next;
340 } while (tobj != mainthreadobj);
343 static void cast_darwinresume()
345 threadobject *tobj = mainthreadobj;
346 nativethread *infoself = THREADINFO;
349 nativethread *info = &tobj->info;
350 if (info != infoself)
352 mach_port_t thread = info->mach_thread;
355 r = thread_resume(thread);
356 if (r != KERN_SUCCESS) {
357 log_text("thread_resume failed");
361 tobj = tobj->info.next;
362 } while (tobj != mainthreadobj);
367 #if defined(__MIPS__)
368 static void cast_irixresume()
370 pthread_mutex_lock(&suspend_ack_lock);
371 pthread_cond_broadcast(&suspend_cond);
372 pthread_mutex_unlock(&suspend_ack_lock);
376 void cast_stopworld()
380 pthread_mutex_lock(&threadlistlock);
381 #if defined(__DARWIN__)
384 count = cast_sendsignals(GC_signum1(), 0);
385 for (i=0; i<count; i++)
386 sem_wait(&suspend_ack);
388 pthread_mutex_unlock(&threadlistlock);
391 void cast_startworld()
393 pthread_mutex_lock(&threadlistlock);
394 #if defined(__DARWIN__)
396 #elif defined(__MIPS__)
399 cast_sendsignals(GC_signum2(), -1);
401 pthread_mutex_unlock(&threadlistlock);
405 #if !defined(__DARWIN__)
406 static void sigsuspend_handler(ucontext_t *ctx)
411 thread_restartcriticalsection(ctx);
413 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
414 (not POSIX async-safe). */
415 #if defined(__IRIX__)
416 pthread_mutex_lock(&suspend_ack_lock);
417 sem_post(&suspend_ack);
418 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
419 pthread_mutex_unlock(&suspend_ack_lock);
421 sem_post(&suspend_ack);
425 sigdelset(&sigs, sig);
430 int cacao_suspendhandler(ucontext_t *ctx)
432 if (stopworldwhere != 2)
435 sigsuspend_handler(ctx);
440 static void setthreadobject(threadobject *thread)
442 #if !defined(HAVE___THREAD)
443 pthread_setspecific(tkey_threadinfo, thread);
450 /* thread_setself **************************************************************
454 *******************************************************************************/
456 void *thread_getself(void)
458 return pthread_getspecific(tkey_threadinfo);
462 static monitorLockRecord *dummyLR;
464 static void initPools();
467 /* thread_preinit **************************************************************
469 Do some early initialization of stuff required.
471 *******************************************************************************/
473 void threads_preinit(void)
476 pthread_mutexattr_t mutexattr;
477 pthread_mutexattr_init(&mutexattr);
478 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
479 pthread_mutex_init(&compiler_mutex, &mutexattr);
480 pthread_mutex_init(&tablelock, &mutexattr);
481 pthread_mutexattr_destroy(&mutexattr);
483 pthread_mutex_init_rec(&compiler_mutex);
484 pthread_mutex_init_rec(&tablelock);
487 pthread_mutex_init(&threadlistlock, NULL);
488 pthread_mutex_init(&stopworldlock, NULL);
490 /* Allocate something so the garbage collector's signal handlers
492 heap_allocate(1, false, NULL);
494 mainthreadobj = NEW(threadobject);
495 mainthreadobj->info.tid = pthread_self();
496 #if !defined(HAVE___THREAD)
497 pthread_key_create(&tkey_threadinfo, NULL);
499 setthreadobject(mainthreadobj);
502 criticaltree = avl_create(criticalcompare, NULL, NULL);
503 thread_addstaticcritical();
504 sem_init(&suspend_ack, 0, 0);
506 /* Every newly created object's monitorPtr points here so we save
507 a check against NULL */
508 dummyLR = NEW(monitorLockRecord);
510 dummyLR->ownerThread = NULL;
511 dummyLR->waiting = false;
514 static pthread_attr_t threadattr;
516 static void freeLockRecordPools(lockRecordPool *);
519 /* threads_init ****************************************************************
521 Initializes the threads required by the JVM: main, finalizer.
523 *******************************************************************************/
525 bool threads_init(u1 *stackbottom)
527 java_lang_String *threadname;
528 java_lang_Thread *mainthread;
529 java_lang_ThreadGroup *threadgroup;
530 threadobject *tempthread;
533 tempthread = mainthreadobj;
535 freeLockRecordPools(mainthreadobj->ee.lrpool);
537 /* This is kinda tricky, we grow the java.lang.Thread object so we
538 can keep the execution environment there. No Thread object must
539 have been created at an earlier time. */
541 class_java_lang_VMThread->instancesize = sizeof(threadobject);
543 /* create a VMThread */
545 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
550 FREE(tempthread, threadobject);
552 initThread(&mainthreadobj->o);
554 setthreadobject(mainthreadobj);
558 mainthreadobj->info.next = mainthreadobj;
559 mainthreadobj->info.prev = mainthreadobj;
561 #if defined(ENABLE_INTRP)
562 /* create interpreter stack */
565 MSET(intrp_main_stack, 0, u1, opt_stacksize);
566 mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
570 threadname = javastring_new(utf_new_char("main"));
572 /* allocate and init ThreadGroup */
574 threadgroup = (java_lang_ThreadGroup *)
575 native_new_and_init(class_java_lang_ThreadGroup);
578 throw_exception_exit();
580 /* create a Thread */
582 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
585 throw_exception_exit();
587 mainthreadobj->o.thread = mainthread;
589 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
591 method = class_resolveclassmethod(class_java_lang_Thread,
593 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
594 class_java_lang_Thread,
600 asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
604 mainthread->group = threadgroup;
605 /* XXX This is a hack because the fourth argument was omitted */
606 mainthread->daemon = false;
608 /* add mainthread to ThreadGroup */
610 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
611 utf_new_char("addThread"),
612 utf_new_char("(Ljava/lang/Thread;)V"),
613 class_java_lang_ThreadGroup,
619 asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
624 setPriority(pthread_self(), 5);
626 pthread_attr_init(&threadattr);
627 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
629 /* everything's ok */
635 void initThread(java_lang_VMThread *t)
637 threadobject *thread = (threadobject*) t;
638 nativethread *info = &thread->info;
639 info->tid = pthread_self();
640 /* TODO destroy all those things */
641 pthread_mutex_init(&info->joinMutex, NULL);
642 pthread_cond_init(&info->joinCond, NULL);
644 pthread_mutex_init(&thread->waitLock, NULL);
645 pthread_cond_init(&thread->waitCond, NULL);
646 thread->interrupted = false;
647 thread->signaled = false;
648 thread->isSleeping = false;
651 static void initThreadLocks(threadobject *);
655 threadobject *thread;
656 functionptr function;
662 /* threads_startup *************************************************************
664 Thread startup function called by pthread_create.
666 ******************************************************************************/
668 static void *threads_startup_thread(void *t)
670 startupinfo *startup;
671 threadobject *thread;
676 functionptr function;
678 #if defined(ENABLE_INTRP)
679 u1 *intrp_thread_stack;
681 /* create interpreter stack */
684 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
685 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
689 /* get passed startupinfo structure and the values in there */
693 thread = startup->thread;
694 function = startup->function;
695 psem = startup->psem;
697 info = &thread->info;
699 /* Seems like we've encountered a situation where info->tid was not set by
700 * pthread_create. We alleviate this problem by waiting for pthread_create
702 sem_wait(startup->psem_first);
705 #if defined(__DARWIN__)
706 info->mach_thread = mach_thread_self();
708 setthreadobject(thread);
710 /* insert the thread into the threadlist */
712 pthread_mutex_lock(&threadlistlock);
714 info->prev = mainthreadobj;
715 info->next = tnext = mainthreadobj->info.next;
716 mainthreadobj->info.next = thread;
717 tnext->info.prev = thread;
719 pthread_mutex_unlock(&threadlistlock);
721 initThreadLocks(thread);
726 setPriority(info->tid, thread->o.thread->priority);
728 #if defined(ENABLE_INTRP)
729 /* set interpreter stack */
732 THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
735 /* find and run the Thread.run()V method if no other function was passed */
737 if (function == NULL) {
738 method = class_resolveclassmethod(thread->o.header.vftbl->class,
741 thread->o.header.vftbl->class,
747 asm_calljavafunction(method, thread, NULL, NULL, NULL);
750 /* call passed function, e.g. finalizer_thread */
755 /* Allow lock record pools to be used by other threads. They
756 cannot be deleted so we'd better not waste them. */
758 freeLockRecordPools(thread->ee.lrpool);
760 /* remove thread from thread list, do this inside a lock */
762 pthread_mutex_lock(&threadlistlock);
763 info->next->info.prev = info->prev;
764 info->prev->info.next = info->next;
765 pthread_mutex_unlock(&threadlistlock);
767 /* reset thread id (lock on joinMutex? TWISTI) */
769 pthread_mutex_lock(&info->joinMutex);
771 pthread_mutex_unlock(&info->joinMutex);
773 pthread_cond_broadcast(&info->joinCond);
779 /* threads_start_thread ********************************************************
781 Start a thread in the JVM.
783 ******************************************************************************/
785 void threads_start_thread(thread *t, functionptr function)
792 info = &((threadobject *) t->vmThread)->info;
794 /* fill startupinfo structure passed by pthread_create to XXX */
796 startup.thread = (threadobject*) t->vmThread;
797 startup.function = function; /* maybe we don't call Thread.run()V */
799 startup.psem_first = &sem_first;
801 sem_init(&sem, 0, 0);
802 sem_init(&sem_first, 0, 0);
804 if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
806 log_text("pthread_create failed");
810 sem_post(&sem_first);
812 /* wait here until the thread has entered itself into the thread list */
816 sem_destroy(&sem_first);
820 /* At the end of the program, we wait for all running non-daemon threads to die
823 static threadobject *findNonDaemon(threadobject *thread)
825 while (thread != mainthreadobj) {
826 if (!thread->o.thread->daemon)
828 thread = thread->info.prev;
834 void joinAllThreads()
836 threadobject *thread;
837 pthread_mutex_lock(&threadlistlock);
838 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
839 nativethread *info = &thread->info;
840 pthread_mutex_lock(&info->joinMutex);
841 pthread_mutex_unlock(&threadlistlock);
843 pthread_cond_wait(&info->joinCond, &info->joinMutex);
844 pthread_mutex_unlock(&info->joinMutex);
845 pthread_mutex_lock(&threadlistlock);
847 pthread_mutex_unlock(&threadlistlock);
850 static void initLockRecord(monitorLockRecord *r, threadobject *t)
857 r->incharge = (monitorLockRecord *) &dummyLR;
859 sem_init(&r->queueSem, 0, 0);
860 pthread_mutex_init(&r->resolveLock, NULL);
861 pthread_cond_init(&r->resolveWait, NULL);
864 /* No lock record must ever be destroyed because there may still be references
867 static void destroyLockRecord(monitorLockRecord *r)
869 sem_destroy(&r->queueSem);
870 pthread_mutex_destroy(&r->resolveLock);
871 pthread_cond_destroy(&r->resolveWait);
877 initThreadLocks(mainthreadobj);
880 static void initThreadLocks(threadobject *thread)
882 thread->ee.firstLR = NULL;
883 thread->ee.lrpool = NULL;
884 thread->ee.numlr = 0;
887 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
889 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
892 p->header.size = size;
893 for (i=0; i<size; i++) {
894 initLockRecord(&p->lr[i], thread);
895 p->lr[i].nextFree = &p->lr[i+1];
897 p->lr[i-1].nextFree = NULL;
901 #define INITIALLOCKRECORDS 8
903 pthread_mutex_t pool_lock;
904 lockRecordPool *global_pool;
906 static void initPools()
908 pthread_mutex_init(&pool_lock, NULL);
911 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
913 pthread_mutex_lock(&pool_lock);
916 lockRecordPool *pool = global_pool;
917 global_pool = pool->header.next;
918 pthread_mutex_unlock(&pool_lock);
920 for (i=0; i < pool->header.size; i++)
921 pool->lr[i].ownerThread = t;
925 pthread_mutex_unlock(&pool_lock);
927 return allocNewLockRecordPool(t, size);
930 static void freeLockRecordPools(lockRecordPool *pool)
932 lockRecordPoolHeader *last;
933 pthread_mutex_lock(&pool_lock);
934 last = &pool->header;
936 last = &last->next->header;
937 last->next = global_pool;
939 pthread_mutex_unlock(&pool_lock);
942 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
944 monitorLockRecord *r = t->ee.firstLR;
947 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
948 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
949 pool->header.next = t->ee.lrpool;
952 t->ee.numlr += pool->header.size;
955 t->ee.firstLR = r->nextFree;
959 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
961 r->nextFree = t->ee.firstLR;
965 void initObjectLock(java_objectheader *o)
967 o->monitorPtr = dummyLR;
971 /* get_dummyLR *****************************************************************
973 Returns the global dummy monitor lock record. The pointer is
974 required in the code generator to set up a virtual
975 java_objectheader for code patch locking.
977 *******************************************************************************/
979 monitorLockRecord *get_dummyLR(void)
985 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
987 atomic_add(&lr->queuers, 1);
989 MEMORY_BARRIER_AFTER_ATOMIC();
992 sem_wait(&lr->queueSem);
994 atomic_add(&lr->queuers, -1);
997 static void freeLockRecord(monitorLockRecord *lr)
1004 sem_post(&lr->queueSem);
1007 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
1013 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
1016 monitorLockRecord *lr = o->monitorPtr;
1018 monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
1022 nlr = o->monitorPtr;
1024 handleWaiter(mlr, lr);
1028 if (lr->ownerThread != t)
1030 MEMORY_BARRIER_BEFORE_ATOMIC();
1031 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
1034 if (mlr == lr || lr->o != o) {
1035 handleWaiter(mlr, lr);
1039 queueOnLockRecord(lr, o);
1040 handleWaiter(mlr, lr);
1043 freeLockRecord(mlr);
1044 recycleLockRecord(t, mlr);
1045 queueOnLockRecord(nlr, o);
1047 if (lr->ownerThread == t) {
1051 queueOnLockRecord(lr, o);
1056 static void wakeWaiters(monitorLockRecord *lr)
1058 monitorLockRecord *tmplr;
1061 /* assign lock record to a temporary variable */
1069 sem_post(&tmplr->queueSem);
1071 tmplr = tmplr->waiter;
1072 } while (tmplr != NULL && tmplr != lr);
1075 #define GRAB_LR(lr,t) \
1076 if (lr->ownerThread != t) { \
1077 lr = lr->incharge; \
1080 #define CHECK_MONITORSTATE(lr,t,mo,a) \
1081 if (lr == NULL || lr->o != mo || lr->ownerThread != t) { \
1082 *exceptionptr = new_illegalmonitorstateexception(); \
1086 bool monitorExit(threadobject *t, java_objectheader *o)
1088 monitorLockRecord *lr = o->monitorPtr;
1090 CHECK_MONITORSTATE(lr, t, o, return false);
1091 if (lr->lockCount > 1) {
1096 monitorLockRecord *wlr = lr->waiter;
1097 if (o->monitorPtr != lr ||
1098 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
1100 monitorLockRecord *nlr = o->monitorPtr;
1102 STORE_ORDER_BARRIER();
1108 recycleLockRecord(t, lr);
1112 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
1115 if (lr->waiter == wlr) {
1116 lr->waiter = wlr->waiter;
1123 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
1125 return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1128 static bool timeIsEarlier(const struct timespec *tv)
1130 struct timeval tvnow;
1131 struct timespec tsnow;
1132 gettimeofday(&tvnow, NULL);
1133 tsnow.tv_sec = tvnow.tv_sec;
1134 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1135 return timespec_less(&tsnow, tv);
1139 /* waitWithTimeout *************************************************************
1143 *******************************************************************************/
1145 static bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
1147 bool wasinterrupted;
1149 pthread_mutex_lock(&t->waitLock);
1151 t->isSleeping = true;
1153 if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
1154 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
1155 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1157 while (!t->interrupted && !t->signaled)
1158 pthread_cond_wait(&t->waitCond, &t->waitLock);
1160 wasinterrupted = t->interrupted;
1161 t->interrupted = false;
1162 t->signaled = false;
1163 t->isSleeping = false;
1165 pthread_mutex_unlock(&t->waitLock);
1167 return wasinterrupted;
1171 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1173 if (millis || nanos) {
1176 gettimeofday(&tv, NULL);
1177 tv.tv_sec += millis / 1000;
1179 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1180 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1181 tm->tv_nsec = nsec % 1000000000;
1188 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1190 bool wasinterrupted;
1191 struct timespec wakeupTime;
1192 monitorLockRecord *mlr, *lr = o->monitorPtr;
1194 CHECK_MONITORSTATE(lr, t, o, return);
1196 calcAbsoluteTime(&wakeupTime, millis, nanos);
1199 wakeWaiters(lr->waiter);
1201 STORE_ORDER_BARRIER();
1203 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1204 mlr = monitorEnter(t, o);
1205 removeFromWaiters(mlr, lr);
1206 mlr->lockCount = lr->lockCount;
1208 lr->waiting = false;
1210 recycleLockRecord(t, lr);
1213 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1216 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1218 monitorLockRecord *lr = o->monitorPtr;
1220 CHECK_MONITORSTATE(lr, t, o, return);
1222 threadobject *wthread;
1223 monitorLockRecord *wlr = lr->waiter;
1226 wthread = wlr->ownerThread;
1227 pthread_mutex_lock(&wthread->waitLock);
1228 if (wthread->isSleeping)
1229 pthread_cond_signal(&wthread->waitCond);
1230 wthread->signaled = true;
1231 pthread_mutex_unlock(&wthread->waitLock);
1236 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1238 monitorLockRecord *lr = o->monitorPtr;
1240 /* The reason why we have to check against NULL is that
1241 * dummyLR->incharge == NULL */
1242 return lr && lr->o == o && lr->ownerThread == t;
1245 void interruptThread(java_lang_VMThread *thread)
1247 threadobject *t = (threadobject*) thread;
1249 t->interrupted = true;
1250 pthread_mutex_lock(&t->waitLock);
1252 pthread_cond_signal(&t->waitCond);
1253 pthread_mutex_unlock(&t->waitLock);
1256 bool interruptedThread()
1258 threadobject *t = (threadobject*) THREADOBJECT;
1259 bool intr = t->interrupted;
1260 t->interrupted = false;
1264 bool isInterruptedThread(java_lang_VMThread *thread)
1266 threadobject *t = (threadobject*) thread;
1267 return t->interrupted;
1270 void sleepThread(s8 millis, s4 nanos)
1272 bool wasinterrupted;
1273 threadobject *t = (threadobject*) THREADOBJECT;
1274 monitorLockRecord *lr;
1275 struct timespec wakeupTime;
1276 calcAbsoluteTime(&wakeupTime, millis, nanos);
1278 lr = allocLockRecordSimple(t);
1279 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1280 recycleLockRecord(t, lr);
1283 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1291 void setPriorityThread(thread *t, s4 priority)
1293 nativethread *info = &((threadobject*) t->vmThread)->info;
1294 setPriority(info->tid, priority);
1297 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1299 threadobject *t = (threadobject*) THREADOBJECT;
1300 monitorWait(t, o, time, nanos);
1303 void signal_cond_for_object(java_objectheader *o)
1305 threadobject *t = (threadobject*) THREADOBJECT;
1306 notifyOneOrAll(t, o, true);
1309 void broadcast_cond_for_object(java_objectheader *o)
1311 threadobject *t = (threadobject*) THREADOBJECT;
1312 notifyOneOrAll(t, o, false);
1316 /* threads_dump ****************************************************************
1318 Dumps info for all threads running in the JVM. This function is
1319 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1321 *******************************************************************************/
1323 void threads_dump(void)
1326 java_lang_VMThread *vmt;
1328 ExecEnvironment *ee;
1329 java_lang_Thread *t;
1332 tobj = mainthreadobj;
1334 printf("Full thread dump CACAO "VERSION":\n");
1336 /* iterate over all started threads */
1339 /* get thread objects */
1346 /* the thread may be currently in initalization, don't print it */
1349 /* get thread name */
1351 name = javastring_toutf(t->name, false);
1360 #if SIZEOF_VOID_P == 8
1361 printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1363 printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1366 /* send SIGUSR1 to thread to print stacktrace */
1368 pthread_kill(nt->tid, SIGUSR1);
1370 /* sleep this thread a bit, so the signal can reach the thread */
1375 tobj = tobj->info.next;
1376 } while (tobj && (tobj != mainthreadobj));
1381 * These are local overrides for various environment variables in Emacs.
1382 * Please do not remove this and leave it at the end of the file, where
1383 * Emacs will automagically detect them.
1384 * ---------------------------------------------------------------------
1387 * indent-tabs-mode: t