1 /* src/threads/native/threads.c - native threads support
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
29 Changes: Christian Thalinger
32 $Id: threads.c 4869 2006-05-03 22:46:39Z edwin $
42 #include <sys/types.h>
50 #include <semaphore.h>
56 #ifndef USE_MD_THREAD_STUFF
57 #include "machine-instr.h"
59 #include "threads/native/generic-primitives.h"
63 #include "mm/memory.h"
64 #include "native/native.h"
65 #include "native/include/java_lang_Object.h"
66 #include "native/include/java_lang_Throwable.h"
67 #include "native/include/java_lang_Thread.h"
68 #include "native/include/java_lang_ThreadGroup.h"
69 #include "native/include/java_lang_VMThread.h"
70 #include "threads/native/threads.h"
71 #include "toolbox/avl.h"
72 #include "toolbox/logging.h"
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/loader.h"
77 #include "vm/options.h"
78 #include "vm/stringlocal.h"
80 #include "vm/jit/asmpart.h"
82 #if !defined(__DARWIN__)
83 #if defined(__LINUX__)
84 #define GC_LINUX_THREADS
85 #elif defined(__MIPS__)
86 #define GC_IRIX_THREADS
88 #include "boehm-gc/include/gc.h"
91 #ifdef USE_MD_THREAD_STUFF
92 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
93 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
94 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
97 /******************************************************************************/
98 /* Recursive Mutex Implementation for Darwin */
99 /******************************************************************************/
103 /* We need this for older MacOSX (10.1.x) */
106 pthread_mutex_t mutex;
109 } pthread_mutex_rec_t;
111 static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
113 pthread_mutex_init(&m->mutex, NULL);
117 static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
119 pthread_mutex_destroy(&m->mutex);
122 static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
127 pthread_mutex_lock(&m->mutex);
128 m->owner = pthread_self();
133 if (m->owner != pthread_self()) {
134 pthread_mutex_lock(&m->mutex);
144 static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
147 pthread_mutex_unlock(&m->mutex);
152 #define pthread_mutex_lock_rec pthread_mutex_lock
153 #define pthread_mutex_unlock_rec pthread_mutex_unlock
154 #define pthread_mutex_rec_t pthread_mutex_t
156 #endif /* MUTEXSIM */
158 /* threads_sem_init ************************************************************
160 Initialize a semaphore. Checks against errors and interruptions.
163 sem..............the semaphore to initialize
164 shared...........true if this semaphore will be shared between processes
165 value............the initial value for the semaphore
167 *******************************************************************************/
169 void threads_sem_init(sem_t *sem, bool shared, int value)
176 r = sem_init(sem, shared, value);
179 } while (errno == EINTR);
181 fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
182 errno, strerror(errno));
186 /* threads_sem_wait ************************************************************
188 Wait for a semaphore, non-interruptible.
190 IMPORTANT: Always use this function instead of `sem_wait` directly, as
191 `sem_wait` may be interrupted by signals!
194 sem..............the semaphore to wait on
196 *******************************************************************************/
198 void threads_sem_wait(sem_t *sem)
208 } while (errno == EINTR);
210 fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
211 errno, strerror(errno));
215 /* threads_sem_post ************************************************************
217 Increase the count of a semaphore. Checks for errors.
220 sem..............the semaphore to increase the count of
222 *******************************************************************************/
224 void threads_sem_post(sem_t *sem)
230 /* unlike sem_wait, sem_post is not interruptible */
236 fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
237 errno, strerror(errno));
241 /* threads_set_thread_priority *************************************************
243 Set the priority of the given thread.
246 tid..........thread id
247 priority.....priority to set
249 ******************************************************************************/
251 static void threads_set_thread_priority(pthread_t tid, int priority)
253 struct sched_param schedp;
256 pthread_getschedparam(tid, &policy, &schedp);
257 schedp.sched_priority = priority;
258 pthread_setschedparam(tid, policy, &schedp);
262 static avl_tree *criticaltree;
263 threadobject *mainthreadobj;
265 #ifndef HAVE___THREAD
266 pthread_key_t tkey_threadinfo;
268 __thread threadobject *threadobj;
271 static pthread_mutex_rec_t compiler_mutex;
275 pthread_mutex_lock_rec(&compiler_mutex);
278 void compiler_unlock()
280 pthread_mutex_unlock_rec(&compiler_mutex);
283 static s4 criticalcompare(const void *pa, const void *pb)
285 const threadcritnode *na = pa;
286 const threadcritnode *nb = pb;
288 if (na->mcodebegin < nb->mcodebegin)
290 if (na->mcodebegin > nb->mcodebegin)
296 static const threadcritnode *findcritical(u1 *mcodeptr)
299 const threadcritnode *m;
301 n = criticaltree->root;
308 const threadcritnode *d = n->data;
310 if (mcodeptr == d->mcodebegin)
313 if (mcodeptr < d->mcodebegin) {
334 void thread_registercritical(threadcritnode *n)
336 avl_insert(criticaltree, n);
339 u1 *thread_checkcritical(u1 *mcodeptr)
341 const threadcritnode *n = findcritical(mcodeptr);
342 return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
345 static void thread_addstaticcritical()
347 /* XXX TWISTI: this is just a quick hack */
348 #if defined(ENABLE_JIT)
349 threadcritnode *n = &asm_criticalsections;
351 while (n->mcodebegin)
352 thread_registercritical(n++);
356 static pthread_mutex_t threadlistlock;
358 static pthread_mutex_t stopworldlock;
359 volatile int stopworldwhere;
361 static sem_t suspend_ack;
362 #if defined(__MIPS__)
363 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
364 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
368 * where - 1 from within GC
371 void lock_stopworld(int where)
373 pthread_mutex_lock(&stopworldlock);
374 stopworldwhere = where;
377 void unlock_stopworld()
380 pthread_mutex_unlock(&stopworldlock);
383 #if !defined(__DARWIN__)
384 /* Caller must hold threadlistlock */
385 static int cast_sendsignals(int sig, int count)
388 threadobject *tobj = mainthreadobj;
389 nativethread *infoself = THREADINFO;
394 tobj = tobj->info.next;
395 } while (tobj != mainthreadobj);
399 nativethread *info = &tobj->info;
400 if (info != infoself)
401 pthread_kill(info->tid, sig);
402 tobj = tobj->info.next;
403 } while (tobj != mainthreadobj);
410 static void cast_darwinstop()
412 threadobject *tobj = mainthreadobj;
413 nativethread *infoself = THREADINFO;
416 nativethread *info = &tobj->info;
417 if (info != infoself)
419 thread_state_flavor_t flavor = PPC_THREAD_STATE;
420 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
421 ppc_thread_state_t thread_state;
422 mach_port_t thread = info->mach_thread;
425 r = thread_suspend(thread);
426 if (r != KERN_SUCCESS) {
427 log_text("thread_suspend failed");
431 r = thread_get_state(thread, flavor,
432 (natural_t*)&thread_state, &thread_state_count);
433 if (r != KERN_SUCCESS) {
434 log_text("thread_get_state failed");
438 thread_restartcriticalsection(&thread_state);
440 r = thread_set_state(thread, flavor,
441 (natural_t*)&thread_state, thread_state_count);
442 if (r != KERN_SUCCESS) {
443 log_text("thread_set_state failed");
447 tobj = tobj->info.next;
448 } while (tobj != mainthreadobj);
451 static void cast_darwinresume()
453 threadobject *tobj = mainthreadobj;
454 nativethread *infoself = THREADINFO;
457 nativethread *info = &tobj->info;
458 if (info != infoself)
460 mach_port_t thread = info->mach_thread;
463 r = thread_resume(thread);
464 if (r != KERN_SUCCESS) {
465 log_text("thread_resume failed");
469 tobj = tobj->info.next;
470 } while (tobj != mainthreadobj);
475 #if defined(__MIPS__)
476 static void cast_irixresume()
478 pthread_mutex_lock(&suspend_ack_lock);
479 pthread_cond_broadcast(&suspend_cond);
480 pthread_mutex_unlock(&suspend_ack_lock);
484 void cast_stopworld()
488 pthread_mutex_lock(&threadlistlock);
489 #if defined(__DARWIN__)
492 count = cast_sendsignals(GC_signum1(), 0);
493 for (i=0; i<count; i++)
494 threads_sem_wait(&suspend_ack);
496 pthread_mutex_unlock(&threadlistlock);
499 void cast_startworld()
501 pthread_mutex_lock(&threadlistlock);
502 #if defined(__DARWIN__)
504 #elif defined(__MIPS__)
507 cast_sendsignals(GC_signum2(), -1);
509 pthread_mutex_unlock(&threadlistlock);
513 #if !defined(__DARWIN__)
514 static void sigsuspend_handler(ucontext_t *ctx)
519 /* XXX TWISTI: this is just a quick hack */
520 #if defined(ENABLE_JIT)
521 thread_restartcriticalsection(ctx);
524 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
525 (not POSIX async-safe). */
526 #if defined(__IRIX__)
527 pthread_mutex_lock(&suspend_ack_lock);
528 threads_sem_post(&suspend_ack);
529 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
530 pthread_mutex_unlock(&suspend_ack_lock);
532 threads_sem_post(&suspend_ack);
536 sigdelset(&sigs, sig);
541 int cacao_suspendhandler(ucontext_t *ctx)
543 if (stopworldwhere != 2)
546 sigsuspend_handler(ctx);
551 #if !defined(ENABLE_JVMTI)
552 static void setthreadobject(threadobject *thread)
554 void setthreadobject(threadobject *thread)
557 #if !defined(HAVE___THREAD)
558 pthread_setspecific(tkey_threadinfo, thread);
565 /* thread_setself **************************************************************
567 Return the threadobject of the current thread.
569 XXX The return value type should be changed to a typed pointer.
571 *******************************************************************************/
573 void *thread_getself(void)
578 /* unlocked dummy record - avoids NULL checks */
579 static monitorLockRecord *dummyLR;
581 static void initPools();
584 /* thread_preinit **************************************************************
586 Do some early initialization of stuff required.
588 *******************************************************************************/
590 void threads_preinit(void)
593 pthread_mutexattr_t mutexattr;
594 pthread_mutexattr_init(&mutexattr);
595 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
596 pthread_mutex_init(&compiler_mutex, &mutexattr);
597 pthread_mutexattr_destroy(&mutexattr);
599 pthread_mutex_init_rec(&compiler_mutex);
602 pthread_mutex_init(&threadlistlock, NULL);
603 pthread_mutex_init(&stopworldlock, NULL);
605 /* Allocate something so the garbage collector's signal handlers
607 heap_allocate(1, false, NULL);
609 mainthreadobj = NEW(threadobject);
610 mainthreadobj->info.tid = pthread_self();
611 #if !defined(HAVE___THREAD)
612 pthread_key_create(&tkey_threadinfo, NULL);
614 setthreadobject(mainthreadobj);
617 /* Every newly created object's monitorPtr points here so we save
618 a check against NULL */
620 dummyLR = NEW(monitorLockRecord);
622 dummyLR->ownerThread = NULL;
623 dummyLR->waiting = NULL;
624 dummyLR->incharge = dummyLR;
626 /* we need a working dummyLR before initializing the critical
629 criticaltree = avl_create(&criticalcompare);
631 thread_addstaticcritical();
632 threads_sem_init(&suspend_ack, 0, 0);
636 static pthread_attr_t threadattr;
638 static void freeLockRecordPools(lockRecordPool *);
641 /* threads_init ****************************************************************
643 Initializes the threads required by the JVM: main, finalizer.
645 *******************************************************************************/
647 bool threads_init(u1 *stackbottom)
649 java_lang_String *threadname;
650 java_lang_Thread *mainthread;
651 java_lang_ThreadGroup *threadgroup;
652 threadobject *tempthread;
655 tempthread = mainthreadobj;
657 freeLockRecordPools(mainthreadobj->ee.lrpool);
659 /* This is kinda tricky, we grow the java.lang.Thread object so we
660 can keep the execution environment there. No Thread object must
661 have been created at an earlier time. */
663 class_java_lang_VMThread->instancesize = sizeof(threadobject);
665 /* create a VMThread */
667 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
672 FREE(tempthread, threadobject);
674 initThread(&mainthreadobj->o);
676 setthreadobject(mainthreadobj);
680 mainthreadobj->info.next = mainthreadobj;
681 mainthreadobj->info.prev = mainthreadobj;
683 #if defined(ENABLE_INTRP)
684 /* create interpreter stack */
687 MSET(intrp_main_stack, 0, u1, opt_stacksize);
688 mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
692 threadname = javastring_new(utf_new_char("main"));
694 /* allocate and init ThreadGroup */
696 threadgroup = (java_lang_ThreadGroup *)
697 native_new_and_init(class_java_lang_ThreadGroup);
700 throw_exception_exit();
702 /* create a Thread */
704 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
707 throw_exception_exit();
709 mainthreadobj->o.thread = mainthread;
711 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
713 method = class_resolveclassmethod(class_java_lang_Thread,
715 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
716 class_java_lang_Thread,
722 (void) vm_call_method(method, (java_objectheader *) mainthread,
723 mainthreadobj, threadname, 5, false);
728 mainthread->group = threadgroup;
730 /* add mainthread to ThreadGroup */
732 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
733 utf_new_char("addThread"),
734 utf_new_char("(Ljava/lang/Thread;)V"),
735 class_java_lang_ThreadGroup,
741 (void) vm_call_method(method, (java_objectheader *) threadgroup,
747 threads_set_thread_priority(pthread_self(), 5);
749 pthread_attr_init(&threadattr);
750 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
752 /* everything's ok */
758 void initThread(java_lang_VMThread *t)
760 threadobject *thread = (threadobject*) t;
761 nativethread *info = &thread->info;
762 info->tid = pthread_self();
763 /* TODO destroy all those things */
764 pthread_mutex_init(&info->joinMutex, NULL);
765 pthread_cond_init(&info->joinCond, NULL);
767 pthread_mutex_init(&thread->waitLock, NULL);
768 pthread_cond_init(&thread->waitCond, NULL);
769 thread->interrupted = false;
770 thread->signaled = false;
771 thread->isSleeping = false;
774 static void initThreadLocks(threadobject *);
777 /* startupinfo *****************************************************************
779 Struct used to pass info from threads_start_thread to
780 threads_startup_thread.
782 ******************************************************************************/
785 threadobject *thread; /* threadobject for this thread */
786 functionptr function; /* function to run in the new thread */
787 sem_t *psem; /* signals when thread has been entered */
788 /* in the thread list */
789 sem_t *psem_first; /* signals when pthread_create has returned */
793 /* threads_startup_thread ******************************************************
795 Thread startup function called by pthread_create.
797 NOTE: This function is not called directly by pthread_create. The Boehm GC
798 inserts its own GC_start_routine in between, which then calls
802 t............the argument passed to pthread_create, ie. a pointer to
803 a startupinfo struct. CAUTION: When the `psem` semaphore
804 is posted, the startupinfo struct becomes invalid! (It
805 is allocated on the stack of threads_start_thread.)
807 ******************************************************************************/
809 static void *threads_startup_thread(void *t)
811 startupinfo *startup;
812 threadobject *thread;
817 functionptr function;
819 #if defined(ENABLE_INTRP)
820 u1 *intrp_thread_stack;
822 /* create interpreter stack */
825 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
826 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
828 intrp_thread_stack = NULL;
832 /* get passed startupinfo structure and the values in there */
835 t = NULL; /* make sure it's not used wrongly */
837 thread = startup->thread;
838 function = startup->function;
839 psem = startup->psem;
841 info = &thread->info;
843 /* Seems like we've encountered a situation where info->tid was not set by
844 * pthread_create. We alleviate this problem by waiting for pthread_create
846 threads_sem_wait(startup->psem_first);
848 /* set the thread object */
850 #if defined(__DARWIN__)
851 info->mach_thread = mach_thread_self();
853 setthreadobject(thread);
855 /* insert the thread into the threadlist */
857 pthread_mutex_lock(&threadlistlock);
859 info->prev = mainthreadobj;
860 info->next = tnext = mainthreadobj->info.next;
861 mainthreadobj->info.next = thread;
862 tnext->info.prev = thread;
864 pthread_mutex_unlock(&threadlistlock);
866 /* init data structures of this thread */
868 initThreadLocks(thread);
870 /* tell threads_startup_thread that we registered ourselves */
871 /* CAUTION: *startup becomes invalid with this! */
874 threads_sem_post(psem);
876 /* set our priority */
878 threads_set_thread_priority(info->tid, thread->o.thread->priority);
880 #if defined(ENABLE_INTRP)
881 /* set interpreter stack */
884 THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
887 /* find and run the Thread.run()V method if no other function was passed */
889 if (function == NULL) {
890 method = class_resolveclassmethod(thread->o.header.vftbl->class,
893 thread->o.header.vftbl->class,
899 (void) vm_call_method(method, (java_objectheader *) thread);
903 /* call passed function, e.g. finalizer_thread */
908 /* Allow lock record pools to be used by other threads. They
909 cannot be deleted so we'd better not waste them. */
911 freeLockRecordPools(thread->ee.lrpool);
913 /* remove thread from thread list, do this inside a lock */
915 pthread_mutex_lock(&threadlistlock);
916 info->next->info.prev = info->prev;
917 info->prev->info.next = info->next;
918 pthread_mutex_unlock(&threadlistlock);
920 /* reset thread id (lock on joinMutex? TWISTI) */
922 pthread_mutex_lock(&info->joinMutex);
924 pthread_mutex_unlock(&info->joinMutex);
926 /* tell everyone that a thread has finished */
928 pthread_cond_broadcast(&info->joinCond);
934 /* threads_start_thread ********************************************************
936 Start a thread in the JVM.
939 t............the java.lang.Thread object
940 function.....function to run in the new thread. NULL means that the
941 "run" method of the object `t` should be called
943 ******************************************************************************/
945 void threads_start_thread(thread *t, functionptr function)
952 info = &((threadobject *) t->vmThread)->info;
954 /* fill startupinfo structure passed by pthread_create to
955 * threads_startup_thread */
957 startup.thread = (threadobject*) t->vmThread;
958 startup.function = function; /* maybe we don't call Thread.run()V */
960 startup.psem_first = &sem_first;
962 threads_sem_init(&sem, 0, 0);
963 threads_sem_init(&sem_first, 0, 0);
965 /* create the thread */
967 if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
969 log_text("pthread_create failed");
973 /* signal that pthread_create has returned, so info->tid is valid */
975 threads_sem_post(&sem_first);
977 /* wait here until the thread has entered itself into the thread list */
979 threads_sem_wait(&sem);
984 sem_destroy(&sem_first);
988 /* At the end of the program, we wait for all running non-daemon threads to die
991 static threadobject *findNonDaemon(threadobject *thread)
993 while (thread != mainthreadobj) {
994 if (!thread->o.thread->daemon)
996 thread = thread->info.prev;
1002 void joinAllThreads()
1004 threadobject *thread;
1005 pthread_mutex_lock(&threadlistlock);
1006 while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
1007 nativethread *info = &thread->info;
1008 pthread_mutex_lock(&info->joinMutex);
1009 pthread_mutex_unlock(&threadlistlock);
1011 pthread_cond_wait(&info->joinCond, &info->joinMutex);
1012 pthread_mutex_unlock(&info->joinMutex);
1013 pthread_mutex_lock(&threadlistlock);
1015 pthread_mutex_unlock(&threadlistlock);
1018 static void initLockRecord(monitorLockRecord *r, threadobject *t)
1025 r->incharge = (monitorLockRecord *) &dummyLR;
1027 threads_sem_init(&r->queueSem, 0, 0);
1028 pthread_mutex_init(&r->resolveLock, NULL);
1029 pthread_cond_init(&r->resolveWait, NULL);
1034 initThreadLocks(mainthreadobj);
1037 static void initThreadLocks(threadobject *thread)
1039 thread->ee.firstLR = NULL;
1040 thread->ee.lrpool = NULL;
1041 thread->ee.numlr = 0;
1044 static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
1046 lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
1049 p->header.size = size;
1050 for (i=0; i<size; i++) {
1051 initLockRecord(&p->lr[i], thread);
1052 p->lr[i].nextFree = &p->lr[i+1];
1054 p->lr[i-1].nextFree = NULL;
1058 #define INITIALLOCKRECORDS 8
1060 pthread_mutex_t pool_lock;
1061 lockRecordPool *global_pool;
1063 static void initPools()
1065 pthread_mutex_init(&pool_lock, NULL);
1068 static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
1070 pthread_mutex_lock(&pool_lock);
1073 lockRecordPool *pool = global_pool;
1074 global_pool = pool->header.next;
1075 pthread_mutex_unlock(&pool_lock);
1077 for (i=0; i < pool->header.size; i++) {
1078 pool->lr[i].ownerThread = t;
1079 pool->lr[i].nextFree = &pool->lr[i+1];
1081 pool->lr[i-1].nextFree = NULL;
1085 pthread_mutex_unlock(&pool_lock);
1087 return allocNewLockRecordPool(t, size);
1090 static void freeLockRecordPools(lockRecordPool *pool)
1092 lockRecordPoolHeader *last;
1093 pthread_mutex_lock(&pool_lock);
1094 last = &pool->header;
1096 last = &last->next->header;
1097 last->next = global_pool;
1099 pthread_mutex_unlock(&pool_lock);
1102 static monitorLockRecord *allocLockRecordSimple(threadobject *t)
1104 monitorLockRecord *r;
1110 int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
1111 lockRecordPool *pool = allocLockRecordPool(t, poolsize);
1112 pool->header.next = t->ee.lrpool;
1113 t->ee.lrpool = pool;
1115 t->ee.numlr += pool->header.size;
1118 t->ee.firstLR = r->nextFree;
1120 r->nextFree = NULL; /* in order to find invalid uses of nextFree */
1125 static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
1129 assert(r->ownerThread == t);
1130 assert(r->nextFree == NULL);
1132 r->nextFree = t->ee.firstLR;
1136 /* initObjectLock **************************************************************
1138 Initialize the monitor pointer of the given object. The monitor gets
1139 initialized to an unlocked state.
1141 *******************************************************************************/
1143 void initObjectLock(java_objectheader *o)
1147 o->monitorPtr = dummyLR;
1151 /* get_dummyLR *****************************************************************
1153 Returns the global dummy monitor lock record. The pointer is
1154 required in the code generator to set up a virtual
1155 java_objectheader for code patch locking.
1157 *******************************************************************************/
1159 monitorLockRecord *get_dummyLR(void)
1165 static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
1167 atomic_add(&lr->queuers, 1);
1168 MEMORY_BARRIER_AFTER_ATOMIC();
1171 threads_sem_wait(&lr->queueSem);
1173 atomic_add(&lr->queuers, -1);
1176 static void freeLockRecord(monitorLockRecord *lr)
1183 threads_sem_post(&lr->queueSem);
1186 static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr, java_objectheader *o)
1188 if (lr->waiting == o)
1192 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
1195 monitorLockRecord *lr = o->monitorPtr;
1197 /* the lock record does not lock this object */
1198 monitorLockRecord *nlr;
1199 monitorLockRecord *mlr;
1201 /* allocate a new lock record for this object */
1202 mlr = allocLockRecordSimple(t);
1205 /* check if it is the same record the object refered to earlier */
1208 nlr = o->monitorPtr;
1210 /* the object still refers to the same lock record */
1212 handleWaiter(mlr, lr, o);
1217 /* no, it's another lock record */
1218 /* if we don't own the old record, set incharge XXX */
1219 if (lr->ownerThread != t)
1222 /* if the object still refers to lr, replace it by the new mlr */
1223 MEMORY_BARRIER_BEFORE_ATOMIC();
1224 nlr = (monitorLockRecord *) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
1228 /* we swapped the new record in successfully */
1229 if (mlr == lr || lr->o != o) {
1230 /* the old lock record is the same as the new one, or */
1231 /* it locks another object. */
1233 handleWaiter(mlr, lr, o);
1236 /* lr locks the object, we have to wait */
1238 queueOnLockRecord(lr, o);
1241 handleWaiter(mlr, lr, o);
1245 /* forget this mlr lock record, wait on nlr and try again */
1246 freeLockRecord(mlr);
1247 recycleLockRecord(t, mlr);
1248 queueOnLockRecord(nlr, o);
1251 /* the lock record is for the object we want */
1253 if (lr->ownerThread == t) {
1254 /* we own it already, just recurse */
1259 /* it's locked. we wait and then try again */
1260 queueOnLockRecord(lr, o);
1265 static void wakeWaiters(monitorLockRecord *lr)
1267 monitorLockRecord *tmplr;
1270 /* assign lock record to a temporary variable */
1278 threads_sem_post(&tmplr->queueSem);
1280 tmplr = tmplr->waiter;
1281 } while (tmplr != NULL && tmplr != lr); /* this breaks cycles to lr */
1284 #define GRAB_LR(lr,t) \
1285 if (lr->ownerThread != t) { \
1286 lr = lr->incharge; \
1289 #define CHECK_MONITORSTATE(lr,t,mo,a) \
1290 if (lr->o != mo || lr->ownerThread != t) { \
1291 *exceptionptr = new_illegalmonitorstateexception(); \
1295 /* monitorExit *****************************************************************
1297 Decrement the counter of a (currently owned) monitor. If the counter
1298 reaches zero, release the monitor.
1300 If the current thread is not the owner of the monitor, an
1301 IllegalMonitorState exception is thrown.
1304 t............the current thread
1305 o............the object of which to exit the monitor
1308 true.........everything ok,
1309 false........an exception has been thrown
1311 *******************************************************************************/
1313 bool monitorExit(threadobject *t, java_objectheader *o)
1315 monitorLockRecord *lr;
1319 CHECK_MONITORSTATE(lr, t, o, return false);
1321 /* { the current thread `t` owns the lock record `lr` on object `o` } */
1323 if (lr->lockCount > 1) {
1324 /* we had locked this one recursively. just decrement, it will */
1325 /* still be locked. */
1330 /* we are going to unlock and recycle this lock record */
1333 monitorLockRecord *wlr = lr->waiter;
1334 if (o->monitorPtr != lr ||
1335 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
1337 monitorLockRecord *nlr = o->monitorPtr;
1338 nlr->waiter = wlr; /* XXX is it ok to overwrite the nlr->waiter field like that? */
1339 STORE_ORDER_BARRIER();
1342 threads_wake_waiters(wlr);
1347 /* unlock and throw away this lock record */
1349 recycleLockRecord(t, lr);
1353 /* threads_remove_waiter *******************************************************
1355 Remove a waiter lock record from the waiter list of the given lock record
1358 lr...........the lock record holding the waiter list
1359 toremove.....the record to remove from the list
1361 *******************************************************************************/
1363 static void threads_remove_waiter(monitorLockRecord *lr,
1364 monitorLockRecord *toremove)
1367 if (lr->waiter == toremove) {
1368 lr->waiter = toremove->waiter;
1372 } while (lr); /* XXX need to break cycle? */
1375 /* threads_timespec_earlier ****************************************************
1377 Return true if timespec tv1 is earlier than timespec tv2.
1380 tv1..........first timespec
1381 tv2..........second timespec
1384 true, if the first timespec is earlier
1386 *******************************************************************************/
1388 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1389 const struct timespec *tv2)
1391 return (tv1->tv_sec < tv2->tv_sec)
1393 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1396 /* threads_current_time_is_earlier_than ****************************************
1398 Check if the current time is earlier than the given timespec.
1401 tv...........the timespec to compare against
1404 true, if the current time is earlier
1406 *******************************************************************************/
1408 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1410 struct timeval tvnow;
1411 struct timespec tsnow;
1413 /* get current time */
1415 if (gettimeofday(&tvnow, NULL) != 0) {
1416 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1417 errno, strerror(errno));
1421 /* convert it to a timespec */
1423 tsnow.tv_sec = tvnow.tv_sec;
1424 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1426 /* compare current time with the given timespec */
1428 return threads_timespec_earlier(&tsnow, tv);
1432 /* threads_wait_with_timeout ***************************************************
1434 Wait for the given maximum amount of time on a monitor until either
1435 we are notified, we are interrupted, or the time is up.
1438 t............the current thread
1439 wakeupTime...absolute (latest) wakeup time
1440 If both tv_sec and tv_nsec are zero, this function
1441 waits for an unlimited amount of time.
1444 true.........if the wait has been interrupted,
1445 false........if the wait was ended by notification or timeout
1447 *******************************************************************************/
1449 static bool threads_wait_with_timeout(threadobject *t,
1450 struct timespec *wakeupTime)
1452 bool wasinterrupted;
1454 /* acquire the waitLock */
1456 pthread_mutex_lock(&t->waitLock);
1458 /* mark us as sleeping */
1460 t->isSleeping = true;
1462 /* wait on waitCond */
1464 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1466 while (!t->interrupted && !t->signaled
1467 && threads_current_time_is_earlier_than(wakeupTime))
1469 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1474 while (!t->interrupted && !t->signaled)
1475 pthread_cond_wait(&t->waitCond, &t->waitLock);
1478 /* check if we were interrupted */
1480 wasinterrupted = t->interrupted;
1482 /* reset all flags */
1484 t->interrupted = false;
1485 t->signaled = false;
1486 t->isSleeping = false;
1488 /* release the waitLock */
1490 pthread_mutex_unlock(&t->waitLock);
1492 return wasinterrupted;
1496 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1498 if (millis || nanos) {
1501 gettimeofday(&tv, NULL);
1502 tv.tv_sec += millis / 1000;
1504 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1505 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1506 tm->tv_nsec = nsec % 1000000000;
1514 /* monitorWait *****************************************************************
1516 Wait on an object for a given (maximum) amount of time.
1519 t............the current thread
1520 o............the object
1521 millis.......milliseconds of timeout
1522 nanos........nanoseconds of timeout
1525 The current thread must be the owner of the object's monitor.
1527 *******************************************************************************/
1529 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1531 bool wasinterrupted;
1532 struct timespec wakeupTime;
1533 monitorLockRecord *newlr;
1534 monitorLockRecord *lr;
1538 CHECK_MONITORSTATE(lr, t, o, return);
1540 /* { the thread t owns the lock record lr on the object o } */
1542 /* calculate the the (latest) wakeup time */
1544 calcAbsoluteTime(&wakeupTime, millis, nanos);
1546 /* wake threads waiting on this record XXX why? */
1549 threads_wake_waiters(lr->waiter);
1551 /* mark the lock record as "waiting on object o" */
1554 STORE_ORDER_BARRIER();
1556 /* unlock this record */
1560 /* wait until notified/interrupted/timed out */
1562 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1564 /* re-enter the monitor */
1566 newlr = monitorEnter(t, o);
1568 /* we are no longer waiting */
1570 threads_remove_waiter(newlr, lr);
1571 newlr->lockCount = lr->lockCount;
1573 /* recylce the old lock record */
1578 recycleLockRecord(t, lr);
1580 /* if we have been interrupted, throw the appropriate exception */
1583 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1586 /* notifyOneOrAll **************************************************************
1588 Notify one thread or all threads waiting on the given object.
1591 t............the current thread
1592 o............the object
1593 one..........if true, only notify one thread
1596 The current thread must be the owner of the object's monitor.
1598 *******************************************************************************/
1600 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1602 monitorLockRecord *lr = o->monitorPtr;
1604 CHECK_MONITORSTATE(lr, t, o, return);
1606 threadobject *wthread;
1607 monitorLockRecord *wlr = lr->waiter;
1610 wthread = wlr->ownerThread;
1611 pthread_mutex_lock(&wthread->waitLock);
1612 if (wthread->isSleeping)
1613 pthread_cond_signal(&wthread->waitCond);
1614 wthread->signaled = true;
1615 pthread_mutex_unlock(&wthread->waitLock);
1620 /* threadHoldsLock *************************************************************
1622 Return true if the given thread owns the monitor of the given object.
1625 t............the thread
1626 o............the object
1629 true, if the thread is locking the object
1631 *******************************************************************************/
1633 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1635 monitorLockRecord *lr;
1640 return (lr->o == o) && (lr->ownerThread == t);
1643 /* interruptThread *************************************************************
1645 Interrupt the given thread.
1647 The thread gets the "waitCond" signal and
1648 its interrupted flag is set to true.
1651 thread............the thread to interrupt
1653 *******************************************************************************/
1655 void interruptThread(java_lang_VMThread *thread)
1657 threadobject *t = (threadobject*) thread;
1659 /* signal the thread a "waitCond" and tell it that it has been */
1662 pthread_mutex_lock(&t->waitLock);
1664 pthread_cond_signal(&t->waitCond);
1665 t->interrupted = true;
1666 pthread_mutex_unlock(&t->waitLock);
1669 /* interruptedThread ***********************************************************
1671 Check if the current thread has been interrupted and reset the
1675 true, if the current thread had been interrupted
1677 *******************************************************************************/
1679 bool interruptedThread()
1684 t = (threadobject*) THREADOBJECT;
1686 intr = t->interrupted;
1688 t->interrupted = false;
1693 /* isInterruptedThread *********************************************************
1695 Check if the given thread has been interrupted
1698 t............the thread to check
1701 true, if the given thread had been interrupted
1703 *******************************************************************************/
1705 bool isInterruptedThread(java_lang_VMThread *thread)
1709 t = (threadobject*) thread;
1711 return t->interrupted;
1714 /* thread_sleep ****************************************************************
1716 Sleep the current thread for the specified amount of time.
1718 *******************************************************************************/
1720 void thread_sleep(s8 millis, s4 nanos)
1723 struct timespec wakeupTime;
1724 bool wasinterrupted;
1726 t = (threadobject *) THREADOBJECT;
1728 calcAbsoluteTime(&wakeupTime, millis, nanos);
1730 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1733 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1741 void setPriorityThread(thread *t, s4 priority)
1743 nativethread *info = &((threadobject*) t->vmThread)->info;
1744 threads_set_thread_priority(info->tid, priority);
1747 void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
1749 threadobject *t = (threadobject*) THREADOBJECT;
1750 monitorWait(t, o, millis, nanos);
1753 void signal_cond_for_object(java_objectheader *o)
1755 threadobject *t = (threadobject*) THREADOBJECT;
1756 notifyOneOrAll(t, o, true);
1759 void broadcast_cond_for_object(java_objectheader *o)
1761 threadobject *t = (threadobject*) THREADOBJECT;
1762 notifyOneOrAll(t, o, false);
1766 /* threads_dump ****************************************************************
1768 Dumps info for all threads running in the JVM. This function is
1769 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1771 *******************************************************************************/
1773 void threads_dump(void)
1776 java_lang_VMThread *vmt;
1778 java_lang_Thread *t;
1781 tobj = mainthreadobj;
1783 printf("Full thread dump CACAO "VERSION":\n");
1785 /* iterate over all started threads */
1788 /* get thread objects */
1794 /* the thread may be currently in initalization, don't print it */
1797 /* get thread name */
1799 name = javastring_toutf(t->name, false);
1808 #if SIZEOF_VOID_P == 8
1809 printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1811 printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1814 /* send SIGUSR1 to thread to print stacktrace */
1816 pthread_kill(nt->tid, SIGUSR1);
1818 /* sleep this thread a bit, so the signal can reach the thread */
1820 thread_sleep(10, 0);
1823 tobj = tobj->info.next;
1824 } while (tobj && (tobj != mainthreadobj));
1829 * These are local overrides for various environment variables in Emacs.
1830 * Please do not remove this and leave it at the end of the file, where
1831 * Emacs will automagically detect them.
1832 * ---------------------------------------------------------------------
1835 * indent-tabs-mode: t
1839 * vim:noexpandtab:sw=4:ts=4: