3 #if defined(NATIVE_THREADS)
24 #include "toolbox/logging.h"
25 #include "toolbox/memory.h"
26 #include "toolbox/avl.h"
29 #include "nat/java_lang_Object.h"
30 #include "nat/java_lang_Throwable.h"
31 #include "nat/java_lang_Thread.h"
32 #include "nat/java_lang_ThreadGroup.h"
35 #include <semaphore.h>
37 #if defined(__LINUX__)
38 #define GC_LINUX_THREADS
39 #include "../mm/boehm-gc/include/gc.h"
45 pthread_mutex_t mutex;
48 } pthread_mutex_rec_t;
50 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
52 pthread_mutex_init(&m->mutex, NULL);
56 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
58 pthread_mutex_destroy(&m->mutex);
61 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
66 pthread_mutex_lock(&m->mutex);
67 m->owner = pthread_self();
71 if (m->owner != pthread_self())
72 pthread_mutex_lock(&m->mutex);
81 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
84 pthread_mutex_unlock(&m->mutex);
89 #define pthread_mutex_lock_rec pthread_mutex_lock
90 #define pthread_mutex_unlock_rec pthread_mutex_unlock
91 #define pthread_mutex_rec_t pthread_mutex_t
95 #include "machine-instr.h"
97 static struct avl_table *criticaltree;
98 static threadobject *mainthreadobj;
100 #ifndef HAVE___THREAD
101 pthread_key_t tkey_threadinfo;
103 __thread threadobject *threadobj;
106 static pthread_mutex_rec_t compiler_mutex;
107 static pthread_mutex_rec_t tablelock;
111 pthread_mutex_lock_rec(&compiler_mutex);
114 void compiler_unlock()
116 pthread_mutex_unlock_rec(&compiler_mutex);
121 pthread_mutex_lock_rec(&tablelock);
126 pthread_mutex_unlock_rec(&tablelock);
129 static int criticalcompare(const void *pa, const void *pb, void *param)
131 const threadcritnode *na = pa;
132 const threadcritnode *nb = pb;
134 if (na->mcodebegin < nb->mcodebegin)
136 if (na->mcodebegin > nb->mcodebegin)
141 static const threadcritnode *findcritical(u1 *mcodeptr)
143 struct avl_node *n = criticaltree->avl_root;
144 const threadcritnode *m = NULL;
149 const threadcritnode *d = n->avl_data;
150 if (mcodeptr == d->mcodebegin)
152 if (mcodeptr < d->mcodebegin) {
158 if (n->avl_link[1]) {
167 void thread_registercritical(threadcritnode *n)
169 avl_insert(criticaltree, n);
172 u1 *thread_checkcritical(u1 *mcodeptr)
174 const threadcritnode *n = findcritical(mcodeptr);
175 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
178 static void thread_addstaticcritical()
180 threadcritnode *n = &asm_criticalsections;
182 while (n->mcodebegin)
183 thread_registercritical(n++);
186 static pthread_mutex_t threadlistlock;
188 static pthread_mutex_t stopworldlock;
189 volatile int stopworldwhere;
191 static sem_t suspend_ack;
194 * where - 1 from within GC
197 void lock_stopworld(int where)
199 pthread_mutex_lock(&stopworldlock);
200 stopworldwhere = where;
203 void unlock_stopworld()
206 pthread_mutex_unlock(&stopworldlock);
209 #if !defined(__DARWIN__)
210 /* Caller must hold threadlistlock */
211 static int cast_sendsignals(int sig, int count)
214 threadobject *tobj = mainthreadobj;
215 nativethread *infoself = THREADINFO;
220 tobj = tobj->info.next;
221 } while (tobj != mainthreadobj);
224 nativethread *info = &tobj->info;
225 if (info != infoself)
226 pthread_kill(info->tid, sig);
227 tobj = tobj->info.next;
228 } while (tobj != mainthreadobj);
234 void cast_stopworld()
238 pthread_mutex_lock(&threadlistlock);
239 #if defined(__DARWIN__)
240 /* XXX stop threads using mach functions */
242 count = cast_sendsignals(GC_signum1(), 0);
243 for (i=0; i<count; i++)
244 sem_wait(&suspend_ack);
246 pthread_mutex_unlock(&threadlistlock);
249 void cast_startworld()
251 pthread_mutex_lock(&threadlistlock);
252 #if defined(__DARWIN__)
253 /* XXX resume threads using mach functions */
255 cast_sendsignals(GC_signum2(), -1);
257 pthread_mutex_unlock(&threadlistlock);
261 #if !defined(__DARWIN__)
262 static void sigsuspend_handler(ucontext_t *ctx)
267 thread_restartcriticalsection(ctx);
269 sem_post(&suspend_ack);
273 sigdelset(&sigs, sig);
277 int cacao_suspendhandler(ucontext_t *ctx)
279 if (stopworldwhere != 2)
282 sigsuspend_handler(ctx);
287 static void setthreadobject(threadobject *thread)
289 #if !defined(HAVE___THREAD)
290 pthread_setspecific(tkey_threadinfo, thread);
297 * Initialize threads.
303 pthread_mutexattr_t mutexattr;
304 pthread_mutexattr_init(&mutexattr);
305 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
306 pthread_mutex_init(&compiler_mutex, &mutexattr);
307 pthread_mutex_init(&tablelock, &mutexattr);
308 pthread_mutexattr_destroy(&mutexattr);
310 pthread_mutex_init_rec(&compiler_mutex);
311 pthread_mutex_init_rec(&tablelock);
314 pthread_mutex_init(&threadlistlock, NULL);
315 pthread_mutex_init(&stopworldlock, NULL);
317 /* Allocate something so the garbage collector's signal handlers are */
319 heap_allocate(1, false, NULL);
321 mainthreadobj = NEW(threadobject);
322 memset(mainthreadobj, 0, sizeof(threadobject));
323 #if !defined(HAVE___THREAD)
324 pthread_key_create(&tkey_threadinfo, NULL);
326 setthreadobject(mainthreadobj);
328 criticaltree = avl_create(criticalcompare, NULL, NULL);
329 thread_addstaticcritical();
330 sem_init(&suspend_ack, 0, 0);
333 static pthread_attr_t threadattr;
334 static void freeLockRecordPools(lockRecordPool *);
337 initThreads(u1 *stackbottom)
339 classinfo *threadclass;
340 classinfo *threadgroupclass;
341 java_lang_Thread *mainthread;
342 threadobject *tempthread = mainthreadobj;
344 threadclass = class_new(utf_new_char("java/lang/Thread"));
345 class_load(threadclass);
346 class_link(threadclass);
349 freeLockRecordPools(mainthreadobj->ee.lrpool);
350 threadclass->instancesize = sizeof(threadobject);
352 mainthreadobj = (threadobject *) builtin_new(threadclass);
353 assert(mainthreadobj);
355 FREE(tempthread, threadobject);
356 initThread(&mainthreadobj->o);
358 #if !defined(HAVE___THREAD)
359 pthread_setspecific(tkey_threadinfo, mainthreadobj);
361 threadobj = mainthreadobj;
364 mainthread = &mainthreadobj->o;
366 mainthreadobj->info.next = mainthreadobj;
367 mainthreadobj->info.prev = mainthreadobj;
369 mainthread->name=javastring_new(utf_new_char("main"));
371 /* Allocate and init ThreadGroup */
372 threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
373 class_load(threadgroupclass);
374 class_link(threadgroupclass);
377 (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
378 assert(mainthread->group != 0);
380 pthread_attr_init(&threadattr);
381 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
384 void initThread(java_lang_Thread *t)
386 nativethread *info = &((threadobject*) t)->info;
387 pthread_mutex_init(&info->joinMutex, NULL);
388 pthread_cond_init(&info->joinCond, NULL);
391 static void initThreadLocks(threadobject *);
394 threadobject *thread;
398 static void *threadstartup(void *t)
400 startupinfo *startup = t;
401 threadobject *thread = startup->thread;
402 sem_t *psem = startup->psem;
403 nativethread *info = &thread->info;
408 #if defined(__DARWIN__)
409 info->mach_thread = mach_thread_self();
411 setthreadobject(thread);
413 pthread_mutex_lock(&threadlistlock);
414 info->prev = mainthreadobj;
415 info->next = tnext = mainthreadobj->info.next;
416 mainthreadobj->info.next = thread;
417 tnext->info.prev = thread;
418 pthread_mutex_unlock(&threadlistlock);
420 initThreadLocks(thread);
425 /* Find the run()V method and call it */
426 method = class_findmethod(thread->o.header.vftbl->class,
427 utf_new_char("run"), utf_new_char("()V"));
429 panic("Cannot find method \'void run ()\'");
431 asm_calljavafunction(method, thread, NULL, NULL, NULL);
433 if (info->_exceptionptr) {
434 utf_display_classname((info->_exceptionptr)->vftbl->class->name);
438 freeLockRecordPools(thread->ee.lrpool);
440 pthread_mutex_lock(&threadlistlock);
441 info->next->info.prev = info->prev;
442 info->prev->info.next = info->next;
443 pthread_mutex_unlock(&threadlistlock);
445 pthread_mutex_lock(&info->joinMutex);
447 pthread_mutex_unlock(&info->joinMutex);
448 pthread_cond_broadcast(&info->joinCond);
453 void startThread(threadobject *t)
455 nativethread *info = &t->info;
462 sem_init(&sem, 0, 0);
464 if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
465 panic("pthread_create failed");
467 /* Wait here until thread has entered itself into the thread list */
472 void joinAllThreads()
474 pthread_mutex_lock(&threadlistlock);
475 while (mainthreadobj->info.prev != mainthreadobj) {
476 nativethread *info = &mainthreadobj->info.prev->info;
477 pthread_mutex_lock(&info->joinMutex);
478 pthread_mutex_unlock(&threadlistlock);
480 pthread_cond_wait(&info->joinCond, &info->joinMutex);
481 pthread_mutex_unlock(&info->joinMutex);
482 pthread_mutex_lock(&threadlistlock);
484 pthread_mutex_unlock(&threadlistlock);
487 bool aliveThread(java_lang_Thread *t)
489 return ((threadobject*) t)->info.tid != 0;
492 void sleepThread(s8 millis)
495 tv.tv_sec = millis / 1000;
496 tv.tv_nsec = millis % 1000 * 1000000;
497 do { } while (nanosleep(&tv, &tv) == EINTR);
505 static void timedCondWait(pthread_cond_t *cond, pthread_mutex_t *mutex, s8 millis)
508 struct timespec desttime;
509 gettimeofday(&now, NULL);
510 desttime.tv_sec = millis / 1000;
511 desttime.tv_nsec = millis % 1000 * 1000000;
512 pthread_cond_timedwait(cond, mutex, &desttime);
521 static void initExecutionEnvironment(ExecEnvironment *ee)
523 pthread_mutex_init(&ee->metaLockMutex, NULL);
524 pthread_cond_init(&ee->metaLockCond, NULL);
525 pthread_mutex_init(&ee->monitorLockMutex, NULL);
526 pthread_cond_init(&ee->monitorLockCond, NULL);
529 static void initLockRecord(monitorLockRecord *r, threadobject *t)
538 initThreadLocks(mainthreadobj);
541 static void initThreadLocks(threadobject *thread)
545 initExecutionEnvironment(&thread->ee);
546 for (i=0; i<INITIALLOCKRECORDS; i++) {
547 monitorLockRecord *r = &thread->ee.lr[i];
548 initLockRecord(r, thread);
549 r->nextFree = &thread->ee.lr[i+1];
551 thread->ee.lr[i-1].nextFree = NULL;
552 thread->ee.firstLR = &thread->ee.lr[0];
555 static inline int lockState(long r)
560 static inline void *lockRecord(long r)
562 return (void*) (r & ~3L);
565 static inline long makeLockBits(void *r, long l)
567 return ((long) r) | l;
570 static lockRecordPool *allocLockRecordPool(threadobject *thread, int size)
572 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
575 p->header.size = size;
576 for (i=0; i<size; i++) {
577 initLockRecord(&p->lr[i], thread);
578 p->lr[i].nextFree = &p->lr[i+1];
580 p->lr[i-1].nextFree = NULL;
584 static void freeLockRecordPools(lockRecordPool *pool)
587 lockRecordPool *n = pool->header.next;
588 mem_free(pool, sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * pool->header.size);
593 static monitorLockRecord *allocLockRecord(threadobject *t)
595 monitorLockRecord *r = t->ee.firstLR;
598 int poolsize = t->ee.lrpool ? t->ee.lrpool->header.size * 2 : INITIALLOCKRECORDS * 2;
599 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
600 pool->header.next = t->ee.lrpool;
605 t->ee.firstLR = r->nextFree;
609 static void recycleLockRecord(threadobject *t, monitorLockRecord *r)
611 r->nextFree = t->ee.firstLR;
615 static monitorLockRecord *appendToQueue(monitorLockRecord *queue, monitorLockRecord *lr)
617 monitorLockRecord *queuestart = queue;
621 queue = queue->queue;
626 static monitorLockRecord *moveMyLRToFront(threadobject *t, monitorLockRecord *lr)
628 monitorLockRecord *pred = NULL;
629 monitorLockRecord *firstLR = lr;
630 while (lr->owner != t) {
636 pred->queue = lr->queue;
638 lr->storedBits = firstLR->storedBits;
642 static long getMetaLockSlow(threadobject *t, long predBits);
643 static void releaseMetaLockSlow(threadobject *t, long releaseBits);
645 static long getMetaLock(threadobject *t, java_objectheader *o)
647 long busyBits = makeLockBits(t, BUSY);
648 long lockBits = atomic_swap(&o->monitorBits, busyBits);
649 return lockState(lockBits) != BUSY ? lockBits : getMetaLockSlow(t, lockBits);
652 static long getMetaLockSlow(threadobject *t, long predBits)
655 threadobject *pred = lockRecord(predBits);
656 pthread_mutex_lock(&pred->ee.metaLockMutex);
657 if (!pred->ee.bitsForGrab) {
660 pthread_cond_wait(&pred->ee.metaLockCond, &pred->ee.metaLockMutex);
661 } while (!t->ee.gotMetaLockSlow);
662 t->ee.gotMetaLockSlow = false;
663 bits = t->ee.metaLockBits;
665 bits = pred->ee.metaLockBits;
666 pred->ee.bitsForGrab = false;
667 pthread_cond_signal(&pred->ee.metaLockCond);
669 pthread_mutex_unlock(&pred->ee.metaLockMutex);
673 static void releaseMetaLock(threadobject *t, java_objectheader *o, long releaseBits)
675 long busyBits = makeLockBits(t, BUSY);
676 int locked = compare_and_swap(&o->monitorBits, busyBits, releaseBits) != 0;
679 releaseMetaLockSlow(t, releaseBits);
682 static void releaseMetaLockSlow(threadobject *t, long releaseBits)
684 pthread_mutex_lock(&t->ee.metaLockMutex);
686 assert(!t->ee.succ->ee.bitsForGrab);
687 assert(!t->ee.bitsForGrab);
688 assert(!t->ee.succ->ee.gotMetaLockSlow);
689 t->ee.succ->ee.metaLockBits = releaseBits;
690 t->ee.succ->ee.gotMetaLockSlow = true;
692 pthread_cond_signal(&t->ee.metaLockCond);
694 t->ee.metaLockBits = releaseBits;
695 t->ee.bitsForGrab = true;
697 pthread_cond_wait(&t->ee.metaLockCond, &t->ee.metaLockMutex);
698 } while (t->ee.bitsForGrab);
700 pthread_mutex_unlock(&t->ee.metaLockMutex);
703 static void monitorEnterSlow(threadobject *t, java_objectheader *o, long r);
705 void monitorEnter(threadobject *t, java_objectheader *o)
707 long r = getMetaLock(t, o);
708 int state = lockState(r);
710 if (state == NEUTRAL) {
711 monitorLockRecord *lr = allocLockRecord(t);
713 releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
714 } else if (state == LOCKED) {
715 monitorLockRecord *ownerLR = lockRecord(r);
716 if (ownerLR->owner == t) {
717 ownerLR->lockCount++;
718 releaseMetaLock(t, o, r);
720 monitorLockRecord *lr = allocLockRecord(t);
721 ownerLR->queue = appendToQueue(ownerLR->queue, lr);
722 monitorEnterSlow(t, o, r);
724 } else if (state == WAITERS) {
725 monitorLockRecord *lr = allocLockRecord(t);
726 monitorLockRecord *firstWaiterLR = lockRecord(r);
727 lr->queue = firstWaiterLR;
728 lr->storedBits = firstWaiterLR->storedBits;
729 releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
733 static void monitorEnterSlow(threadobject *t, java_objectheader *o, long r)
735 monitorLockRecord *lr;
736 while (lockState(r) == LOCKED) {
737 pthread_mutex_lock(&t->ee.monitorLockMutex);
738 releaseMetaLock(t, o, r);
739 pthread_cond_wait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex);
740 pthread_mutex_unlock(&t->ee.monitorLockMutex);
741 r = getMetaLock(t, o);
743 assert(lockState(r) == WAITERS);
744 lr = moveMyLRToFront(t, lockRecord(r));
745 releaseMetaLock(t, o, makeLockBits(lr, LOCKED));
748 static void monitorExitSlow(threadobject *t, java_objectheader *o, monitorLockRecord *lr);
750 void monitorExit(threadobject *t, java_objectheader *o)
752 long r = getMetaLock(t, o);
753 monitorLockRecord *ownerLR = lockRecord(r);
754 int state = lockState(r);
755 if (state == LOCKED && ownerLR->owner == t) {
756 assert(ownerLR->lockCount >= 1);
757 if (ownerLR->lockCount == 1) {
758 if (ownerLR->queue == NULL) {
759 assert(lockState(ownerLR->storedBits) == NEUTRAL);
760 releaseMetaLock(t, o, ownerLR->storedBits);
762 ownerLR->queue->storedBits = ownerLR->storedBits;
763 monitorExitSlow(t, o, ownerLR->queue);
764 ownerLR->queue = NULL;
766 recycleLockRecord(t, ownerLR);
768 ownerLR->lockCount--;
769 releaseMetaLock(t, o, r);
772 releaseMetaLock(t, o, r);
773 panic("Illegal monitor exception");
777 static threadobject *wakeupEE(monitorLockRecord *lr)
779 while (lr->queue && lr->queue->owner->ee.isWaitingForNotify)
784 static void monitorExitSlow(threadobject *t, java_objectheader *o, monitorLockRecord *lr)
786 threadobject *wakeEE = wakeupEE(lr);
788 pthread_mutex_lock(&wakeEE->ee.monitorLockMutex);
789 releaseMetaLock(t, o, makeLockBits(lr, WAITERS));
790 pthread_cond_signal(&wakeEE->ee.monitorLockCond);
791 pthread_mutex_unlock(&wakeEE->ee.monitorLockMutex);
793 releaseMetaLock(t, o, makeLockBits(lr, WAITERS));
797 void monitorWait(threadobject *t, java_objectheader *o, s8 millis)
799 long r = getMetaLock(t, o);
800 monitorLockRecord *ownerLR = lockRecord(r);
801 int state = lockState(r);
802 if (state == LOCKED && ownerLR->owner == t) {
803 pthread_mutex_lock(&t->ee.monitorLockMutex);
804 t->ee.isWaitingForNotify = true;
805 monitorExitSlow(t, o, ownerLR);
807 pthread_cond_wait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex);
809 timedCondWait(&t->ee.monitorLockCond, &t->ee.monitorLockMutex, millis);
810 t->ee.isWaitingForNotify = false;
811 pthread_mutex_unlock(&t->ee.monitorLockMutex);
812 r = getMetaLock(t, o);
813 monitorEnterSlow(t, o, r);
815 releaseMetaLock(t, o, r);
816 panic("Illegal monitor exception");
820 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
822 long r = getMetaLock(t, o);
823 monitorLockRecord *ownerLR = lockRecord(r);
824 int state = lockState(r);
825 if (state == LOCKED && ownerLR->owner == t) {
826 monitorLockRecord *q = ownerLR->queue;
828 if (q->owner->ee.isWaitingForNotify) {
829 q->owner->ee.isWaitingForNotify = false;
835 releaseMetaLock(t, o, r);
837 releaseMetaLock(t, o, r);
838 panic("Illegal monitor exception");
842 void wait_cond_for_object(java_objectheader *o, s8 time)
844 threadobject *t = (threadobject*) THREADOBJECT;
845 monitorWait(t, o, time);
848 void signal_cond_for_object(java_objectheader *o)
850 threadobject *t = (threadobject*) THREADOBJECT;
851 notifyOneOrAll(t, o, true);
854 void broadcast_cond_for_object(java_objectheader *o)
856 threadobject *t = (threadobject*) THREADOBJECT;
857 notifyOneOrAll(t, o, false);
864 * These are local overrides for various environment variables in Emacs.
865 * Please do not remove this and leave it at the end of the file, where
866 * Emacs will automagically detect them.
867 * ---------------------------------------------------------------------
870 * indent-tabs-mode: t