14 #include "mm/memory.h"
15 #include "native/native.h"
16 #include "native/include/java_lang_Object.h"
17 #include "native/include/java_lang_Throwable.h"
18 #include "native/include/java_lang_Thread.h"
19 #include "native/include/java_lang_ThreadGroup.h"
20 #include "native/include/java_lang_VMThread.h"
21 #include "threads/native/threads.h"
22 #include "toolbox/avl.h"
23 #include "toolbox/logging.h"
24 #include "vm/builtin.h"
25 #include "vm/exceptions.h"
26 #include "vm/global.h"
27 #include "vm/loader.h"
28 #include "vm/tables.h"
29 #include "vm/jit/asmpart.h"
32 #include <semaphore.h>
34 #if !defined(__DARWIN__)
35 #if defined(__LINUX__)
36 #define GC_LINUX_THREADS
37 #elif defined(__MIPS__)
38 #define GC_IRIX_THREADS
40 #include "boehm-gc/include/gc.h"
45 /* We need this for older MacOSX (10.1.x) */
48 pthread_mutex_t mutex;
51 } pthread_mutex_rec_t;
53 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
55 pthread_mutex_init(&m->mutex, NULL);
59 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
61 pthread_mutex_destroy(&m->mutex);
64 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
69 pthread_mutex_lock(&m->mutex);
70 m->owner = pthread_self();
74 if (m->owner != pthread_self())
75 pthread_mutex_lock(&m->mutex);
84 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
87 pthread_mutex_unlock(&m->mutex);
92 #define pthread_mutex_lock_rec pthread_mutex_lock
93 #define pthread_mutex_unlock_rec pthread_mutex_unlock
94 #define pthread_mutex_rec_t pthread_mutex_t
98 static void setPriority(pthread_t tid, int priority)
100 struct sched_param schedp;
103 pthread_getschedparam(tid, &policy, &schedp);
104 schedp.sched_priority = priority;
105 pthread_setschedparam(tid, policy, &schedp);
108 #include "machine-instr.h"
110 static struct avl_table *criticaltree;
111 static threadobject *mainthreadobj;
113 #ifndef HAVE___THREAD
114 pthread_key_t tkey_threadinfo;
116 __thread threadobject *threadobj;
119 static pthread_mutex_rec_t compiler_mutex;
120 static pthread_mutex_rec_t tablelock;
124 pthread_mutex_lock_rec(&compiler_mutex);
127 void compiler_unlock()
129 pthread_mutex_unlock_rec(&compiler_mutex);
134 pthread_mutex_lock_rec(&tablelock);
139 pthread_mutex_unlock_rec(&tablelock);
142 static int criticalcompare(const void *pa, const void *pb, void *param)
144 const threadcritnode *na = pa;
145 const threadcritnode *nb = pb;
147 if (na->mcodebegin < nb->mcodebegin)
149 if (na->mcodebegin > nb->mcodebegin)
154 static const threadcritnode *findcritical(u1 *mcodeptr)
156 struct avl_node *n = criticaltree->avl_root;
157 const threadcritnode *m = NULL;
162 const threadcritnode *d = n->avl_data;
163 if (mcodeptr == d->mcodebegin)
165 if (mcodeptr < d->mcodebegin) {
171 if (n->avl_link[1]) {
180 void thread_registercritical(threadcritnode *n)
182 avl_insert(criticaltree, n);
185 u1 *thread_checkcritical(u1 *mcodeptr)
187 const threadcritnode *n = findcritical(mcodeptr);
188 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
191 static void thread_addstaticcritical()
193 threadcritnode *n = &asm_criticalsections;
195 while (n->mcodebegin)
196 thread_registercritical(n++);
199 static pthread_mutex_t threadlistlock;
201 static pthread_mutex_t stopworldlock;
202 volatile int stopworldwhere;
204 static sem_t suspend_ack;
205 #if defined(__MIPS__)
206 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
207 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
211 * where - 1 from within GC
214 void lock_stopworld(int where)
216 pthread_mutex_lock(&stopworldlock);
217 stopworldwhere = where;
220 void unlock_stopworld()
223 pthread_mutex_unlock(&stopworldlock);
226 #if !defined(__DARWIN__)
227 /* Caller must hold threadlistlock */
228 static int cast_sendsignals(int sig, int count)
231 threadobject *tobj = mainthreadobj;
232 nativethread *infoself = THREADINFO;
237 tobj = tobj->info.next;
238 } while (tobj != mainthreadobj);
241 nativethread *info = &tobj->info;
242 if (info != infoself)
243 pthread_kill(info->tid, sig);
244 tobj = tobj->info.next;
245 } while (tobj != mainthreadobj);
252 static void cast_darwinstop()
254 threadobject *tobj = mainthreadobj;
255 nativethread *infoself = THREADINFO;
258 nativethread *info = &tobj->info;
259 if (info != infoself)
261 thread_state_flavor_t flavor = PPC_THREAD_STATE;
262 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
263 ppc_thread_state_t thread_state;
264 mach_port_t thread = info->mach_thread;
267 r = thread_suspend(thread);
268 if (r != KERN_SUCCESS)
269 panic("thread_suspend failed");
271 r = thread_get_state(thread, flavor,
272 (natural_t*)&thread_state, &thread_state_count);
273 if (r != KERN_SUCCESS)
274 panic("thread_get_state failed");
276 thread_restartcriticalsection(&thread_state);
278 r = thread_set_state(thread, flavor,
279 (natural_t*)&thread_state, thread_state_count);
280 if (r != KERN_SUCCESS)
281 panic("thread_set_state failed");
283 tobj = tobj->info.next;
284 } while (tobj != mainthreadobj);
287 static void cast_darwinresume()
289 threadobject *tobj = mainthreadobj;
290 nativethread *infoself = THREADINFO;
293 nativethread *info = &tobj->info;
294 if (info != infoself)
296 mach_port_t thread = info->mach_thread;
299 r = thread_resume(thread);
300 if (r != KERN_SUCCESS)
301 panic("thread_resume failed");
303 tobj = tobj->info.next;
304 } while (tobj != mainthreadobj);
309 #if defined(__MIPS__)
310 static void cast_irixresume()
312 pthread_mutex_lock(&suspend_ack_lock);
313 pthread_cond_broadcast(&suspend_cond);
314 pthread_mutex_unlock(&suspend_ack_lock);
318 void cast_stopworld()
322 pthread_mutex_lock(&threadlistlock);
323 #if defined(__DARWIN__)
326 count = cast_sendsignals(GC_signum1(), 0);
327 for (i=0; i<count; i++)
328 sem_wait(&suspend_ack);
330 pthread_mutex_unlock(&threadlistlock);
333 void cast_startworld()
335 pthread_mutex_lock(&threadlistlock);
336 #if defined(__DARWIN__)
338 #elif defined(__MIPS__)
341 cast_sendsignals(GC_signum2(), -1);
343 pthread_mutex_unlock(&threadlistlock);
347 #if !defined(__DARWIN__)
348 static void sigsuspend_handler(ucontext_t *ctx)
353 thread_restartcriticalsection(ctx);
355 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
356 (not POSIX async-safe). */
357 #if defined(__IRIX__)
358 pthread_mutex_lock(&suspend_ack_lock);
359 sem_post(&suspend_ack);
360 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
361 pthread_mutex_unlock(&suspend_ack_lock);
363 sem_post(&suspend_ack);
367 sigdelset(&sigs, sig);
372 int cacao_suspendhandler(ucontext_t *ctx)
374 if (stopworldwhere != 2)
377 sigsuspend_handler(ctx);
382 static void setthreadobject(threadobject *thread)
384 #if !defined(HAVE___THREAD)
385 pthread_setspecific(tkey_threadinfo, thread);
391 static monitorLockRecord *dummyLR;
393 static void initPools();
396 * Initialize threads.
402 pthread_mutexattr_t mutexattr;
403 pthread_mutexattr_init(&mutexattr);
404 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
405 pthread_mutex_init(&compiler_mutex, &mutexattr);
406 pthread_mutex_init(&tablelock, &mutexattr);
407 pthread_mutexattr_destroy(&mutexattr);
409 pthread_mutex_init_rec(&compiler_mutex);
410 pthread_mutex_init_rec(&tablelock);
413 pthread_mutex_init(&threadlistlock, NULL);
414 pthread_mutex_init(&stopworldlock, NULL);
416 /* Allocate something so the garbage collector's signal handlers are */
418 heap_allocate(1, false, NULL);
420 mainthreadobj = NEW(threadobject);
421 memset(mainthreadobj, 0, sizeof(threadobject));
422 mainthreadobj->info.tid = pthread_self();
423 #if !defined(HAVE___THREAD)
424 pthread_key_create(&tkey_threadinfo, NULL);
426 setthreadobject(mainthreadobj);
429 criticaltree = avl_create(criticalcompare, NULL, NULL);
430 thread_addstaticcritical();
431 sem_init(&suspend_ack, 0, 0);
433 /* Every newly created object's monitorPtr points here so we save a check
435 dummyLR = mem_alloc(sizeof(monitorLockRecord));
437 dummyLR->ownerThread = NULL;
438 dummyLR->waiting = false;
441 static pthread_attr_t threadattr;
443 static void freeLockRecordPools(lockRecordPool *);
446 initThreads(u1 *stackbottom)
448 classinfo *threadclass;
449 classinfo *threadgroupclass;
450 java_lang_String *threadname;
451 java_lang_Thread *mainthread;
452 java_lang_ThreadGroup *threadgroup;
453 threadobject *tempthread = mainthreadobj;
456 threadclass = class_new(utf_new_char("java/lang/VMThread"));
457 class_load(threadclass);
458 class_link(threadclass);
461 throw_exception_exit();
463 freeLockRecordPools(mainthreadobj->ee.lrpool);
464 /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
465 * the execution environment there. No Thread object must have been created
466 * at an earlier time */
467 threadclass->instancesize = sizeof(threadobject);
469 /* Create a VMThread */
470 mainthreadobj = (threadobject *) builtin_new(threadclass);
473 throw_exception_exit();
475 FREE(tempthread, threadobject);
476 initThread(&mainthreadobj->o);
478 setthreadobject(mainthreadobj);
481 mainthreadobj->info.next = mainthreadobj;
482 mainthreadobj->info.prev = mainthreadobj;
484 threadname = javastring_new(utf_new_char("main"));
486 /* Allocate and init ThreadGroup */
487 threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
489 (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
492 throw_exception_exit();
494 /* Create a Thread */
495 threadclass = class_new(utf_new_char("java/lang/Thread"));
496 mainthread = (java_lang_Thread*) builtin_new(threadclass);
497 mainthreadobj->o.thread = mainthread;
500 throw_exception_exit();
502 /* Call Thread constructor */
503 method = class_resolveclassmethod(threadclass,
504 utf_new_char("<init>"),
505 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
510 throw_exception_exit();
512 asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
514 throw_exception_exit();
516 mainthread->group = threadgroup;
517 /* XXX This is a hack because the fourth argument was omitted */
518 mainthread->daemon = false;
520 /* Add mainthread to ThreadGroup */
521 method = class_resolveclassmethod(threadgroupclass,
522 utf_new_char("addThread"),
523 utf_new_char("(Ljava/lang/Thread;)V"),
528 throw_exception_exit();
530 asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
532 throw_exception_exit();
534 setPriority(pthread_self(), 5);
536 pthread_attr_init(&threadattr);
537 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
540 void initThread(java_lang_VMThread *t)
542 threadobject *thread = (threadobject*) t;
543 nativethread *info = &thread->info;
544 info->tid = pthread_self();
545 /* TODO destroy all those things */
546 pthread_mutex_init(&info->joinMutex, NULL);
547 pthread_cond_init(&info->joinCond, NULL);
549 pthread_mutex_init(&thread->waitLock, NULL);
550 pthread_cond_init(&thread->waitCond, NULL);
551 thread->interrupted = false;
552 thread->signaled = false;
553 thread->isSleeping = false;
556 static void initThreadLocks(threadobject *);
559 threadobject *thread;
563 static void *threadstartup(void *t)
565 startupinfo *startup = t;
566 threadobject *thread = startup->thread;
567 sem_t *psem = startup->psem;
568 nativethread *info = &thread->info;
573 #if defined(__DARWIN__)
574 info->mach_thread = mach_thread_self();
576 setthreadobject(thread);
578 pthread_mutex_lock(&threadlistlock);
579 info->prev = mainthreadobj;
580 info->next = tnext = mainthreadobj->info.next;
581 mainthreadobj->info.next = thread;
582 tnext->info.prev = thread;
583 pthread_mutex_unlock(&threadlistlock);
585 initThreadLocks(thread);
590 setPriority(info->tid, thread->o.thread->priority);
593 /* Find the run()V method and call it */
594 method = class_resolveclassmethod(thread->o.header.vftbl->class,
597 thread->o.header.vftbl->class,
600 /* if method != NULL, we had not exception */
602 asm_calljavafunction(method, thread, NULL, NULL, NULL);
608 /* Allow lock record pools to be used by other threads. They cannot be
609 * deleted so we'd better not waste them. */
610 freeLockRecordPools(thread->ee.lrpool);
612 pthread_mutex_lock(&threadlistlock);
613 info->next->info.prev = info->prev;
614 info->prev->info.next = info->next;
615 pthread_mutex_unlock(&threadlistlock);
617 pthread_mutex_lock(&info->joinMutex);
619 pthread_mutex_unlock(&info->joinMutex);
620 pthread_cond_broadcast(&info->joinCond);
625 void startThread(thread *t)
627 nativethread *info = &((threadobject*) t->vmThread)->info;
631 startup.thread = (threadobject*) t->vmThread;
634 sem_init(&sem, 0, 0);
636 if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
637 panic("pthread_create failed");
639 /* Wait here until the thread has entered itself into the thread list */
644 /* At the end of the program, we wait for all running non-daemon threads to die
647 static threadobject *findNonDaemon(threadobject *thread)
649 while (thread != mainthreadobj) {
650 if (!thread->o.thread->daemon)
652 thread = thread->info.prev;
658 void joinAllThreads()
660 threadobject *thread;
661 pthread_mutex_lock(&threadlistlock);
662 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
663 nativethread *info = &thread->info;
664 pthread_mutex_lock(&info->joinMutex);
665 pthread_mutex_unlock(&threadlistlock);
667 pthread_cond_wait(&info->joinCond, &info->joinMutex);
668 pthread_mutex_unlock(&info->joinMutex);
669 pthread_mutex_lock(&threadlistlock);
671 pthread_mutex_unlock(&threadlistlock);
674 static void initLockRecord(monitorLockRecord *r, threadobject *t)
681 r->incharge = (monitorLockRecord *) &dummyLR;
683 sem_init(&r->queueSem, 0, 0);
684 pthread_mutex_init(&r->resolveLock, NULL);
685 pthread_cond_init(&r->resolveWait, NULL);
688 /* No lock record must ever be destroyed because there may still be references
691 static void destroyLockRecord(monitorLockRecord *r)
693 sem_destroy(&r->queueSem);
694 pthread_mutex_destroy(&r->resolveLock);
695 pthread_cond_destroy(&r->resolveWait);
701 initThreadLocks(mainthreadobj);
704 static void initThreadLocks(threadobject *thread)
706 thread->ee.firstLR = NULL;
707 thread->ee.lrpool = NULL;
708 thread->ee.numlr = 0;
711 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
713 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
716 p->header.size = size;
717 for (i=0; i<size; i++) {
718 initLockRecord(&p->lr[i], thread);
719 p->lr[i].nextFree = &p->lr[i+1];
721 p->lr[i-1].nextFree = NULL;
725 #define INITIALLOCKRECORDS 8
727 static pthread_mutex_t pool_lock;
728 static lockRecordPool *global_pool;
730 static void initPools()
732 pthread_mutex_init(&pool_lock, NULL);
735 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
737 pthread_mutex_lock(&pool_lock);
740 lockRecordPool *pool = global_pool;
741 global_pool = pool->header.next;
742 pthread_mutex_unlock(&pool_lock);
744 for (i=0; i < pool->header.size; i++)
745 pool->lr[i].ownerThread = t;
749 pthread_mutex_unlock(&pool_lock);
751 return allocNewLockRecordPool(t, size);
754 static void freeLockRecordPools(lockRecordPool *pool)
756 lockRecordPoolHeader *last;
757 pthread_mutex_lock(&pool_lock);
758 last = &pool->header;
760 last = &last->next->header;
761 last->next = global_pool;
763 pthread_mutex_unlock(&pool_lock);
766 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
768 monitorLockRecord *r = t->ee.firstLR;
771 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
772 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
773 pool->header.next = t->ee.lrpool;
776 t->ee.numlr += pool->header.size;
779 t->ee.firstLR = r->nextFree;
783 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
785 r->nextFree = t->ee.firstLR;
789 void initObjectLock(java_objectheader *o)
791 o->monitorPtr = dummyLR;
794 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
796 atomic_add(&lr->queuers, 1);
797 MEMORY_BARRIER_AFTER_ATOMIC();
799 sem_wait(&lr->queueSem);
800 atomic_add(&lr->queuers, -1);
803 static void freeLockRecord(monitorLockRecord *lr)
810 sem_post(&lr->queueSem);
813 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
819 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
822 monitorLockRecord *lr = o->monitorPtr;
824 monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
830 handleWaiter(mlr, lr);
834 if (lr->ownerThread != t)
836 MEMORY_BARRIER_BEFORE_ATOMIC();
837 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
840 if (mlr == lr || lr->o != o) {
841 handleWaiter(mlr, lr);
845 queueOnLockRecord(lr, o);
846 handleWaiter(mlr, lr);
850 recycleLockRecord(t, mlr);
851 queueOnLockRecord(nlr, o);
853 if (lr->ownerThread == t) {
857 queueOnLockRecord(lr, o);
862 static void wakeWaiters(monitorLockRecord *lr)
867 sem_post(&lr->queueSem);
872 #define GRAB_LR(lr,t) \
873 if (lr->ownerThread != t) { \
877 #define CHECK_MONITORSTATE(lr,t,mo,a) \
878 if (lr->o != mo || lr->ownerThread != t) { \
879 *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
883 bool monitorExit(threadobject *t, java_objectheader *o)
885 monitorLockRecord *lr = o->monitorPtr;
887 CHECK_MONITORSTATE(lr, t, o, return false);
888 if (lr->lockCount > 1) {
893 monitorLockRecord *wlr = lr->waiter;
894 if (o->monitorPtr != lr ||
895 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
897 monitorLockRecord *nlr = o->monitorPtr;
899 STORE_ORDER_BARRIER();
905 recycleLockRecord(t, lr);
909 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
912 if (lr->waiter == wlr) {
913 lr->waiter = wlr->waiter;
920 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
922 return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
925 static bool timeIsEarlier(const struct timespec *tv)
927 struct timeval tvnow;
928 struct timespec tsnow;
929 gettimeofday(&tvnow, NULL);
930 tsnow.tv_sec = tvnow.tv_sec;
931 tsnow.tv_nsec = tvnow.tv_usec * 1000;
932 return timespec_less(&tsnow, tv);
935 bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
939 pthread_mutex_lock(&t->waitLock);
940 t->isSleeping = true;
941 if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
942 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
943 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
945 while (!t->interrupted && !t->signaled)
946 pthread_cond_wait(&t->waitCond, &t->waitLock);
947 wasinterrupted = t->interrupted;
948 t->interrupted = false;
950 t->isSleeping = false;
951 pthread_mutex_unlock(&t->waitLock);
952 return wasinterrupted;
955 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
957 if (millis || nanos) {
960 gettimeofday(&tv, NULL);
961 tv.tv_sec += millis / 1000;
963 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
964 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
965 tm->tv_nsec = nsec % 1000000000;
972 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
975 struct timespec wakeupTime;
976 monitorLockRecord *mlr, *lr = o->monitorPtr;
978 CHECK_MONITORSTATE(lr, t, o, return);
980 calcAbsoluteTime(&wakeupTime, millis, nanos);
983 wakeWaiters(lr->waiter);
985 STORE_ORDER_BARRIER();
987 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
988 mlr = monitorEnter(t, o);
989 removeFromWaiters(mlr, lr);
990 mlr->lockCount = lr->lockCount;
994 recycleLockRecord(t, lr);
997 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1000 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1002 monitorLockRecord *lr = o->monitorPtr;
1004 CHECK_MONITORSTATE(lr, t, o, return);
1006 threadobject *wthread;
1007 monitorLockRecord *wlr = lr->waiter;
1010 wthread = wlr->ownerThread;
1011 pthread_mutex_lock(&wthread->waitLock);
1012 if (wthread->isSleeping)
1013 pthread_cond_signal(&wthread->waitCond);
1014 wthread->signaled = true;
1015 pthread_mutex_unlock(&wthread->waitLock);
1020 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1022 monitorLockRecord *lr = o->monitorPtr;
1024 return lr->o == o && lr->ownerThread == t;
1027 void interruptThread(java_lang_VMThread *thread)
1029 threadobject *t = (threadobject*) thread;
1031 t->interrupted = true;
1032 pthread_mutex_lock(&t->waitLock);
1034 pthread_cond_signal(&t->waitCond);
1035 pthread_mutex_unlock(&t->waitLock);
1038 bool interruptedThread()
1040 threadobject *t = (threadobject*) THREADOBJECT;
1041 bool intr = t->interrupted;
1042 t->interrupted = false;
1046 bool isInterruptedThread(java_lang_VMThread *thread)
1048 threadobject *t = (threadobject*) thread;
1049 return t->interrupted;
1052 void sleepThread(s8 millis, s4 nanos)
1054 bool wasinterrupted;
1055 threadobject *t = (threadobject*) THREADOBJECT;
1056 monitorLockRecord *lr;
1057 struct timespec wakeupTime;
1058 calcAbsoluteTime(&wakeupTime, millis, nanos);
1060 lr = allocLockRecordSimple(t);
1061 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1062 recycleLockRecord(t, lr);
1065 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1073 void setPriorityThread(thread *t, s4 priority)
1075 nativethread *info = &((threadobject*) t->vmThread)->info;
1076 setPriority(info->tid, priority);
1079 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1081 threadobject *t = (threadobject*) THREADOBJECT;
1082 monitorWait(t, o, time, nanos);
1085 void signal_cond_for_object(java_objectheader *o)
1087 threadobject *t = (threadobject*) THREADOBJECT;
1088 notifyOneOrAll(t, o, true);
1091 void broadcast_cond_for_object(java_objectheader *o)
1093 threadobject *t = (threadobject*) THREADOBJECT;
1094 notifyOneOrAll(t, o, false);
1099 * These are local overrides for various environment variables in Emacs.
1100 * Please do not remove this and leave it at the end of the file, where
1101 * Emacs will automagically detect them.
1102 * ---------------------------------------------------------------------
1105 * indent-tabs-mode: t