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
31 $Id: threads.c 4443 2006-02-05 13:39:34Z stefan $
39 #include <sys/types.h>
47 #include <semaphore.h>
54 #ifndef USE_MD_THREAD_STUFF
55 #include "machine-instr.h"
57 #include "threads/native/generic-primitives.h"
60 #include "cacao/cacao.h"
62 #include "mm/memory.h"
63 #include "native/native.h"
64 #include "native/include/java_lang_Object.h"
65 #include "native/include/java_lang_Throwable.h"
66 #include "native/include/java_lang_Thread.h"
67 #include "native/include/java_lang_ThreadGroup.h"
68 #include "native/include/java_lang_VMThread.h"
69 #include "threads/native/threads.h"
70 #include "toolbox/avl.h"
71 #include "toolbox/logging.h"
72 #include "vm/builtin.h"
73 #include "vm/exceptions.h"
74 #include "vm/global.h"
75 #include "vm/loader.h"
76 #include "vm/options.h"
77 #include "vm/stringlocal.h"
78 #include "vm/jit/asmpart.h"
80 #if !defined(__DARWIN__)
81 #if defined(__LINUX__)
82 #define GC_LINUX_THREADS
83 #elif defined(__MIPS__)
84 #define GC_IRIX_THREADS
86 #include "boehm-gc/include/gc.h"
89 #ifdef USE_MD_THREAD_STUFF
90 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
91 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
92 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
97 /* We need this for older MacOSX (10.1.x) */
100 pthread_mutex_t mutex;
103 } pthread_mutex_rec_t;
105 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
107 pthread_mutex_init(&m->mutex, NULL);
111 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
113 pthread_mutex_destroy(&m->mutex);
116 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
121 pthread_mutex_lock(&m->mutex);
122 m->owner = pthread_self();
126 if (m->owner != pthread_self())
127 pthread_mutex_lock(&m->mutex);
136 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
139 pthread_mutex_unlock(&m->mutex);
144 #define pthread_mutex_lock_rec pthread_mutex_lock
145 #define pthread_mutex_unlock_rec pthread_mutex_unlock
146 #define pthread_mutex_rec_t pthread_mutex_t
148 #endif /* MUTEXSIM */
150 static void setPriority(pthread_t tid, int priority)
152 struct sched_param schedp;
155 pthread_getschedparam(tid, &policy, &schedp);
156 schedp.sched_priority = priority;
157 pthread_setschedparam(tid, policy, &schedp);
161 static avl_tree *criticaltree;
162 threadobject *mainthreadobj;
164 #ifndef HAVE___THREAD
165 pthread_key_t tkey_threadinfo;
167 __thread threadobject *threadobj;
170 static pthread_mutex_rec_t compiler_mutex;
171 static pthread_mutex_rec_t tablelock;
175 pthread_mutex_lock_rec(&compiler_mutex);
178 void compiler_unlock()
180 pthread_mutex_unlock_rec(&compiler_mutex);
185 pthread_mutex_lock_rec(&tablelock);
190 pthread_mutex_unlock_rec(&tablelock);
194 static s4 criticalcompare(const void *pa, const void *pb)
196 const threadcritnode *na = pa;
197 const threadcritnode *nb = pb;
199 if (na->mcodebegin < nb->mcodebegin)
201 if (na->mcodebegin > nb->mcodebegin)
207 static const threadcritnode *findcritical(u1 *mcodeptr)
210 const threadcritnode *m;
212 n = criticaltree->root;
219 const threadcritnode *d = n->data;
221 if (mcodeptr == d->mcodebegin)
224 if (mcodeptr < d->mcodebegin) {
241 void thread_registercritical(threadcritnode *n)
243 avl_insert(criticaltree, n);
246 u1 *thread_checkcritical(u1 *mcodeptr)
248 const threadcritnode *n = findcritical(mcodeptr);
249 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
252 static void thread_addstaticcritical()
254 /* XXX TWISTI: this is just a quick hack */
255 #if defined(ENABLE_JIT)
256 threadcritnode *n = &asm_criticalsections;
258 while (n->mcodebegin)
259 thread_registercritical(n++);
263 static pthread_mutex_t threadlistlock;
265 static pthread_mutex_t stopworldlock;
266 volatile int stopworldwhere;
268 static sem_t suspend_ack;
269 #if defined(__MIPS__)
270 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
271 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
275 * where - 1 from within GC
278 void lock_stopworld(int where)
280 pthread_mutex_lock(&stopworldlock);
281 stopworldwhere = where;
284 void unlock_stopworld()
287 pthread_mutex_unlock(&stopworldlock);
290 #if !defined(__DARWIN__)
291 /* Caller must hold threadlistlock */
292 static int cast_sendsignals(int sig, int count)
295 threadobject *tobj = mainthreadobj;
296 nativethread *infoself = THREADINFO;
301 tobj = tobj->info.next;
302 } while (tobj != mainthreadobj);
305 nativethread *info = &tobj->info;
306 if (info != infoself)
307 pthread_kill(info->tid, sig);
308 tobj = tobj->info.next;
309 } while (tobj != mainthreadobj);
316 static void cast_darwinstop()
318 threadobject *tobj = mainthreadobj;
319 nativethread *infoself = THREADINFO;
322 nativethread *info = &tobj->info;
323 if (info != infoself)
325 thread_state_flavor_t flavor = PPC_THREAD_STATE;
326 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
327 ppc_thread_state_t thread_state;
328 mach_port_t thread = info->mach_thread;
331 r = thread_suspend(thread);
332 if (r != KERN_SUCCESS) {
333 log_text("thread_suspend failed");
337 r = thread_get_state(thread, flavor,
338 (natural_t*)&thread_state, &thread_state_count);
339 if (r != KERN_SUCCESS) {
340 log_text("thread_get_state failed");
344 thread_restartcriticalsection(&thread_state);
346 r = thread_set_state(thread, flavor,
347 (natural_t*)&thread_state, thread_state_count);
348 if (r != KERN_SUCCESS) {
349 log_text("thread_set_state failed");
353 tobj = tobj->info.next;
354 } while (tobj != mainthreadobj);
357 static void cast_darwinresume()
359 threadobject *tobj = mainthreadobj;
360 nativethread *infoself = THREADINFO;
363 nativethread *info = &tobj->info;
364 if (info != infoself)
366 mach_port_t thread = info->mach_thread;
369 r = thread_resume(thread);
370 if (r != KERN_SUCCESS) {
371 log_text("thread_resume failed");
375 tobj = tobj->info.next;
376 } while (tobj != mainthreadobj);
381 #if defined(__MIPS__)
382 static void cast_irixresume()
384 pthread_mutex_lock(&suspend_ack_lock);
385 pthread_cond_broadcast(&suspend_cond);
386 pthread_mutex_unlock(&suspend_ack_lock);
390 void cast_stopworld()
394 pthread_mutex_lock(&threadlistlock);
395 #if defined(__DARWIN__)
398 count = cast_sendsignals(GC_signum1(), 0);
399 for (i=0; i<count; i++)
400 sem_wait(&suspend_ack);
402 pthread_mutex_unlock(&threadlistlock);
405 void cast_startworld()
407 pthread_mutex_lock(&threadlistlock);
408 #if defined(__DARWIN__)
410 #elif defined(__MIPS__)
413 cast_sendsignals(GC_signum2(), -1);
415 pthread_mutex_unlock(&threadlistlock);
419 #if !defined(__DARWIN__)
420 static void sigsuspend_handler(ucontext_t *ctx)
425 /* XXX TWISTI: this is just a quick hack */
426 #if defined(ENABLE_JIT)
427 thread_restartcriticalsection(ctx);
430 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
431 (not POSIX async-safe). */
432 #if defined(__IRIX__)
433 pthread_mutex_lock(&suspend_ack_lock);
434 sem_post(&suspend_ack);
435 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
436 pthread_mutex_unlock(&suspend_ack_lock);
438 sem_post(&suspend_ack);
442 sigdelset(&sigs, sig);
447 int cacao_suspendhandler(ucontext_t *ctx)
449 if (stopworldwhere != 2)
452 sigsuspend_handler(ctx);
457 static void setthreadobject(threadobject *thread)
459 #if !defined(HAVE___THREAD)
460 pthread_setspecific(tkey_threadinfo, thread);
467 /* thread_setself **************************************************************
471 *******************************************************************************/
473 void *thread_getself(void)
479 static monitorLockRecord *dummyLR;
481 static void initPools();
484 /* thread_preinit **************************************************************
486 Do some early initialization of stuff required.
488 *******************************************************************************/
490 void threads_preinit(void)
493 pthread_mutexattr_t mutexattr;
494 pthread_mutexattr_init(&mutexattr);
495 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
496 pthread_mutex_init(&compiler_mutex, &mutexattr);
497 pthread_mutex_init(&tablelock, &mutexattr);
498 pthread_mutexattr_destroy(&mutexattr);
500 pthread_mutex_init_rec(&compiler_mutex);
501 pthread_mutex_init_rec(&tablelock);
504 pthread_mutex_init(&threadlistlock, NULL);
505 pthread_mutex_init(&stopworldlock, NULL);
507 /* Allocate something so the garbage collector's signal handlers
509 heap_allocate(1, false, NULL);
511 mainthreadobj = NEW(threadobject);
512 mainthreadobj->info.tid = pthread_self();
513 #if !defined(HAVE___THREAD)
514 pthread_key_create(&tkey_threadinfo, NULL);
516 setthreadobject(mainthreadobj);
519 /* Every newly created object's monitorPtr points here so we save
520 a check against NULL */
522 dummyLR = NEW(monitorLockRecord);
524 dummyLR->ownerThread = NULL;
525 dummyLR->waiting = NULL;
526 dummyLR->incharge = dummyLR;
528 /* we need a working dummyLR before initializing the critical
531 criticaltree = avl_create(&criticalcompare);
533 thread_addstaticcritical();
534 sem_init(&suspend_ack, 0, 0);
538 static pthread_attr_t threadattr;
540 static void freeLockRecordPools(lockRecordPool *);
543 /* threads_init ****************************************************************
545 Initializes the threads required by the JVM: main, finalizer.
547 *******************************************************************************/
549 bool threads_init(u1 *stackbottom)
551 java_lang_String *threadname;
552 java_lang_Thread *mainthread;
553 java_lang_ThreadGroup *threadgroup;
554 threadobject *tempthread;
557 tempthread = mainthreadobj;
559 freeLockRecordPools(mainthreadobj->ee.lrpool);
561 /* This is kinda tricky, we grow the java.lang.Thread object so we
562 can keep the execution environment there. No Thread object must
563 have been created at an earlier time. */
565 class_java_lang_VMThread->instancesize = sizeof(threadobject);
567 /* create a VMThread */
569 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
574 FREE(tempthread, threadobject);
576 initThread(&mainthreadobj->o);
578 setthreadobject(mainthreadobj);
582 mainthreadobj->info.next = mainthreadobj;
583 mainthreadobj->info.prev = mainthreadobj;
585 #if defined(ENABLE_INTRP)
586 /* create interpreter stack */
589 MSET(intrp_main_stack, 0, u1, opt_stacksize);
590 mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
594 threadname = javastring_new(utf_new_char("main"));
596 /* allocate and init ThreadGroup */
598 threadgroup = (java_lang_ThreadGroup *)
599 native_new_and_init(class_java_lang_ThreadGroup);
602 throw_exception_exit();
604 /* create a Thread */
606 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
609 throw_exception_exit();
611 mainthreadobj->o.thread = mainthread;
613 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
615 method = class_resolveclassmethod(class_java_lang_Thread,
617 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
618 class_java_lang_Thread,
624 ASM_CALLJAVAFUNCTION(method, mainthread, mainthreadobj, threadname,
630 mainthread->group = threadgroup;
631 /* XXX This is a hack because the fourth argument was omitted */
632 mainthread->daemon = false;
634 /* add mainthread to ThreadGroup */
636 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
637 utf_new_char("addThread"),
638 utf_new_char("(Ljava/lang/Thread;)V"),
639 class_java_lang_ThreadGroup,
645 ASM_CALLJAVAFUNCTION(method, threadgroup, mainthread, NULL, NULL);
650 setPriority(pthread_self(), 5);
652 pthread_attr_init(&threadattr);
653 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
655 /* everything's ok */
661 void initThread(java_lang_VMThread *t)
663 threadobject *thread = (threadobject*) t;
664 nativethread *info = &thread->info;
665 info->tid = pthread_self();
666 /* TODO destroy all those things */
667 pthread_mutex_init(&info->joinMutex, NULL);
668 pthread_cond_init(&info->joinCond, NULL);
670 pthread_mutex_init(&thread->waitLock, NULL);
671 pthread_cond_init(&thread->waitCond, NULL);
672 thread->interrupted = false;
673 thread->signaled = false;
674 thread->isSleeping = false;
677 static void initThreadLocks(threadobject *);
681 threadobject *thread;
682 functionptr function;
688 /* threads_startup *************************************************************
690 Thread startup function called by pthread_create.
692 ******************************************************************************/
694 static void *threads_startup_thread(void *t)
696 startupinfo *startup;
697 threadobject *thread;
702 functionptr function;
704 #if defined(ENABLE_INTRP)
705 u1 *intrp_thread_stack;
707 /* create interpreter stack */
710 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
711 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
715 /* get passed startupinfo structure and the values in there */
719 thread = startup->thread;
720 function = startup->function;
721 psem = startup->psem;
723 info = &thread->info;
725 /* Seems like we've encountered a situation where info->tid was not set by
726 * pthread_create. We alleviate this problem by waiting for pthread_create
728 sem_wait(startup->psem_first);
731 #if defined(__DARWIN__)
732 info->mach_thread = mach_thread_self();
734 setthreadobject(thread);
736 /* insert the thread into the threadlist */
738 pthread_mutex_lock(&threadlistlock);
740 info->prev = mainthreadobj;
741 info->next = tnext = mainthreadobj->info.next;
742 mainthreadobj->info.next = thread;
743 tnext->info.prev = thread;
745 pthread_mutex_unlock(&threadlistlock);
747 initThreadLocks(thread);
752 setPriority(info->tid, thread->o.thread->priority);
754 #if defined(ENABLE_INTRP)
755 /* set interpreter stack */
758 THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
761 /* find and run the Thread.run()V method if no other function was passed */
763 if (function == NULL) {
764 method = class_resolveclassmethod(thread->o.header.vftbl->class,
767 thread->o.header.vftbl->class,
773 ASM_CALLJAVAFUNCTION(method, thread, NULL, NULL, NULL);
776 /* call passed function, e.g. finalizer_thread */
781 /* Allow lock record pools to be used by other threads. They
782 cannot be deleted so we'd better not waste them. */
784 freeLockRecordPools(thread->ee.lrpool);
786 /* remove thread from thread list, do this inside a lock */
788 pthread_mutex_lock(&threadlistlock);
789 info->next->info.prev = info->prev;
790 info->prev->info.next = info->next;
791 pthread_mutex_unlock(&threadlistlock);
793 /* reset thread id (lock on joinMutex? TWISTI) */
795 pthread_mutex_lock(&info->joinMutex);
797 pthread_mutex_unlock(&info->joinMutex);
799 pthread_cond_broadcast(&info->joinCond);
805 /* threads_start_thread ********************************************************
807 Start a thread in the JVM.
809 ******************************************************************************/
811 void threads_start_thread(thread *t, functionptr function)
818 info = &((threadobject *) t->vmThread)->info;
820 /* fill startupinfo structure passed by pthread_create to XXX */
822 startup.thread = (threadobject*) t->vmThread;
823 startup.function = function; /* maybe we don't call Thread.run()V */
825 startup.psem_first = &sem_first;
827 sem_init(&sem, 0, 0);
828 sem_init(&sem_first, 0, 0);
830 if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
832 log_text("pthread_create failed");
836 sem_post(&sem_first);
838 /* wait here until the thread has entered itself into the thread list */
842 sem_destroy(&sem_first);
846 /* At the end of the program, we wait for all running non-daemon threads to die
849 static threadobject *findNonDaemon(threadobject *thread)
851 while (thread != mainthreadobj) {
852 if (!thread->o.thread->daemon)
854 thread = thread->info.prev;
860 void joinAllThreads()
862 threadobject *thread;
863 pthread_mutex_lock(&threadlistlock);
864 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
865 nativethread *info = &thread->info;
866 pthread_mutex_lock(&info->joinMutex);
867 pthread_mutex_unlock(&threadlistlock);
869 pthread_cond_wait(&info->joinCond, &info->joinMutex);
870 pthread_mutex_unlock(&info->joinMutex);
871 pthread_mutex_lock(&threadlistlock);
873 pthread_mutex_unlock(&threadlistlock);
876 static void initLockRecord(monitorLockRecord *r, threadobject *t)
883 r->incharge = (monitorLockRecord *) &dummyLR;
885 sem_init(&r->queueSem, 0, 0);
886 pthread_mutex_init(&r->resolveLock, NULL);
887 pthread_cond_init(&r->resolveWait, NULL);
890 /* No lock record must ever be destroyed because there may still be references
893 static void destroyLockRecord(monitorLockRecord *r)
895 sem_destroy(&r->queueSem);
896 pthread_mutex_destroy(&r->resolveLock);
897 pthread_cond_destroy(&r->resolveWait);
903 initThreadLocks(mainthreadobj);
906 static void initThreadLocks(threadobject *thread)
908 thread->ee.firstLR = NULL;
909 thread->ee.lrpool = NULL;
910 thread->ee.numlr = 0;
913 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
915 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
918 p->header.size = size;
919 for (i=0; i<size; i++) {
920 initLockRecord(&p->lr[i], thread);
921 p->lr[i].nextFree = &p->lr[i+1];
923 p->lr[i-1].nextFree = NULL;
927 #define INITIALLOCKRECORDS 8
929 pthread_mutex_t pool_lock;
930 lockRecordPool *global_pool;
932 static void initPools()
934 pthread_mutex_init(&pool_lock, NULL);
937 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
939 pthread_mutex_lock(&pool_lock);
942 lockRecordPool *pool = global_pool;
943 global_pool = pool->header.next;
944 pthread_mutex_unlock(&pool_lock);
946 for (i=0; i < pool->header.size; i++)
947 pool->lr[i].ownerThread = t;
951 pthread_mutex_unlock(&pool_lock);
953 return allocNewLockRecordPool(t, size);
956 static void freeLockRecordPools(lockRecordPool *pool)
958 lockRecordPoolHeader *last;
959 pthread_mutex_lock(&pool_lock);
960 last = &pool->header;
962 last = &last->next->header;
963 last->next = global_pool;
965 pthread_mutex_unlock(&pool_lock);
968 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
970 monitorLockRecord *r = t->ee.firstLR;
973 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
974 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
975 pool->header.next = t->ee.lrpool;
978 t->ee.numlr += pool->header.size;
981 t->ee.firstLR = r->nextFree;
985 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
987 r->nextFree = t->ee.firstLR;
991 void initObjectLock(java_objectheader *o)
993 o->monitorPtr = dummyLR;
997 /* get_dummyLR *****************************************************************
999 Returns the global dummy monitor lock record. The pointer is
1000 required in the code generator to set up a virtual
1001 java_objectheader for code patch locking.
1003 *******************************************************************************/
1005 monitorLockRecord *get_dummyLR(void)
1011 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
1013 atomic_add(&lr->queuers, 1);
1015 MEMORY_BARRIER_AFTER_ATOMIC();
1018 sem_wait(&lr->queueSem);
1020 atomic_add(&lr->queuers, -1);
1023 static void freeLockRecord(monitorLockRecord *lr)
1030 sem_post(&lr->queueSem);
1033 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr, java_objectheader *o)
1035 if (lr->waiting == o)
1039 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
1042 monitorLockRecord *lr = o->monitorPtr;
1044 monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
1048 nlr = o->monitorPtr;
1050 handleWaiter(mlr, lr, o);
1054 if (lr->ownerThread != t)
1056 MEMORY_BARRIER_BEFORE_ATOMIC();
1057 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
1060 if (mlr == lr || lr->o != o) {
1061 handleWaiter(mlr, lr, o);
1065 queueOnLockRecord(lr, o);
1066 handleWaiter(mlr, lr, o);
1069 freeLockRecord(mlr);
1070 recycleLockRecord(t, mlr);
1071 queueOnLockRecord(nlr, o);
1073 if (lr->ownerThread == t) {
1077 queueOnLockRecord(lr, o);
1082 static void wakeWaiters(monitorLockRecord *lr)
1084 monitorLockRecord *tmplr;
1087 /* assign lock record to a temporary variable */
1095 sem_post(&tmplr->queueSem);
1097 tmplr = tmplr->waiter;
1098 } while (tmplr != NULL && tmplr != lr);
1101 #define GRAB_LR(lr,t) \
1102 if (lr->ownerThread != t) { \
1103 lr = lr->incharge; \
1106 #define CHECK_MONITORSTATE(lr,t,mo,a) \
1107 if (lr->o != mo || lr->ownerThread != t) { \
1108 *exceptionptr = new_illegalmonitorstateexception(); \
1112 bool monitorExit(threadobject *t, java_objectheader *o)
1114 monitorLockRecord *lr = o->monitorPtr;
1116 CHECK_MONITORSTATE(lr, t, o, return false);
1117 if (lr->lockCount > 1) {
1122 monitorLockRecord *wlr = lr->waiter;
1123 if (o->monitorPtr != lr ||
1124 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
1126 monitorLockRecord *nlr = o->monitorPtr;
1128 STORE_ORDER_BARRIER();
1134 recycleLockRecord(t, lr);
1138 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
1141 if (lr->waiter == wlr) {
1142 lr->waiter = wlr->waiter;
1149 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
1151 return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1154 static bool timeIsEarlier(const struct timespec *tv)
1156 struct timeval tvnow;
1157 struct timespec tsnow;
1158 gettimeofday(&tvnow, NULL);
1159 tsnow.tv_sec = tvnow.tv_sec;
1160 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1161 return timespec_less(&tsnow, tv);
1165 /* waitWithTimeout *************************************************************
1169 *******************************************************************************/
1171 static bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
1173 bool wasinterrupted;
1175 pthread_mutex_lock(&t->waitLock);
1177 t->isSleeping = true;
1179 if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
1180 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
1181 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1183 while (!t->interrupted && !t->signaled)
1184 pthread_cond_wait(&t->waitCond, &t->waitLock);
1186 wasinterrupted = t->interrupted;
1187 t->interrupted = false;
1188 t->signaled = false;
1189 t->isSleeping = false;
1191 pthread_mutex_unlock(&t->waitLock);
1193 return wasinterrupted;
1197 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1199 if (millis || nanos) {
1202 gettimeofday(&tv, NULL);
1203 tv.tv_sec += millis / 1000;
1205 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1206 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1207 tm->tv_nsec = nsec % 1000000000;
1214 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1216 bool wasinterrupted;
1217 struct timespec wakeupTime;
1218 monitorLockRecord *mlr, *lr = o->monitorPtr;
1220 CHECK_MONITORSTATE(lr, t, o, return);
1222 calcAbsoluteTime(&wakeupTime, millis, nanos);
1225 wakeWaiters(lr->waiter);
1227 STORE_ORDER_BARRIER();
1229 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1230 mlr = monitorEnter(t, o);
1231 removeFromWaiters(mlr, lr);
1232 mlr->lockCount = lr->lockCount;
1236 recycleLockRecord(t, lr);
1239 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1242 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1244 monitorLockRecord *lr = o->monitorPtr;
1246 CHECK_MONITORSTATE(lr, t, o, return);
1248 threadobject *wthread;
1249 monitorLockRecord *wlr = lr->waiter;
1252 wthread = wlr->ownerThread;
1253 pthread_mutex_lock(&wthread->waitLock);
1254 if (wthread->isSleeping)
1255 pthread_cond_signal(&wthread->waitCond);
1256 wthread->signaled = true;
1257 pthread_mutex_unlock(&wthread->waitLock);
1262 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1264 monitorLockRecord *lr = o->monitorPtr;
1266 /* The reason why we have to check against NULL is that
1267 * dummyLR->incharge == NULL */
1268 return lr->o == o && lr->ownerThread == t;
1271 void interruptThread(java_lang_VMThread *thread)
1273 threadobject *t = (threadobject*) thread;
1275 pthread_mutex_lock(&t->waitLock);
1277 pthread_cond_signal(&t->waitCond);
1278 t->interrupted = true;
1279 pthread_mutex_unlock(&t->waitLock);
1282 bool interruptedThread()
1284 threadobject *t = (threadobject*) THREADOBJECT;
1285 bool intr = t->interrupted;
1286 t->interrupted = false;
1290 bool isInterruptedThread(java_lang_VMThread *thread)
1292 threadobject *t = (threadobject*) thread;
1293 return t->interrupted;
1296 void sleepThread(s8 millis, s4 nanos)
1298 bool wasinterrupted;
1299 threadobject *t = (threadobject*) THREADOBJECT;
1300 monitorLockRecord *lr;
1301 struct timespec wakeupTime;
1302 calcAbsoluteTime(&wakeupTime, millis, nanos);
1304 lr = allocLockRecordSimple(t);
1305 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1306 recycleLockRecord(t, lr);
1309 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1317 void setPriorityThread(thread *t, s4 priority)
1319 nativethread *info = &((threadobject*) t->vmThread)->info;
1320 setPriority(info->tid, priority);
1323 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1325 threadobject *t = (threadobject*) THREADOBJECT;
1326 monitorWait(t, o, time, nanos);
1329 void signal_cond_for_object(java_objectheader *o)
1331 threadobject *t = (threadobject*) THREADOBJECT;
1332 notifyOneOrAll(t, o, true);
1335 void broadcast_cond_for_object(java_objectheader *o)
1337 threadobject *t = (threadobject*) THREADOBJECT;
1338 notifyOneOrAll(t, o, false);
1342 /* threads_dump ****************************************************************
1344 Dumps info for all threads running in the JVM. This function is
1345 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1347 *******************************************************************************/
1349 void threads_dump(void)
1352 java_lang_VMThread *vmt;
1354 ExecEnvironment *ee;
1355 java_lang_Thread *t;
1358 tobj = mainthreadobj;
1360 printf("Full thread dump CACAO "VERSION":\n");
1362 /* iterate over all started threads */
1365 /* get thread objects */
1372 /* the thread may be currently in initalization, don't print it */
1375 /* get thread name */
1377 name = javastring_toutf(t->name, false);
1386 #if SIZEOF_VOID_P == 8
1387 printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1389 printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1392 /* send SIGUSR1 to thread to print stacktrace */
1394 pthread_kill(nt->tid, SIGUSR1);
1396 /* sleep this thread a bit, so the signal can reach the thread */
1401 tobj = tobj->info.next;
1402 } while (tobj && (tobj != mainthreadobj));
1407 * These are local overrides for various environment variables in Emacs.
1408 * Please do not remove this and leave it at the end of the file, where
1409 * Emacs will automagically detect them.
1410 * ---------------------------------------------------------------------
1413 * indent-tabs-mode: t