3 #if defined(NATIVE_THREADS)
24 #include "exceptions.h"
25 #include "toolbox/logging.h"
26 #include "toolbox/memory.h"
27 #include "toolbox/avl.h"
30 #include "nat/java_lang_Object.h"
31 #include "nat/java_lang_Throwable.h"
32 #include "nat/java_lang_Thread.h"
33 #include "nat/java_lang_ThreadGroup.h"
34 #include "nat/java_lang_VMThread.h"
37 #include <semaphore.h>
39 #if !defined(__DARWIN__)
40 #if defined(__LINUX__)
41 #define GC_LINUX_THREADS
42 #elif defined(__MIPS__)
43 #define GC_IRIX_THREADS
45 #include "../mm/boehm-gc/include/gc.h"
50 /* We need this for older MacOSX (10.1.x) */
53 pthread_mutex_t mutex;
56 } pthread_mutex_rec_t;
58 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
60 pthread_mutex_init(&m->mutex, NULL);
64 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
66 pthread_mutex_destroy(&m->mutex);
69 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
74 pthread_mutex_lock(&m->mutex);
75 m->owner = pthread_self();
79 if (m->owner != pthread_self())
80 pthread_mutex_lock(&m->mutex);
89 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
92 pthread_mutex_unlock(&m->mutex);
97 #define pthread_mutex_lock_rec pthread_mutex_lock
98 #define pthread_mutex_unlock_rec pthread_mutex_unlock
99 #define pthread_mutex_rec_t pthread_mutex_t
101 #endif /* MUTEXSIM */
103 static void setPriority(pthread_t tid, int priority)
105 struct sched_param schedp;
108 pthread_getschedparam(tid, &policy, &schedp);
109 schedp.sched_priority = priority;
110 pthread_setschedparam(tid, policy, &schedp);
113 #include "machine-instr.h"
115 static struct avl_table *criticaltree;
116 static threadobject *mainthreadobj;
118 #ifndef HAVE___THREAD
119 pthread_key_t tkey_threadinfo;
121 __thread threadobject *threadobj;
124 static pthread_mutex_rec_t compiler_mutex;
125 static pthread_mutex_rec_t tablelock;
129 pthread_mutex_lock_rec(&compiler_mutex);
132 void compiler_unlock()
134 pthread_mutex_unlock_rec(&compiler_mutex);
139 pthread_mutex_lock_rec(&tablelock);
144 pthread_mutex_unlock_rec(&tablelock);
147 static int criticalcompare(const void *pa, const void *pb, void *param)
149 const threadcritnode *na = pa;
150 const threadcritnode *nb = pb;
152 if (na->mcodebegin < nb->mcodebegin)
154 if (na->mcodebegin > nb->mcodebegin)
159 static const threadcritnode *findcritical(u1 *mcodeptr)
161 struct avl_node *n = criticaltree->avl_root;
162 const threadcritnode *m = NULL;
167 const threadcritnode *d = n->avl_data;
168 if (mcodeptr == d->mcodebegin)
170 if (mcodeptr < d->mcodebegin) {
176 if (n->avl_link[1]) {
185 void thread_registercritical(threadcritnode *n)
187 avl_insert(criticaltree, n);
190 u1 *thread_checkcritical(u1 *mcodeptr)
192 const threadcritnode *n = findcritical(mcodeptr);
193 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
196 static void thread_addstaticcritical()
198 threadcritnode *n = &asm_criticalsections;
200 while (n->mcodebegin)
201 thread_registercritical(n++);
204 static pthread_mutex_t threadlistlock;
206 static pthread_mutex_t stopworldlock;
207 volatile int stopworldwhere;
209 static sem_t suspend_ack;
210 #if defined(__MIPS__)
211 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
212 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
216 * where - 1 from within GC
219 void lock_stopworld(int where)
221 pthread_mutex_lock(&stopworldlock);
222 stopworldwhere = where;
225 void unlock_stopworld()
228 pthread_mutex_unlock(&stopworldlock);
231 #if !defined(__DARWIN__)
232 /* Caller must hold threadlistlock */
233 static int cast_sendsignals(int sig, int count)
236 threadobject *tobj = mainthreadobj;
237 nativethread *infoself = THREADINFO;
242 tobj = tobj->info.next;
243 } while (tobj != mainthreadobj);
246 nativethread *info = &tobj->info;
247 if (info != infoself)
248 pthread_kill(info->tid, sig);
249 tobj = tobj->info.next;
250 } while (tobj != mainthreadobj);
257 static void cast_darwinstop()
259 threadobject *tobj = mainthreadobj;
260 nativethread *infoself = THREADINFO;
263 nativethread *info = &tobj->info;
264 if (info != infoself)
266 thread_state_flavor_t flavor = PPC_THREAD_STATE;
267 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
268 ppc_thread_state_t thread_state;
269 mach_port_t thread = info->mach_thread;
272 r = thread_suspend(thread);
273 if (r != KERN_SUCCESS)
274 panic("thread_suspend failed");
276 r = thread_get_state(thread, flavor,
277 (natural_t*)&thread_state, &thread_state_count);
278 if (r != KERN_SUCCESS)
279 panic("thread_get_state failed");
281 thread_restartcriticalsection(&thread_state);
283 r = thread_set_state(thread, flavor,
284 (natural_t*)&thread_state, thread_state_count);
285 if (r != KERN_SUCCESS)
286 panic("thread_set_state failed");
288 tobj = tobj->info.next;
289 } while (tobj != mainthreadobj);
292 static void cast_darwinresume()
294 threadobject *tobj = mainthreadobj;
295 nativethread *infoself = THREADINFO;
298 nativethread *info = &tobj->info;
299 if (info != infoself)
301 mach_port_t thread = info->mach_thread;
304 r = thread_resume(thread);
305 if (r != KERN_SUCCESS)
306 panic("thread_resume failed");
308 tobj = tobj->info.next;
309 } while (tobj != mainthreadobj);
314 #if defined(__MIPS__)
315 static void cast_irixresume()
317 pthread_mutex_lock(&suspend_ack_lock);
318 pthread_cond_broadcast(&suspend_cond);
319 pthread_mutex_unlock(&suspend_ack_lock);
323 void cast_stopworld()
327 pthread_mutex_lock(&threadlistlock);
328 #if defined(__DARWIN__)
331 count = cast_sendsignals(GC_signum1(), 0);
332 for (i=0; i<count; i++)
333 sem_wait(&suspend_ack);
335 pthread_mutex_unlock(&threadlistlock);
338 void cast_startworld()
340 pthread_mutex_lock(&threadlistlock);
341 #if defined(__DARWIN__)
343 #elif defined(__MIPS__)
346 cast_sendsignals(GC_signum2(), -1);
348 pthread_mutex_unlock(&threadlistlock);
352 #if !defined(__DARWIN__)
353 static void sigsuspend_handler(ucontext_t *ctx)
358 thread_restartcriticalsection(ctx);
360 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
361 (not POSIX async-safe). */
362 #if defined(__IRIX__)
363 pthread_mutex_lock(&suspend_ack_lock);
364 sem_post(&suspend_ack);
365 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
366 pthread_mutex_unlock(&suspend_ack_lock);
368 sem_post(&suspend_ack);
372 sigdelset(&sigs, sig);
377 int cacao_suspendhandler(ucontext_t *ctx)
379 if (stopworldwhere != 2)
382 sigsuspend_handler(ctx);
387 static void setthreadobject(threadobject *thread)
389 #if !defined(HAVE___THREAD)
390 pthread_setspecific(tkey_threadinfo, thread);
396 static monitorLockRecord *dummyLR;
398 static void initPools();
401 * Initialize threads.
407 pthread_mutexattr_t mutexattr;
408 pthread_mutexattr_init(&mutexattr);
409 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
410 pthread_mutex_init(&compiler_mutex, &mutexattr);
411 pthread_mutex_init(&tablelock, &mutexattr);
412 pthread_mutexattr_destroy(&mutexattr);
414 pthread_mutex_init_rec(&compiler_mutex);
415 pthread_mutex_init_rec(&tablelock);
418 pthread_mutex_init(&threadlistlock, NULL);
419 pthread_mutex_init(&stopworldlock, NULL);
421 /* Allocate something so the garbage collector's signal handlers are */
423 heap_allocate(1, false, NULL);
425 mainthreadobj = NEW(threadobject);
426 memset(mainthreadobj, 0, sizeof(threadobject));
427 mainthreadobj->info.tid = pthread_self();
428 #if !defined(HAVE___THREAD)
429 pthread_key_create(&tkey_threadinfo, NULL);
431 setthreadobject(mainthreadobj);
434 criticaltree = avl_create(criticalcompare, NULL, NULL);
435 thread_addstaticcritical();
436 sem_init(&suspend_ack, 0, 0);
438 /* Every newly created object's monitorPtr points here so we save a check
440 dummyLR = mem_alloc(sizeof(monitorLockRecord));
442 dummyLR->ownerThread = NULL;
443 dummyLR->waiting = false;
446 static pthread_attr_t threadattr;
448 static void freeLockRecordPools(lockRecordPool *);
451 initThreads(u1 *stackbottom)
453 classinfo *threadclass;
454 classinfo *threadgroupclass;
455 java_lang_String *threadname;
456 java_lang_Thread *mainthread;
457 java_lang_ThreadGroup *threadgroup;
458 threadobject *tempthread = mainthreadobj;
461 threadclass = class_new(utf_new_char("java/lang/VMThread"));
462 class_load(threadclass);
463 class_link(threadclass);
466 throw_exception_exit();
468 freeLockRecordPools(mainthreadobj->ee.lrpool);
469 /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
470 * the execution environment there. No Thread object must have been created
471 * at an earlier time */
472 threadclass->instancesize = sizeof(threadobject);
474 /* Create a VMThread */
475 mainthreadobj = (threadobject *) builtin_new(threadclass);
478 throw_exception_exit();
480 FREE(tempthread, threadobject);
481 initThread(&mainthreadobj->o);
483 setthreadobject(mainthreadobj);
486 mainthreadobj->info.next = mainthreadobj;
487 mainthreadobj->info.prev = mainthreadobj;
489 threadname = javastring_new(utf_new_char("main"));
491 /* Allocate and init ThreadGroup */
492 threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
494 (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
497 throw_exception_exit();
499 /* Create a Thread */
500 threadclass = class_new(utf_new_char("java/lang/Thread"));
501 mainthread = (java_lang_Thread*) builtin_new(threadclass);
502 mainthreadobj->o.thread = mainthread;
505 throw_exception_exit();
507 /* Call Thread constructor */
508 method = class_resolveclassmethod(threadclass,
509 utf_new_char("<init>"),
510 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
515 throw_exception_exit();
517 asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
519 throw_exception_exit();
521 mainthread->group = threadgroup;
522 /* XXX This is a hack because the fourth argument was omitted */
523 mainthread->daemon = false;
525 /* Add mainthread to ThreadGroup */
526 method = class_resolveclassmethod(threadgroupclass,
527 utf_new_char("addThread"),
528 utf_new_char("(Ljava/lang/Thread;)V"),
533 throw_exception_exit();
535 asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
537 throw_exception_exit();
539 setPriority(pthread_self(), 5);
541 pthread_attr_init(&threadattr);
542 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
545 void initThread(java_lang_VMThread *t)
547 threadobject *thread = (threadobject*) t;
548 nativethread *info = &thread->info;
549 info->tid = pthread_self();
550 /* TODO destroy all those things */
551 pthread_mutex_init(&info->joinMutex, NULL);
552 pthread_cond_init(&info->joinCond, NULL);
554 pthread_mutex_init(&thread->waitLock, NULL);
555 pthread_cond_init(&thread->waitCond, NULL);
556 thread->interrupted = false;
557 thread->signaled = false;
558 thread->isSleeping = false;
561 static void initThreadLocks(threadobject *);
564 threadobject *thread;
568 static void *threadstartup(void *t)
570 startupinfo *startup = t;
571 threadobject *thread = startup->thread;
572 sem_t *psem = startup->psem;
573 nativethread *info = &thread->info;
578 #if defined(__DARWIN__)
579 info->mach_thread = mach_thread_self();
581 setthreadobject(thread);
583 pthread_mutex_lock(&threadlistlock);
584 info->prev = mainthreadobj;
585 info->next = tnext = mainthreadobj->info.next;
586 mainthreadobj->info.next = thread;
587 tnext->info.prev = thread;
588 pthread_mutex_unlock(&threadlistlock);
590 initThreadLocks(thread);
595 setPriority(info->tid, thread->o.thread->priority);
598 /* Find the run()V method and call it */
599 method = class_resolveclassmethod(thread->o.header.vftbl->class,
602 thread->o.header.vftbl->class,
605 /* if method != NULL, we had not exception */
607 asm_calljavafunction(method, thread, NULL, NULL, NULL);
613 /* Allow lock record pools to be used by other threads. They cannot be
614 * deleted so we'd better not waste them. */
615 freeLockRecordPools(thread->ee.lrpool);
617 pthread_mutex_lock(&threadlistlock);
618 info->next->info.prev = info->prev;
619 info->prev->info.next = info->next;
620 pthread_mutex_unlock(&threadlistlock);
622 pthread_mutex_lock(&info->joinMutex);
624 pthread_mutex_unlock(&info->joinMutex);
625 pthread_cond_broadcast(&info->joinCond);
630 void startThread(thread *t)
632 nativethread *info = &((threadobject*) t->vmThread)->info;
636 startup.thread = (threadobject*) t->vmThread;
639 sem_init(&sem, 0, 0);
641 if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
642 panic("pthread_create failed");
644 /* Wait here until the thread has entered itself into the thread list */
649 /* At the end of the program, we wait for all running non-daemon threads to die
652 static threadobject *findNonDaemon(threadobject *thread)
654 while (thread != mainthreadobj) {
655 if (!thread->o.thread->daemon)
657 thread = thread->info.prev;
663 void joinAllThreads()
665 threadobject *thread;
666 pthread_mutex_lock(&threadlistlock);
667 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
668 nativethread *info = &thread->info;
669 pthread_mutex_lock(&info->joinMutex);
670 pthread_mutex_unlock(&threadlistlock);
672 pthread_cond_wait(&info->joinCond, &info->joinMutex);
673 pthread_mutex_unlock(&info->joinMutex);
674 pthread_mutex_lock(&threadlistlock);
676 pthread_mutex_unlock(&threadlistlock);
679 static void initLockRecord(monitorLockRecord *r, threadobject *t)
686 r->incharge = (monitorLockRecord *) &dummyLR;
688 sem_init(&r->queueSem, 0, 0);
689 pthread_mutex_init(&r->resolveLock, NULL);
690 pthread_cond_init(&r->resolveWait, NULL);
693 /* No lock record must ever be destroyed because there may still be references
696 static void destroyLockRecord(monitorLockRecord *r)
698 sem_destroy(&r->queueSem);
699 pthread_mutex_destroy(&r->resolveLock);
700 pthread_cond_destroy(&r->resolveWait);
706 initThreadLocks(mainthreadobj);
709 static void initThreadLocks(threadobject *thread)
711 thread->ee.firstLR = NULL;
712 thread->ee.lrpool = NULL;
713 thread->ee.numlr = 0;
716 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
718 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
721 p->header.size = size;
722 for (i=0; i<size; i++) {
723 initLockRecord(&p->lr[i], thread);
724 p->lr[i].nextFree = &p->lr[i+1];
726 p->lr[i-1].nextFree = NULL;
730 #define INITIALLOCKRECORDS 8
732 static pthread_mutex_t pool_lock;
733 static lockRecordPool *global_pool;
735 static void initPools()
737 pthread_mutex_init(&pool_lock, NULL);
740 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
742 pthread_mutex_lock(&pool_lock);
745 lockRecordPool *pool = global_pool;
746 global_pool = pool->header.next;
747 pthread_mutex_unlock(&pool_lock);
749 for (i=0; i < pool->header.size; i++)
750 pool->lr[i].ownerThread = t;
754 pthread_mutex_unlock(&pool_lock);
756 return allocNewLockRecordPool(t, size);
759 static void freeLockRecordPools(lockRecordPool *pool)
761 lockRecordPoolHeader *last;
762 pthread_mutex_lock(&pool_lock);
763 last = &pool->header;
765 last = &last->next->header;
766 last->next = global_pool;
768 pthread_mutex_unlock(&pool_lock);
771 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
773 monitorLockRecord *r = t->ee.firstLR;
776 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
777 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
778 pool->header.next = t->ee.lrpool;
781 t->ee.numlr += pool->header.size;
784 t->ee.firstLR = r->nextFree;
788 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
790 r->nextFree = t->ee.firstLR;
794 void initObjectLock(java_objectheader *o)
796 o->monitorPtr = dummyLR;
799 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
801 atomic_add(&lr->queuers, 1);
802 MEMORY_BARRIER_AFTER_ATOMIC();
804 sem_wait(&lr->queueSem);
805 atomic_add(&lr->queuers, -1);
808 static void freeLockRecord(monitorLockRecord *lr)
815 sem_post(&lr->queueSem);
818 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
824 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
827 monitorLockRecord *lr = o->monitorPtr;
829 monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
835 handleWaiter(mlr, lr);
839 if (lr->ownerThread != t)
841 MEMORY_BARRIER_BEFORE_ATOMIC();
842 nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
845 if (mlr == lr || lr->o != o) {
846 handleWaiter(mlr, lr);
850 queueOnLockRecord(lr, o);
851 handleWaiter(mlr, lr);
855 recycleLockRecord(t, mlr);
856 queueOnLockRecord(nlr, o);
858 if (lr->ownerThread == t) {
862 queueOnLockRecord(lr, o);
867 static void wakeWaiters(monitorLockRecord *lr)
872 sem_post(&lr->queueSem);
877 #define GRAB_LR(lr,t) \
878 if (lr->ownerThread != t) { \
882 #define CHECK_MONITORSTATE(lr,t,mo,a) \
883 if (lr->o != mo || lr->ownerThread != t) { \
884 *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
888 bool monitorExit(threadobject *t, java_objectheader *o)
890 monitorLockRecord *lr = o->monitorPtr;
892 CHECK_MONITORSTATE(lr, t, o, return false);
893 if (lr->lockCount > 1) {
898 monitorLockRecord *wlr = lr->waiter;
899 if (o->monitorPtr != lr ||
900 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
902 monitorLockRecord *nlr = o->monitorPtr;
904 STORE_ORDER_BARRIER();
910 recycleLockRecord(t, lr);
914 static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
917 if (lr->waiter == wlr) {
918 lr->waiter = wlr->waiter;
925 static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
927 return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
930 static bool timeIsEarlier(const struct timespec *tv)
932 struct timeval tvnow;
933 struct timespec tsnow;
934 gettimeofday(&tvnow, NULL);
935 tsnow.tv_sec = tvnow.tv_sec;
936 tsnow.tv_nsec = tvnow.tv_usec * 1000;
937 return timespec_less(&tsnow, tv);
940 bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
944 pthread_mutex_lock(&t->waitLock);
945 t->isSleeping = true;
946 if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
947 while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
948 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
950 while (!t->interrupted && !t->signaled)
951 pthread_cond_wait(&t->waitCond, &t->waitLock);
952 wasinterrupted = t->interrupted;
953 t->interrupted = false;
955 t->isSleeping = false;
956 pthread_mutex_unlock(&t->waitLock);
957 return wasinterrupted;
960 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
962 if (millis || nanos) {
965 gettimeofday(&tv, NULL);
966 tv.tv_sec += millis / 1000;
968 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
969 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
970 tm->tv_nsec = nsec % 1000000000;
977 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
980 struct timespec wakeupTime;
981 monitorLockRecord *mlr, *lr = o->monitorPtr;
983 CHECK_MONITORSTATE(lr, t, o, return);
985 calcAbsoluteTime(&wakeupTime, millis, nanos);
988 wakeWaiters(lr->waiter);
990 STORE_ORDER_BARRIER();
992 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
993 mlr = monitorEnter(t, o);
994 removeFromWaiters(mlr, lr);
995 mlr->lockCount = lr->lockCount;
999 recycleLockRecord(t, lr);
1002 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1005 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1007 monitorLockRecord *lr = o->monitorPtr;
1009 CHECK_MONITORSTATE(lr, t, o, return);
1011 threadobject *wthread;
1012 monitorLockRecord *wlr = lr->waiter;
1015 wthread = wlr->ownerThread;
1016 pthread_mutex_lock(&wthread->waitLock);
1017 if (wthread->isSleeping)
1018 pthread_cond_signal(&wthread->waitCond);
1019 wthread->signaled = true;
1020 pthread_mutex_unlock(&wthread->waitLock);
1025 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1027 monitorLockRecord *lr = o->monitorPtr;
1029 return lr->o == o && lr->ownerThread == t;
1032 void interruptThread(java_lang_VMThread *thread)
1034 threadobject *t = (threadobject*) thread;
1036 t->interrupted = true;
1037 pthread_mutex_lock(&t->waitLock);
1039 pthread_cond_signal(&t->waitCond);
1040 pthread_mutex_unlock(&t->waitLock);
1043 bool interruptedThread()
1045 threadobject *t = (threadobject*) THREADOBJECT;
1046 bool intr = t->interrupted;
1047 t->interrupted = false;
1051 bool isInterruptedThread(java_lang_VMThread *thread)
1053 threadobject *t = (threadobject*) thread;
1054 return t->interrupted;
1057 void sleepThread(s8 millis, s4 nanos)
1059 bool wasinterrupted;
1060 threadobject *t = (threadobject*) THREADOBJECT;
1061 monitorLockRecord *lr;
1062 struct timespec wakeupTime;
1063 calcAbsoluteTime(&wakeupTime, millis, nanos);
1065 lr = allocLockRecordSimple(t);
1066 wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
1067 recycleLockRecord(t, lr);
1070 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1078 void setPriorityThread(thread *t, s4 priority)
1080 nativethread *info = &((threadobject*) t->vmThread)->info;
1081 setPriority(info->tid, priority);
1084 void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
1086 threadobject *t = (threadobject*) THREADOBJECT;
1087 monitorWait(t, o, time, nanos);
1090 void signal_cond_for_object(java_objectheader *o)
1092 threadobject *t = (threadobject*) THREADOBJECT;
1093 notifyOneOrAll(t, o, true);
1096 void broadcast_cond_for_object(java_objectheader *o)
1098 threadobject *t = (threadobject*) THREADOBJECT;
1099 notifyOneOrAll(t, o, false);
1106 * These are local overrides for various environment variables in Emacs.
1107 * Please do not remove this and leave it at the end of the file, where
1108 * Emacs will automagically detect them.
1109 * ---------------------------------------------------------------------
1112 * indent-tabs-mode: t