1 /* 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 $Id: threads.c 2348 2005-04-22 13:52:35Z twisti $
37 #include <sys/types.h>
47 #include "mm/memory.h"
48 #include "native/native.h"
49 #include "native/include/java_lang_Object.h"
50 #include "native/include/java_lang_Throwable.h"
51 #include "native/include/java_lang_Thread.h"
52 #include "native/include/java_lang_ThreadGroup.h"
53 #include "native/include/java_lang_VMThread.h"
54 #include "threads/native/threads.h"
55 #include "toolbox/avl.h"
56 #include "toolbox/logging.h"
57 #include "vm/builtin.h"
58 #include "vm/exceptions.h"
59 #include "vm/global.h"
60 #include "vm/loader.h"
61 #include "vm/stringlocal.h"
62 #include "vm/tables.h"
63 #include "vm/jit/asmpart.h"
66 #include <semaphore.h>
68 #if !defined(__DARWIN__)
69 #if defined(__LINUX__)
70 #define GC_LINUX_THREADS
71 #elif defined(__MIPS__)
72 #define GC_IRIX_THREADS
74 #include "boehm-gc/include/gc.h"
79 /* We need this for older MacOSX (10.1.x) */
82 pthread_mutex_t mutex;
85 } pthread_mutex_rec_t;
87 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
89 pthread_mutex_init(&m->mutex, NULL);
93 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
95 pthread_mutex_destroy(&m->mutex);
98 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
103 pthread_mutex_lock(&m->mutex);
104 m->owner = pthread_self();
108 if (m->owner != pthread_self())
109 pthread_mutex_lock(&m->mutex);
118 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
121 pthread_mutex_unlock(&m->mutex);
126 #define pthread_mutex_lock_rec pthread_mutex_lock
127 #define pthread_mutex_unlock_rec pthread_mutex_unlock
128 #define pthread_mutex_rec_t pthread_mutex_t
130 #endif /* MUTEXSIM */
132 static void setPriority(pthread_t tid, int priority)
134 struct sched_param schedp;
137 pthread_getschedparam(tid, &policy, &schedp);
138 schedp.sched_priority = priority;
139 pthread_setschedparam(tid, policy, &schedp);
142 #include "machine-instr.h"
144 static struct avl_table *criticaltree;
145 static threadobject *mainthreadobj;
147 #ifndef HAVE___THREAD
148 pthread_key_t tkey_threadinfo;
150 __thread threadobject *threadobj;
153 static pthread_mutex_rec_t compiler_mutex;
154 static pthread_mutex_rec_t tablelock;
158 pthread_mutex_lock_rec(&compiler_mutex);
161 void compiler_unlock()
163 pthread_mutex_unlock_rec(&compiler_mutex);
168 pthread_mutex_lock_rec(&tablelock);
173 pthread_mutex_unlock_rec(&tablelock);
176 static int criticalcompare(const void *pa, const void *pb, void *param)
178 const threadcritnode *na = pa;
179 const threadcritnode *nb = pb;
181 if (na->mcodebegin < nb->mcodebegin)
183 if (na->mcodebegin > nb->mcodebegin)
188 static const threadcritnode *findcritical(u1 *mcodeptr)
190 struct avl_node *n = criticaltree->avl_root;
191 const threadcritnode *m = NULL;
196 const threadcritnode *d = n->avl_data;
197 if (mcodeptr == d->mcodebegin)
199 if (mcodeptr < d->mcodebegin) {
205 if (n->avl_link[1]) {
214 void thread_registercritical(threadcritnode *n)
216 avl_insert(criticaltree, n);
219 u1 *thread_checkcritical(u1 *mcodeptr)
221 const threadcritnode *n = findcritical(mcodeptr);
222 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
225 static void thread_addstaticcritical()
227 threadcritnode *n = &asm_criticalsections;
229 while (n->mcodebegin)
230 thread_registercritical(n++);
233 static pthread_mutex_t threadlistlock;
235 static pthread_mutex_t stopworldlock;
236 volatile int stopworldwhere;
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;
245 * where - 1 from within GC
248 void lock_stopworld(int where)
250 pthread_mutex_lock(&stopworldlock);
251 stopworldwhere = where;
254 void unlock_stopworld()
257 pthread_mutex_unlock(&stopworldlock);
260 #if !defined(__DARWIN__)
261 /* Caller must hold threadlistlock */
262 static int cast_sendsignals(int sig, int count)
265 threadobject *tobj = mainthreadobj;
266 nativethread *infoself = THREADINFO;
271 tobj = tobj->info.next;
272 } while (tobj != mainthreadobj);
275 nativethread *info = &tobj->info;
276 if (info != infoself)
277 pthread_kill(info->tid, sig);
278 tobj = tobj->info.next;
279 } while (tobj != mainthreadobj);
286 static void cast_darwinstop()
288 threadobject *tobj = mainthreadobj;
289 nativethread *infoself = THREADINFO;
292 nativethread *info = &tobj->info;
293 if (info != infoself)
295 thread_state_flavor_t flavor = PPC_THREAD_STATE;
296 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
297 ppc_thread_state_t thread_state;
298 mach_port_t thread = info->mach_thread;
301 r = thread_suspend(thread);
302 if (r != KERN_SUCCESS)
303 panic("thread_suspend failed");
305 r = thread_get_state(thread, flavor,
306 (natural_t*)&thread_state, &thread_state_count);
307 if (r != KERN_SUCCESS)
308 panic("thread_get_state failed");
310 thread_restartcriticalsection(&thread_state);
312 r = thread_set_state(thread, flavor,
313 (natural_t*)&thread_state, thread_state_count);
314 if (r != KERN_SUCCESS)
315 panic("thread_set_state failed");
317 tobj = tobj->info.next;
318 } while (tobj != mainthreadobj);
321 static void cast_darwinresume()
323 threadobject *tobj = mainthreadobj;
324 nativethread *infoself = THREADINFO;
327 nativethread *info = &tobj->info;
328 if (info != infoself)
330 mach_port_t thread = info->mach_thread;
333 r = thread_resume(thread);
334 if (r != KERN_SUCCESS)
335 panic("thread_resume failed");
337 tobj = tobj->info.next;
338 } while (tobj != mainthreadobj);
343 #if defined(__MIPS__)
344 static void cast_irixresume()
346 pthread_mutex_lock(&suspend_ack_lock);
347 pthread_cond_broadcast(&suspend_cond);
348 pthread_mutex_unlock(&suspend_ack_lock);
352 void cast_stopworld()
356 pthread_mutex_lock(&threadlistlock);
357 #if defined(__DARWIN__)
360 count = cast_sendsignals(GC_signum1(), 0);
361 for (i=0; i<count; i++)
362 sem_wait(&suspend_ack);
364 pthread_mutex_unlock(&threadlistlock);
367 void cast_startworld()
369 pthread_mutex_lock(&threadlistlock);
370 #if defined(__DARWIN__)
372 #elif defined(__MIPS__)
375 cast_sendsignals(GC_signum2(), -1);
377 pthread_mutex_unlock(&threadlistlock);
381 #if !defined(__DARWIN__)
382 static void sigsuspend_handler(ucontext_t *ctx)
387 thread_restartcriticalsection(ctx);
389 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
390 (not POSIX async-safe). */
391 #if defined(__IRIX__)
392 pthread_mutex_lock(&suspend_ack_lock);
393 sem_post(&suspend_ack);
394 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
395 pthread_mutex_unlock(&suspend_ack_lock);
397 sem_post(&suspend_ack);
401 sigdelset(&sigs, sig);
406 int cacao_suspendhandler(ucontext_t *ctx)
408 if (stopworldwhere != 2)
411 sigsuspend_handler(ctx);
416 static void setthreadobject(threadobject *thread)
418 #if !defined(HAVE___THREAD)
419 pthread_setspecific(tkey_threadinfo, thread);
425 static monitorLockRecord *dummyLR;
427 static void initPools();
430 * Initialize threads.
436 pthread_mutexattr_t mutexattr;
437 pthread_mutexattr_init(&mutexattr);
438 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
439 pthread_mutex_init(&compiler_mutex, &mutexattr);
440 pthread_mutex_init(&tablelock, &mutexattr);
441 pthread_mutexattr_destroy(&mutexattr);
443 pthread_mutex_init_rec(&compiler_mutex);
444 pthread_mutex_init_rec(&tablelock);
447 pthread_mutex_init(&threadlistlock, NULL);
448 pthread_mutex_init(&stopworldlock, NULL);
450 /* Allocate something so the garbage collector's signal handlers are */
452 heap_allocate(1, false, NULL);
454 mainthreadobj = NEW(threadobject);
455 mainthreadobj->info.tid = pthread_self();
456 #if !defined(HAVE___THREAD)
457 pthread_key_create(&tkey_threadinfo, NULL);
459 setthreadobject(mainthreadobj);
462 criticaltree = avl_create(criticalcompare, NULL, NULL);
463 thread_addstaticcritical();
464 sem_init(&suspend_ack, 0, 0);
466 /* Every newly created object's monitorPtr points here so we save a check
468 dummyLR = NEW(monitorLockRecord);
470 dummyLR->ownerThread = NULL;
471 dummyLR->waiting = false;
474 static pthread_attr_t threadattr;
476 static void freeLockRecordPools(lockRecordPool *);
479 initThreads(u1 *stackbottom)
481 classinfo *threadclass;
482 java_lang_String *threadname;
483 java_lang_Thread *mainthread;
484 java_lang_ThreadGroup *threadgroup;
485 threadobject *tempthread = mainthreadobj;
488 if (!load_class_bootstrap(utf_new_char("java/lang/VMThread"),&threadclass))
489 throw_exception_exit();
491 throw_exception_exit();
492 if (!link_class(threadclass))
493 throw_exception_exit();
495 freeLockRecordPools(mainthreadobj->ee.lrpool);
496 /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
497 * the execution environment there. No Thread object must have been created
498 * at an earlier time */
499 threadclass->instancesize = sizeof(threadobject);
501 /* Create a VMThread */
502 mainthreadobj = (threadobject *) builtin_new(threadclass);
505 throw_exception_exit();
507 FREE(tempthread, threadobject);
508 initThread(&mainthreadobj->o);
510 setthreadobject(mainthreadobj);
513 mainthreadobj->info.next = mainthreadobj;
514 mainthreadobj->info.prev = mainthreadobj;
516 threadname = javastring_new(utf_new_char("main"));
518 /* Allocate and init ThreadGroup */
520 threadgroup = (java_lang_ThreadGroup *)
521 native_new_and_init(class_java_lang_ThreadGroup);
524 throw_exception_exit();
526 /* Create a Thread */
527 if (!load_class_bootstrap(utf_new_char("java/lang/Thread"),&threadclass))
528 throw_exception_exit();
529 mainthread = (java_lang_Thread*) builtin_new(threadclass);
530 mainthreadobj->o.thread = mainthread;
533 throw_exception_exit();
535 /* Call Thread constructor */
536 method = class_resolveclassmethod(threadclass,
538 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
543 throw_exception_exit();
545 asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
547 throw_exception_exit();
549 mainthread->group = threadgroup;
550 /* XXX This is a hack because the fourth argument was omitted */
551 mainthread->daemon = false;
553 /* Add mainthread to ThreadGroup */
554 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
555 utf_new_char("addThread"),
556 utf_new_char("(Ljava/lang/Thread;)V"),
557 class_java_lang_ThreadGroup,
561 throw_exception_exit();
563 asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
565 throw_exception_exit();
567 setPriority(pthread_self(), 5);
569 pthread_attr_init(&threadattr);
570 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
573 void initThread(java_lang_VMThread *t)
575 threadobject *thread = (threadobject*) t;
576 nativethread *info = &thread->info;
577 info->tid = pthread_self();
578 /* TODO destroy all those things */
579 pthread_mutex_init(&info->joinMutex, NULL);
580 pthread_cond_init(&info->joinCond, NULL);
582 pthread_mutex_init(&thread->waitLock, NULL);
583 pthread_cond_init(&thread->waitCond, NULL);
584 thread->interrupted = false;
585 thread->signaled = false;
586 thread->isSleeping = false;
589 static void initThreadLocks(threadobject *);
592 threadobject *thread;
596 static void *threadstartup(void *t)
598 startupinfo *startup = t;
599 threadobject *thread = startup->thread;
600 sem_t *psem = startup->psem;
601 nativethread *info = &thread->info;
606 #if defined(__DARWIN__)
607 info->mach_thread = mach_thread_self();
609 setthreadobject(thread);
611 pthread_mutex_lock(&threadlistlock);
612 info->prev = mainthreadobj;
613 info->next = tnext = mainthreadobj->info.next;
614 mainthreadobj->info.next = thread;
615 tnext->info.prev = thread;
616 pthread_mutex_unlock(&threadlistlock);
618 initThreadLocks(thread);
623 setPriority(info->tid, thread->o.thread->priority);
626 /* Find the run()V method and call it */
627 method = class_resolveclassmethod(thread->o.header.vftbl->class,
630 thread->o.header.vftbl->class,
633 /* if method != NULL, we had not exception */
635 asm_calljavafunction(method, thread, NULL, NULL, NULL);
641 /* Allow lock record pools to be used by other threads. They cannot be
642 * deleted so we'd better not waste them. */
643 freeLockRecordPools(thread->ee.lrpool);
645 pthread_mutex_lock(&threadlistlock);
646 info->next->info.prev = info->prev;
647 info->prev->info.next = info->next;
648 pthread_mutex_unlock(&threadlistlock);
650 pthread_mutex_lock(&info->joinMutex);
652 pthread_mutex_unlock(&info->joinMutex);
653 pthread_cond_broadcast(&info->joinCond);
658 void startThread(thread *t)
660 nativethread *info = &((threadobject*) t->vmThread)->info;
664 startup.thread = (threadobject*) t->vmThread;
667 sem_init(&sem, 0, 0);
669 if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
670 panic("pthread_create failed");
672 /* Wait here until the thread has entered itself into the thread list */
677 /* At the end of the program, we wait for all running non-daemon threads to die
680 static threadobject *findNonDaemon(threadobject *thread)
682 while (thread != mainthreadobj) {
683 if (!thread->o.thread->daemon)
685 thread = thread->info.prev;
691 void joinAllThreads()
693 threadobject *thread;
694 pthread_mutex_lock(&threadlistlock);
695 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
696 nativethread *info = &thread->info;
697 pthread_mutex_lock(&info->joinMutex);
698 pthread_mutex_unlock(&threadlistlock);
700 pthread_cond_wait(&info->joinCond, &info->joinMutex);
701 pthread_mutex_unlock(&info->joinMutex);
702 pthread_mutex_lock(&threadlistlock);
704 pthread_mutex_unlock(&threadlistlock);
707 static void initLockRecord(monitorLockRecord *r, threadobject *t)
714 r->incharge = (monitorLockRecord *) &dummyLR;
716 sem_init(&r->queueSem, 0, 0);
717 pthread_mutex_init(&r->resolveLock, NULL);
718 pthread_cond_init(&r->resolveWait, NULL);
721 /* No lock record must ever be destroyed because there may still be references
724 static void destroyLockRecord(monitorLockRecord *r)
726 sem_destroy(&r->queueSem);
727 pthread_mutex_destroy(&r->resolveLock);
728 pthread_cond_destroy(&r->resolveWait);
734 initThreadLocks(mainthreadobj);
737 static void initThreadLocks(threadobject *thread)
739 thread->ee.firstLR = NULL;
740 thread->ee.lrpool = NULL;
741 thread->ee.numlr = 0;
744 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
746 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
749 p->header.size = size;
750 for (i=0; i<size; i++) {
751 initLockRecord(&p->lr[i], thread);
752 p->lr[i].nextFree = &p->lr[i+1];
754 p->lr[i-1].nextFree = NULL;
758 #define INITIALLOCKRECORDS 8
760 static pthread_mutex_t pool_lock;
761 static lockRecordPool *global_pool;
763 static void initPools()
765 pthread_mutex_init(&pool_lock, NULL);
768 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
770 pthread_mutex_lock(&pool_lock);
773 lockRecordPool *pool = global_pool;
774 global_pool = pool->header.next;
775 pthread_mutex_unlock(&pool_lock);
777 for (i=0; i < pool->header.size; i++)
778 pool->lr[i].ownerThread = t;
782 pthread_mutex_unlock(&pool_lock);
784 return allocNewLockRecordPool(t, size);
787 static void freeLockRecordPools(lockRecordPool *pool)
789 lockRecordPoolHeader *last;
790 pthread_mutex_lock(&pool_lock);
791 last = &pool->header;
793 last = &last->next->header;
794 last->next = global_pool;
796 pthread_mutex_unlock(&pool_lock);
799 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
801 monitorLockRecord *r = t->ee.firstLR;
804 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
805 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
806 pool->header.next = t->ee.lrpool;
809 t->ee.numlr += pool->header.size;
812 t->ee.firstLR = r->nextFree;
816 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
818 r->nextFree = t->ee.firstLR;
822 void initObjectLock(java_objectheader *o)
824 o->monitorPtr = dummyLR;
827 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
829 atomic_add(&lr->queuers, 1);
830 MEMORY_BARRIER_AFTER_ATOMIC();
832 sem_wait(&lr->queueSem);
833 atomic_add(&lr->queuers, -1);
836 static void freeLockRecord(monitorLockRecord *lr)
843 sem_post(&lr->queueSem);
846 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
852 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
855 monitorLockRecord *lr = o->monitorPtr;
857 monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
863 handleWaiter(mlr, lr);
867 if (lr->ownerThread != t)
869 MEMORY_BARRIER_BEFORE_ATOMIC();
870 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
873 if (mlr == lr || lr->o != o) {
874 handleWaiter(mlr, lr);
878 queueOnLockRecord(lr, o);
879 handleWaiter(mlr, lr);
883 recycleLockRecord(t, mlr);
884 queueOnLockRecord(nlr, o);
886 if (lr->ownerThread == t) {
890 queueOnLockRecord(lr, o);
895 static void wakeWaiters(monitorLockRecord *lr)
900 sem_post(&lr->queueSem);
905 #define GRAB_LR(lr,t) \
906 if (lr->ownerThread != t) { \
910 #define CHECK_MONITORSTATE(lr,t,mo,a) \
911 if (lr->o != mo || lr->ownerThread != t) { \
912 *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
916 bool monitorExit(threadobject *t, java_objectheader *o)
918 monitorLockRecord *lr = o->monitorPtr;
920 CHECK_MONITORSTATE(lr, t, o, return false);
921 if (lr->lockCount > 1) {
926 monitorLockRecord *wlr = lr->waiter;
927 if (o->monitorPtr != lr ||
928 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
930 monitorLockRecord *nlr = o->monitorPtr;
932 STORE_ORDER_BARRIER();
938 recycleLockRecord(t, lr);
942 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
945 if (lr->waiter == wlr) {
946 lr->waiter = wlr->waiter;
953 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
955 return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
958 static bool timeIsEarlier(const struct timespec *tv)
960 struct timeval tvnow;
961 struct timespec tsnow;
962 gettimeofday(&tvnow, NULL);
963 tsnow.tv_sec = tvnow.tv_sec;
964 tsnow.tv_nsec = tvnow.tv_usec * 1000;
965 return timespec_less(&tsnow, tv);
968 bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
972 pthread_mutex_lock(&t->waitLock);
973 t->isSleeping = true;
974 if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
975 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
976 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
978 while (!t->interrupted && !t->signaled)
979 pthread_cond_wait(&t->waitCond, &t->waitLock);
980 wasinterrupted = t->interrupted;
981 t->interrupted = false;
983 t->isSleeping = false;
984 pthread_mutex_unlock(&t->waitLock);
985 return wasinterrupted;
988 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
990 if (millis || nanos) {
993 gettimeofday(&tv, NULL);
994 tv.tv_sec += millis / 1000;
996 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
997 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
998 tm->tv_nsec = nsec % 1000000000;
1005 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1007 bool wasinterrupted;
1008 struct timespec wakeupTime;
1009 monitorLockRecord *mlr, *lr = o->monitorPtr;
1011 CHECK_MONITORSTATE(lr, t, o, return);
1013 calcAbsoluteTime(&wakeupTime, millis, nanos);
1016 wakeWaiters(lr->waiter);
1018 STORE_ORDER_BARRIER();
1020 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1021 mlr = monitorEnter(t, o);
1022 removeFromWaiters(mlr, lr);
1023 mlr->lockCount = lr->lockCount;
1025 lr->waiting = false;
1027 recycleLockRecord(t, lr);
1030 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1033 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1035 monitorLockRecord *lr = o->monitorPtr;
1037 CHECK_MONITORSTATE(lr, t, o, return);
1039 threadobject *wthread;
1040 monitorLockRecord *wlr = lr->waiter;
1043 wthread = wlr->ownerThread;
1044 pthread_mutex_lock(&wthread->waitLock);
1045 if (wthread->isSleeping)
1046 pthread_cond_signal(&wthread->waitCond);
1047 wthread->signaled = true;
1048 pthread_mutex_unlock(&wthread->waitLock);
1053 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1055 monitorLockRecord *lr = o->monitorPtr;
1057 return lr && lr->o == o && lr->ownerThread == t;
1060 void interruptThread(java_lang_VMThread *thread)
1062 threadobject *t = (threadobject*) thread;
1064 t->interrupted = true;
1065 pthread_mutex_lock(&t->waitLock);
1067 pthread_cond_signal(&t->waitCond);
1068 pthread_mutex_unlock(&t->waitLock);
1071 bool interruptedThread()
1073 threadobject *t = (threadobject*) THREADOBJECT;
1074 bool intr = t->interrupted;
1075 t->interrupted = false;
1079 bool isInterruptedThread(java_lang_VMThread *thread)
1081 threadobject *t = (threadobject*) thread;
1082 return t->interrupted;
1085 void sleepThread(s8 millis, s4 nanos)
1087 bool wasinterrupted;
1088 threadobject *t = (threadobject*) THREADOBJECT;
1089 monitorLockRecord *lr;
1090 struct timespec wakeupTime;
1091 calcAbsoluteTime(&wakeupTime, millis, nanos);
1093 lr = allocLockRecordSimple(t);
1094 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1095 recycleLockRecord(t, lr);
1098 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1106 void setPriorityThread(thread *t, s4 priority)
1108 nativethread *info = &((threadobject*) t->vmThread)->info;
1109 setPriority(info->tid, priority);
1112 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1114 threadobject *t = (threadobject*) THREADOBJECT;
1115 monitorWait(t, o, time, nanos);
1118 void signal_cond_for_object(java_objectheader *o)
1120 threadobject *t = (threadobject*) THREADOBJECT;
1121 notifyOneOrAll(t, o, true);
1124 void broadcast_cond_for_object(java_objectheader *o)
1126 threadobject *t = (threadobject*) THREADOBJECT;
1127 notifyOneOrAll(t, o, false);
1132 * These are local overrides for various environment variables in Emacs.
1133 * Please do not remove this and leave it at the end of the file, where
1134 * Emacs will automagically detect them.
1135 * ---------------------------------------------------------------------
1138 * indent-tabs-mode: t