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 2760 2005-06-20 22:36:55Z stefan $
39 #include <sys/types.h>
49 #include "mm/memory.h"
50 #include "native/native.h"
51 #include "native/include/java_lang_Object.h"
52 #include "native/include/java_lang_Throwable.h"
53 #include "native/include/java_lang_Thread.h"
54 #include "native/include/java_lang_ThreadGroup.h"
55 #include "native/include/java_lang_VMThread.h"
56 #include "threads/native/threads.h"
57 #include "toolbox/avl.h"
58 #include "toolbox/logging.h"
59 #include "vm/builtin.h"
60 #include "vm/exceptions.h"
61 #include "vm/global.h"
62 #include "vm/loader.h"
63 #include "vm/stringlocal.h"
64 #include "vm/tables.h"
65 #include "vm/jit/asmpart.h"
68 #include <semaphore.h>
70 #if !defined(__DARWIN__)
71 #if defined(__LINUX__)
72 #define GC_LINUX_THREADS
73 #elif defined(__MIPS__)
74 #define GC_IRIX_THREADS
76 #include "boehm-gc/include/gc.h"
81 /* We need this for older MacOSX (10.1.x) */
84 pthread_mutex_t mutex;
87 } pthread_mutex_rec_t;
89 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
91 pthread_mutex_init(&m->mutex, NULL);
95 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
97 pthread_mutex_destroy(&m->mutex);
100 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
105 pthread_mutex_lock(&m->mutex);
106 m->owner = pthread_self();
110 if (m->owner != pthread_self())
111 pthread_mutex_lock(&m->mutex);
120 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
123 pthread_mutex_unlock(&m->mutex);
128 #define pthread_mutex_lock_rec pthread_mutex_lock
129 #define pthread_mutex_unlock_rec pthread_mutex_unlock
130 #define pthread_mutex_rec_t pthread_mutex_t
132 #endif /* MUTEXSIM */
134 static void setPriority(pthread_t tid, int priority)
136 struct sched_param schedp;
139 pthread_getschedparam(tid, &policy, &schedp);
140 schedp.sched_priority = priority;
141 pthread_setschedparam(tid, policy, &schedp);
144 #include "machine-instr.h"
146 static struct avl_table *criticaltree;
147 static threadobject *mainthreadobj;
149 #ifndef HAVE___THREAD
150 pthread_key_t tkey_threadinfo;
152 __thread threadobject *threadobj;
155 static pthread_mutex_rec_t compiler_mutex;
156 static pthread_mutex_rec_t tablelock;
160 pthread_mutex_lock_rec(&compiler_mutex);
163 void compiler_unlock()
165 pthread_mutex_unlock_rec(&compiler_mutex);
170 pthread_mutex_lock_rec(&tablelock);
175 pthread_mutex_unlock_rec(&tablelock);
178 static int criticalcompare(const void *pa, const void *pb, void *param)
180 const threadcritnode *na = pa;
181 const threadcritnode *nb = pb;
183 if (na->mcodebegin < nb->mcodebegin)
185 if (na->mcodebegin > nb->mcodebegin)
190 static const threadcritnode *findcritical(u1 *mcodeptr)
192 struct avl_node *n = criticaltree->avl_root;
193 const threadcritnode *m = NULL;
198 const threadcritnode *d = n->avl_data;
199 if (mcodeptr == d->mcodebegin)
201 if (mcodeptr < d->mcodebegin) {
207 if (n->avl_link[1]) {
216 void thread_registercritical(threadcritnode *n)
218 avl_insert(criticaltree, n);
221 u1 *thread_checkcritical(u1 *mcodeptr)
223 const threadcritnode *n = findcritical(mcodeptr);
224 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
227 static void thread_addstaticcritical()
229 threadcritnode *n = &asm_criticalsections;
231 while (n->mcodebegin)
232 thread_registercritical(n++);
235 static pthread_mutex_t threadlistlock;
237 static pthread_mutex_t stopworldlock;
238 volatile int stopworldwhere;
240 static sem_t suspend_ack;
241 #if defined(__MIPS__)
242 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
243 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
247 * where - 1 from within GC
250 void lock_stopworld(int where)
252 pthread_mutex_lock(&stopworldlock);
253 stopworldwhere = where;
256 void unlock_stopworld()
259 pthread_mutex_unlock(&stopworldlock);
262 #if !defined(__DARWIN__)
263 /* Caller must hold threadlistlock */
264 static int cast_sendsignals(int sig, int count)
267 threadobject *tobj = mainthreadobj;
268 nativethread *infoself = THREADINFO;
273 tobj = tobj->info.next;
274 } while (tobj != mainthreadobj);
277 nativethread *info = &tobj->info;
278 if (info != infoself)
279 pthread_kill(info->tid, sig);
280 tobj = tobj->info.next;
281 } while (tobj != mainthreadobj);
288 static void cast_darwinstop()
290 threadobject *tobj = mainthreadobj;
291 nativethread *infoself = THREADINFO;
294 nativethread *info = &tobj->info;
295 if (info != infoself)
297 thread_state_flavor_t flavor = PPC_THREAD_STATE;
298 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
299 ppc_thread_state_t thread_state;
300 mach_port_t thread = info->mach_thread;
303 r = thread_suspend(thread);
304 if (r != KERN_SUCCESS) {
305 log_text("thread_suspend failed");
309 r = thread_get_state(thread, flavor,
310 (natural_t*)&thread_state, &thread_state_count);
311 if (r != KERN_SUCCESS) {
312 log_text("thread_get_state failed");
316 thread_restartcriticalsection(&thread_state);
318 r = thread_set_state(thread, flavor,
319 (natural_t*)&thread_state, thread_state_count);
320 if (r != KERN_SUCCESS) {
321 log_text("thread_set_state failed");
325 tobj = tobj->info.next;
326 } while (tobj != mainthreadobj);
329 static void cast_darwinresume()
331 threadobject *tobj = mainthreadobj;
332 nativethread *infoself = THREADINFO;
335 nativethread *info = &tobj->info;
336 if (info != infoself)
338 mach_port_t thread = info->mach_thread;
341 r = thread_resume(thread);
342 if (r != KERN_SUCCESS) {
343 log_text("thread_resume failed");
347 tobj = tobj->info.next;
348 } while (tobj != mainthreadobj);
353 #if defined(__MIPS__)
354 static void cast_irixresume()
356 pthread_mutex_lock(&suspend_ack_lock);
357 pthread_cond_broadcast(&suspend_cond);
358 pthread_mutex_unlock(&suspend_ack_lock);
362 void cast_stopworld()
366 pthread_mutex_lock(&threadlistlock);
367 #if defined(__DARWIN__)
370 count = cast_sendsignals(GC_signum1(), 0);
371 for (i=0; i<count; i++)
372 sem_wait(&suspend_ack);
374 pthread_mutex_unlock(&threadlistlock);
377 void cast_startworld()
379 pthread_mutex_lock(&threadlistlock);
380 #if defined(__DARWIN__)
382 #elif defined(__MIPS__)
385 cast_sendsignals(GC_signum2(), -1);
387 pthread_mutex_unlock(&threadlistlock);
391 #if !defined(__DARWIN__)
392 static void sigsuspend_handler(ucontext_t *ctx)
397 thread_restartcriticalsection(ctx);
399 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
400 (not POSIX async-safe). */
401 #if defined(__IRIX__)
402 pthread_mutex_lock(&suspend_ack_lock);
403 sem_post(&suspend_ack);
404 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
405 pthread_mutex_unlock(&suspend_ack_lock);
407 sem_post(&suspend_ack);
411 sigdelset(&sigs, sig);
416 int cacao_suspendhandler(ucontext_t *ctx)
418 if (stopworldwhere != 2)
421 sigsuspend_handler(ctx);
426 static void setthreadobject(threadobject *thread)
428 #if !defined(HAVE___THREAD)
429 pthread_setspecific(tkey_threadinfo, thread);
435 static monitorLockRecord *dummyLR;
437 static void initPools();
440 * Initialize threads.
446 pthread_mutexattr_t mutexattr;
447 pthread_mutexattr_init(&mutexattr);
448 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
449 pthread_mutex_init(&compiler_mutex, &mutexattr);
450 pthread_mutex_init(&tablelock, &mutexattr);
451 pthread_mutexattr_destroy(&mutexattr);
453 pthread_mutex_init_rec(&compiler_mutex);
454 pthread_mutex_init_rec(&tablelock);
457 pthread_mutex_init(&threadlistlock, NULL);
458 pthread_mutex_init(&stopworldlock, NULL);
460 /* Allocate something so the garbage collector's signal handlers are */
462 heap_allocate(1, false, NULL);
464 mainthreadobj = NEW(threadobject);
465 mainthreadobj->info.tid = pthread_self();
466 #if !defined(HAVE___THREAD)
467 pthread_key_create(&tkey_threadinfo, NULL);
469 setthreadobject(mainthreadobj);
472 criticaltree = avl_create(criticalcompare, NULL, NULL);
473 thread_addstaticcritical();
474 sem_init(&suspend_ack, 0, 0);
476 /* Every newly created object's monitorPtr points here so we save a check
478 dummyLR = NEW(monitorLockRecord);
480 dummyLR->ownerThread = NULL;
481 dummyLR->waiting = false;
484 static pthread_attr_t threadattr;
486 static void freeLockRecordPools(lockRecordPool *);
489 initThreads(u1 *stackbottom)
491 classinfo *threadclass;
492 java_lang_String *threadname;
493 java_lang_Thread *mainthread;
494 java_lang_ThreadGroup *threadgroup;
495 threadobject *tempthread = mainthreadobj;
498 if (!(threadclass = load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
499 throw_exception_exit();
502 throw_exception_exit();
504 if (!link_class(threadclass))
505 throw_exception_exit();
507 freeLockRecordPools(mainthreadobj->ee.lrpool);
508 /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
509 * the execution environment there. No Thread object must have been created
510 * at an earlier time */
511 threadclass->instancesize = sizeof(threadobject);
513 /* Create a VMThread */
514 mainthreadobj = (threadobject *) builtin_new(threadclass);
517 throw_exception_exit();
519 FREE(tempthread, threadobject);
520 initThread(&mainthreadobj->o);
522 setthreadobject(mainthreadobj);
525 mainthreadobj->info.next = mainthreadobj;
526 mainthreadobj->info.prev = mainthreadobj;
528 threadname = javastring_new(utf_new_char("main"));
530 /* Allocate and init ThreadGroup */
532 threadgroup = (java_lang_ThreadGroup *)
533 native_new_and_init(class_java_lang_ThreadGroup);
536 throw_exception_exit();
538 /* Create a Thread */
540 if (!(threadclass = load_class_bootstrap(utf_new_char("java/lang/Thread"))))
541 throw_exception_exit();
543 mainthread = (java_lang_Thread*) builtin_new(threadclass);
544 mainthreadobj->o.thread = mainthread;
547 throw_exception_exit();
549 /* Call Thread constructor */
550 method = class_resolveclassmethod(threadclass,
552 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
557 throw_exception_exit();
559 asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
561 throw_exception_exit();
563 mainthread->group = threadgroup;
564 /* XXX This is a hack because the fourth argument was omitted */
565 mainthread->daemon = false;
567 /* Add mainthread to ThreadGroup */
568 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
569 utf_new_char("addThread"),
570 utf_new_char("(Ljava/lang/Thread;)V"),
571 class_java_lang_ThreadGroup,
575 throw_exception_exit();
577 asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
579 throw_exception_exit();
581 setPriority(pthread_self(), 5);
583 pthread_attr_init(&threadattr);
584 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
587 void initThread(java_lang_VMThread *t)
589 threadobject *thread = (threadobject*) t;
590 nativethread *info = &thread->info;
591 info->tid = pthread_self();
592 /* TODO destroy all those things */
593 pthread_mutex_init(&info->joinMutex, NULL);
594 pthread_cond_init(&info->joinCond, NULL);
596 pthread_mutex_init(&thread->waitLock, NULL);
597 pthread_cond_init(&thread->waitCond, NULL);
598 thread->interrupted = false;
599 thread->signaled = false;
600 thread->isSleeping = false;
603 static void initThreadLocks(threadobject *);
606 threadobject *thread;
610 static void *threadstartup(void *t)
612 startupinfo *startup = t;
613 threadobject *thread = startup->thread;
614 sem_t *psem = startup->psem;
615 nativethread *info = &thread->info;
619 /* Seems like we've encountered a situation where info->tid was not set by
620 * pthread_create. We alleviate this problem by waiting for pthread_create
625 #if defined(__DARWIN__)
626 info->mach_thread = mach_thread_self();
628 setthreadobject(thread);
630 pthread_mutex_lock(&threadlistlock);
631 info->prev = mainthreadobj;
632 info->next = tnext = mainthreadobj->info.next;
633 mainthreadobj->info.next = thread;
634 tnext->info.prev = thread;
635 pthread_mutex_unlock(&threadlistlock);
637 initThreadLocks(thread);
642 setPriority(info->tid, thread->o.thread->priority);
644 /* Find the run()V method and call it */
646 method = class_resolveclassmethod(thread->o.header.vftbl->class,
649 thread->o.header.vftbl->class,
655 asm_calljavafunction(method, thread, NULL, NULL, NULL);
657 /* Allow lock record pools to be used by other threads. They cannot be
658 * deleted so we'd better not waste them. */
659 freeLockRecordPools(thread->ee.lrpool);
661 pthread_mutex_lock(&threadlistlock);
662 info->next->info.prev = info->prev;
663 info->prev->info.next = info->next;
664 pthread_mutex_unlock(&threadlistlock);
666 pthread_mutex_lock(&info->joinMutex);
668 pthread_mutex_unlock(&info->joinMutex);
669 pthread_cond_broadcast(&info->joinCond);
674 void startThread(thread *t)
676 nativethread *info = &((threadobject*) t->vmThread)->info;
680 startup.thread = (threadobject*) t->vmThread;
683 sem_init(&sem, 0, 0);
685 if (pthread_create(&info->tid, &threadattr, threadstartup, &startup)) {
686 log_text("pthread_create failed");
691 /* Wait here until the thread has entered itself into the thread list */
696 /* At the end of the program, we wait for all running non-daemon threads to die
699 static threadobject *findNonDaemon(threadobject *thread)
701 while (thread != mainthreadobj) {
702 if (!thread->o.thread->daemon)
704 thread = thread->info.prev;
710 void joinAllThreads()
712 threadobject *thread;
713 pthread_mutex_lock(&threadlistlock);
714 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
715 nativethread *info = &thread->info;
716 pthread_mutex_lock(&info->joinMutex);
717 pthread_mutex_unlock(&threadlistlock);
719 pthread_cond_wait(&info->joinCond, &info->joinMutex);
720 pthread_mutex_unlock(&info->joinMutex);
721 pthread_mutex_lock(&threadlistlock);
723 pthread_mutex_unlock(&threadlistlock);
726 static void initLockRecord(monitorLockRecord *r, threadobject *t)
733 r->incharge = (monitorLockRecord *) &dummyLR;
735 sem_init(&r->queueSem, 0, 0);
736 pthread_mutex_init(&r->resolveLock, NULL);
737 pthread_cond_init(&r->resolveWait, NULL);
740 /* No lock record must ever be destroyed because there may still be references
743 static void destroyLockRecord(monitorLockRecord *r)
745 sem_destroy(&r->queueSem);
746 pthread_mutex_destroy(&r->resolveLock);
747 pthread_cond_destroy(&r->resolveWait);
753 initThreadLocks(mainthreadobj);
756 static void initThreadLocks(threadobject *thread)
758 thread->ee.firstLR = NULL;
759 thread->ee.lrpool = NULL;
760 thread->ee.numlr = 0;
763 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
765 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
768 p->header.size = size;
769 for (i=0; i<size; i++) {
770 initLockRecord(&p->lr[i], thread);
771 p->lr[i].nextFree = &p->lr[i+1];
773 p->lr[i-1].nextFree = NULL;
777 #define INITIALLOCKRECORDS 8
779 static pthread_mutex_t pool_lock;
780 static lockRecordPool *global_pool;
782 static void initPools()
784 pthread_mutex_init(&pool_lock, NULL);
787 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
789 pthread_mutex_lock(&pool_lock);
792 lockRecordPool *pool = global_pool;
793 global_pool = pool->header.next;
794 pthread_mutex_unlock(&pool_lock);
796 for (i=0; i < pool->header.size; i++)
797 pool->lr[i].ownerThread = t;
801 pthread_mutex_unlock(&pool_lock);
803 return allocNewLockRecordPool(t, size);
806 static void freeLockRecordPools(lockRecordPool *pool)
808 lockRecordPoolHeader *last;
809 pthread_mutex_lock(&pool_lock);
810 last = &pool->header;
812 last = &last->next->header;
813 last->next = global_pool;
815 pthread_mutex_unlock(&pool_lock);
818 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
820 monitorLockRecord *r = t->ee.firstLR;
823 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
824 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
825 pool->header.next = t->ee.lrpool;
828 t->ee.numlr += pool->header.size;
831 t->ee.firstLR = r->nextFree;
835 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
837 r->nextFree = t->ee.firstLR;
841 void initObjectLock(java_objectheader *o)
843 o->monitorPtr = dummyLR;
847 /* get_dummyLR *****************************************************************
849 Returns the global dummy monitor lock record. The pointer is
850 required in the code generator to set up a virtual
851 java_objectheader for code patch locking.
853 *******************************************************************************/
855 monitorLockRecord *get_dummyLR(void)
861 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
863 atomic_add(&lr->queuers, 1);
864 MEMORY_BARRIER_AFTER_ATOMIC();
866 sem_wait(&lr->queueSem);
867 atomic_add(&lr->queuers, -1);
870 static void freeLockRecord(monitorLockRecord *lr)
877 sem_post(&lr->queueSem);
880 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
886 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
889 monitorLockRecord *lr = o->monitorPtr;
891 monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
897 handleWaiter(mlr, lr);
901 if (lr->ownerThread != t)
903 MEMORY_BARRIER_BEFORE_ATOMIC();
904 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
907 if (mlr == lr || lr->o != o) {
908 handleWaiter(mlr, lr);
912 queueOnLockRecord(lr, o);
913 handleWaiter(mlr, lr);
917 recycleLockRecord(t, mlr);
918 queueOnLockRecord(nlr, o);
920 if (lr->ownerThread == t) {
924 queueOnLockRecord(lr, o);
929 static void wakeWaiters(monitorLockRecord *lr)
934 sem_post(&lr->queueSem);
939 #define GRAB_LR(lr,t) \
940 if (lr->ownerThread != t) { \
944 #define CHECK_MONITORSTATE(lr,t,mo,a) \
945 if (lr->o != mo || lr->ownerThread != t) { \
946 *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
950 bool monitorExit(threadobject *t, java_objectheader *o)
952 monitorLockRecord *lr = o->monitorPtr;
954 CHECK_MONITORSTATE(lr, t, o, return false);
955 if (lr->lockCount > 1) {
960 monitorLockRecord *wlr = lr->waiter;
961 if (o->monitorPtr != lr ||
962 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
964 monitorLockRecord *nlr = o->monitorPtr;
966 STORE_ORDER_BARRIER();
972 recycleLockRecord(t, lr);
976 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
979 if (lr->waiter == wlr) {
980 lr->waiter = wlr->waiter;
987 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
989 return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
992 static bool timeIsEarlier(const struct timespec *tv)
994 struct timeval tvnow;
995 struct timespec tsnow;
996 gettimeofday(&tvnow, NULL);
997 tsnow.tv_sec = tvnow.tv_sec;
998 tsnow.tv_nsec = tvnow.tv_usec * 1000;
999 return timespec_less(&tsnow, tv);
1002 bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
1004 bool wasinterrupted;
1006 pthread_mutex_lock(&t->waitLock);
1007 t->isSleeping = true;
1008 if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
1009 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
1010 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1012 while (!t->interrupted && !t->signaled)
1013 pthread_cond_wait(&t->waitCond, &t->waitLock);
1014 wasinterrupted = t->interrupted;
1015 t->interrupted = false;
1016 t->signaled = false;
1017 t->isSleeping = false;
1018 pthread_mutex_unlock(&t->waitLock);
1019 return wasinterrupted;
1022 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1024 if (millis || nanos) {
1027 gettimeofday(&tv, NULL);
1028 tv.tv_sec += millis / 1000;
1030 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1031 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1032 tm->tv_nsec = nsec % 1000000000;
1039 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1041 bool wasinterrupted;
1042 struct timespec wakeupTime;
1043 monitorLockRecord *mlr, *lr = o->monitorPtr;
1045 CHECK_MONITORSTATE(lr, t, o, return);
1047 calcAbsoluteTime(&wakeupTime, millis, nanos);
1050 wakeWaiters(lr->waiter);
1052 STORE_ORDER_BARRIER();
1054 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1055 mlr = monitorEnter(t, o);
1056 removeFromWaiters(mlr, lr);
1057 mlr->lockCount = lr->lockCount;
1059 lr->waiting = false;
1061 recycleLockRecord(t, lr);
1064 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1067 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1069 monitorLockRecord *lr = o->monitorPtr;
1071 CHECK_MONITORSTATE(lr, t, o, return);
1073 threadobject *wthread;
1074 monitorLockRecord *wlr = lr->waiter;
1077 wthread = wlr->ownerThread;
1078 pthread_mutex_lock(&wthread->waitLock);
1079 if (wthread->isSleeping)
1080 pthread_cond_signal(&wthread->waitCond);
1081 wthread->signaled = true;
1082 pthread_mutex_unlock(&wthread->waitLock);
1087 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1089 monitorLockRecord *lr = o->monitorPtr;
1091 /* The reason why we have to check against NULL is that
1092 * dummyLR->incharge == NULL */
1093 return lr && lr->o == o && lr->ownerThread == t;
1096 void interruptThread(java_lang_VMThread *thread)
1098 threadobject *t = (threadobject*) thread;
1100 t->interrupted = true;
1101 pthread_mutex_lock(&t->waitLock);
1103 pthread_cond_signal(&t->waitCond);
1104 pthread_mutex_unlock(&t->waitLock);
1107 bool interruptedThread()
1109 threadobject *t = (threadobject*) THREADOBJECT;
1110 bool intr = t->interrupted;
1111 t->interrupted = false;
1115 bool isInterruptedThread(java_lang_VMThread *thread)
1117 threadobject *t = (threadobject*) thread;
1118 return t->interrupted;
1121 void sleepThread(s8 millis, s4 nanos)
1123 bool wasinterrupted;
1124 threadobject *t = (threadobject*) THREADOBJECT;
1125 monitorLockRecord *lr;
1126 struct timespec wakeupTime;
1127 calcAbsoluteTime(&wakeupTime, millis, nanos);
1129 lr = allocLockRecordSimple(t);
1130 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1131 recycleLockRecord(t, lr);
1134 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1142 void setPriorityThread(thread *t, s4 priority)
1144 nativethread *info = &((threadobject*) t->vmThread)->info;
1145 setPriority(info->tid, priority);
1148 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1150 threadobject *t = (threadobject*) THREADOBJECT;
1151 monitorWait(t, o, time, nanos);
1154 void signal_cond_for_object(java_objectheader *o)
1156 threadobject *t = (threadobject*) THREADOBJECT;
1157 notifyOneOrAll(t, o, true);
1160 void broadcast_cond_for_object(java_objectheader *o)
1162 threadobject *t = (threadobject*) THREADOBJECT;
1163 notifyOneOrAll(t, o, false);
1167 /* thread_dump *****************************************************************
1169 Dumps info for all threads running in the JVM. This function is
1170 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1172 *******************************************************************************/
1174 void thread_dump(void)
1178 java_lang_VMThread *vmt;
1179 java_lang_Thread *t;
1182 tobj = mainthreadobj;
1184 printf("Full thread dump CACAO "VERSION"\n");
1186 /* iterate over all started threads */
1189 /* get thread objects */
1195 /* get thread name */
1197 name = javastring_toutf(t->name, false);
1201 #if SIZEOF_VOID_P == 8
1202 printf("\" prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1204 printf("\" prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1207 /* TODO: print stacktrace */
1209 tobj = tobj->info.next;
1210 } while (tobj != mainthreadobj);
1215 * These are local overrides for various environment variables in Emacs.
1216 * Please do not remove this and leave it at the end of the file, where
1217 * Emacs will automagically detect them.
1218 * ---------------------------------------------------------------------
1221 * indent-tabs-mode: t