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 4903 2006-05-11 12:48:43Z 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 *newlr,
1187 monitorLockRecord *curlr,
1188 java_objectheader *o)
1190 /* if the current lock record is used for waiting on the object */
1191 /* `o`, then record it as a waiter in the new lock record */
1193 if (curlr->waiting == o)
1194 newlr->waiter = curlr;
1197 /* monitorEnter ****************************************************************
1199 Acquire the monitor of the given object. If the current thread already
1200 owns the monitor, the lock counter is simply increased.
1202 This function blocks until it can acquire the monitor.
1205 t............the current thread
1206 o............the object of which to enter the monitor
1209 the new lock record of the object when it has been entered
1211 *******************************************************************************/
1213 monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
1216 monitorLockRecord *lr = o->monitorPtr;
1218 /* the lock record does not lock this object */
1219 monitorLockRecord *nlr;
1220 monitorLockRecord *mlr;
1222 /* allocate a new lock record for this object */
1223 mlr = allocLockRecordSimple(t);
1226 /* check if it is the same record the object refered to earlier */
1229 nlr = o->monitorPtr;
1231 /* the object still refers to the same lock record */
1233 handleWaiter(mlr, lr, o);
1238 /* no, it's another lock record */
1239 /* if we don't own the old record, set incharge XXX */
1240 if (lr->ownerThread != t)
1243 /* if the object still refers to lr, replace it by the new mlr */
1244 MEMORY_BARRIER_BEFORE_ATOMIC();
1245 nlr = (monitorLockRecord *) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
1249 /* we swapped the new record in successfully */
1250 if (mlr == lr || lr->o != o) {
1251 /* the old lock record is the same as the new one, or */
1252 /* it locks another object. */
1254 handleWaiter(mlr, lr, o);
1257 /* lr locks the object, we have to wait */
1259 queueOnLockRecord(lr, o);
1262 handleWaiter(mlr, lr, o);
1266 /* forget this mlr lock record, wait on nlr and try again */
1267 freeLockRecord(mlr);
1268 recycleLockRecord(t, mlr);
1269 queueOnLockRecord(nlr, o);
1272 /* the lock record is for the object we want */
1274 if (lr->ownerThread == t) {
1275 /* we own it already, just recurse */
1280 /* it's locked. we wait and then try again */
1281 queueOnLockRecord(lr, o);
1286 /* threads_wake_waiters ********************************************************
1288 For each lock record in the given waiter list, post the queueSem
1289 once for each queuer of the lock record.
1292 lr...........the head of the waiter list
1294 *******************************************************************************/
1296 static void threads_wake_waiters(monitorLockRecord *lr)
1298 monitorLockRecord *tmplr;
1301 /* move it to a local variable (Stefan commented this especially.
1302 * Might be important somehow...) */
1310 threads_sem_post(&tmplr->queueSem);
1312 tmplr = tmplr->waiter;
1313 } while (tmplr != NULL && tmplr != lr); /* this breaks cycles to lr */
1316 #define GRAB_LR(lr,t) \
1317 if (lr->ownerThread != t) { \
1318 lr = lr->incharge; \
1321 #define CHECK_MONITORSTATE(lr,t,mo,a) \
1322 if (lr->o != mo || lr->ownerThread != t) { \
1323 *exceptionptr = new_illegalmonitorstateexception(); \
1327 /* monitorExit *****************************************************************
1329 Decrement the counter of a (currently owned) monitor. If the counter
1330 reaches zero, release the monitor.
1332 If the current thread is not the owner of the monitor, an
1333 IllegalMonitorState exception is thrown.
1336 t............the current thread
1337 o............the object of which to exit the monitor
1340 true.........everything ok,
1341 false........an exception has been thrown
1343 *******************************************************************************/
1345 bool monitorExit(threadobject *t, java_objectheader *o)
1347 monitorLockRecord *lr;
1351 CHECK_MONITORSTATE(lr, t, o, return false);
1353 /* { the current thread `t` owns the lock record `lr` on object `o` } */
1355 if (lr->lockCount > 1) {
1356 /* we had locked this one recursively. just decrement, it will */
1357 /* still be locked. */
1362 /* we are going to unlock and recycle this lock record */
1365 monitorLockRecord *wlr = lr->waiter;
1366 if (o->monitorPtr != lr ||
1367 (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
1369 monitorLockRecord *nlr = o->monitorPtr;
1370 assert(nlr->waiter == NULL);
1371 nlr->waiter = wlr; /* XXX is it ok to overwrite the nlr->waiter field like that? */
1372 STORE_ORDER_BARRIER();
1375 threads_wake_waiters(wlr);
1380 /* unlock and throw away this lock record */
1382 recycleLockRecord(t, lr);
1386 /* threads_remove_waiter *******************************************************
1388 Remove a waiter lock record from the waiter list of the given lock record
1391 lr...........the lock record holding the waiter list
1392 toremove.....the record to remove from the list
1394 *******************************************************************************/
1396 static void threads_remove_waiter(monitorLockRecord *lr,
1397 monitorLockRecord *toremove)
1400 if (lr->waiter == toremove) {
1401 lr->waiter = toremove->waiter;
1405 } while (lr); /* XXX need to break cycle? */
1408 /* threads_timespec_earlier ****************************************************
1410 Return true if timespec tv1 is earlier than timespec tv2.
1413 tv1..........first timespec
1414 tv2..........second timespec
1417 true, if the first timespec is earlier
1419 *******************************************************************************/
1421 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1422 const struct timespec *tv2)
1424 return (tv1->tv_sec < tv2->tv_sec)
1426 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1429 /* threads_current_time_is_earlier_than ****************************************
1431 Check if the current time is earlier than the given timespec.
1434 tv...........the timespec to compare against
1437 true, if the current time is earlier
1439 *******************************************************************************/
1441 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1443 struct timeval tvnow;
1444 struct timespec tsnow;
1446 /* get current time */
1448 if (gettimeofday(&tvnow, NULL) != 0) {
1449 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1450 errno, strerror(errno));
1454 /* convert it to a timespec */
1456 tsnow.tv_sec = tvnow.tv_sec;
1457 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1459 /* compare current time with the given timespec */
1461 return threads_timespec_earlier(&tsnow, tv);
1465 /* threads_wait_with_timeout ***************************************************
1467 Wait for the given maximum amount of time on a monitor until either
1468 we are notified, we are interrupted, or the time is up.
1471 t............the current thread
1472 wakeupTime...absolute (latest) wakeup time
1473 If both tv_sec and tv_nsec are zero, this function
1474 waits for an unlimited amount of time.
1477 true.........if the wait has been interrupted,
1478 false........if the wait was ended by notification or timeout
1480 *******************************************************************************/
1482 static bool threads_wait_with_timeout(threadobject *t,
1483 struct timespec *wakeupTime)
1485 bool wasinterrupted;
1487 /* acquire the waitLock */
1489 pthread_mutex_lock(&t->waitLock);
1491 /* mark us as sleeping */
1493 t->isSleeping = true;
1495 /* wait on waitCond */
1497 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1499 while (!t->interrupted && !t->signaled
1500 && threads_current_time_is_earlier_than(wakeupTime))
1502 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1507 while (!t->interrupted && !t->signaled)
1508 pthread_cond_wait(&t->waitCond, &t->waitLock);
1511 /* check if we were interrupted */
1513 wasinterrupted = t->interrupted;
1515 /* reset all flags */
1517 t->interrupted = false;
1518 t->signaled = false;
1519 t->isSleeping = false;
1521 /* release the waitLock */
1523 pthread_mutex_unlock(&t->waitLock);
1525 return wasinterrupted;
1529 static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
1531 if (millis || nanos) {
1534 gettimeofday(&tv, NULL);
1535 tv.tv_sec += millis / 1000;
1537 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1538 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1539 tm->tv_nsec = nsec % 1000000000;
1547 /* monitorWait *****************************************************************
1549 Wait on an object for a given (maximum) amount of time.
1552 t............the current thread
1553 o............the object
1554 millis.......milliseconds of timeout
1555 nanos........nanoseconds of timeout
1558 The current thread must be the owner of the object's monitor.
1560 *******************************************************************************/
1562 void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
1564 bool wasinterrupted;
1565 struct timespec wakeupTime;
1566 monitorLockRecord *newlr;
1567 monitorLockRecord *lr;
1571 CHECK_MONITORSTATE(lr, t, o, return);
1573 /* { the thread t owns the lock record lr on the object o } */
1575 /* calculate the the (latest) wakeup time */
1577 calcAbsoluteTime(&wakeupTime, millis, nanos);
1579 /* wake threads waiting on this record XXX why? */
1582 threads_wake_waiters(lr->waiter);
1584 /* mark the lock record as "waiting on object o" */
1587 STORE_ORDER_BARRIER();
1589 /* unlock this record */
1593 /* wait until notified/interrupted/timed out */
1595 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1597 /* re-enter the monitor */
1599 newlr = monitorEnter(t, o);
1601 /* we are no longer waiting */
1603 threads_remove_waiter(newlr, lr);
1604 newlr->lockCount = lr->lockCount;
1606 /* recylce the old lock record */
1611 recycleLockRecord(t, lr);
1613 /* if we have been interrupted, throw the appropriate exception */
1616 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1619 /* notifyOneOrAll **************************************************************
1621 Notify one thread or all threads waiting on the given object.
1624 t............the current thread
1625 o............the object
1626 one..........if true, only notify one thread
1629 The current thread must be the owner of the object's monitor.
1631 *******************************************************************************/
1633 static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
1635 monitorLockRecord *lr;
1636 monitorLockRecord *wlr;
1637 threadobject *wthread;
1641 CHECK_MONITORSTATE(lr, t, o, return);
1643 /* { the thread t owns the lock record lr on the object o } */
1645 /* for each waiter: */
1647 for (wlr = lr->waiter; wlr; wlr = wlr->waiter) {
1649 /* signal the waiting thread */
1651 wthread = wlr->ownerThread;
1652 pthread_mutex_lock(&wthread->waitLock);
1653 if (wthread->isSleeping)
1654 pthread_cond_signal(&wthread->waitCond);
1655 wthread->signaled = true;
1656 pthread_mutex_unlock(&wthread->waitLock);
1658 /* if we should only wake one, we are done */
1665 /* threadHoldsLock *************************************************************
1667 Return true if the given thread owns the monitor of the given object.
1670 t............the thread
1671 o............the object
1674 true, if the thread is locking the object
1676 *******************************************************************************/
1678 bool threadHoldsLock(threadobject *t, java_objectheader *o)
1680 monitorLockRecord *lr;
1685 return (lr->o == o) && (lr->ownerThread == t);
1688 /* interruptThread *************************************************************
1690 Interrupt the given thread.
1692 The thread gets the "waitCond" signal and
1693 its interrupted flag is set to true.
1696 thread............the thread to interrupt
1698 *******************************************************************************/
1700 void interruptThread(java_lang_VMThread *thread)
1702 threadobject *t = (threadobject*) thread;
1704 /* signal the thread a "waitCond" and tell it that it has been */
1707 pthread_mutex_lock(&t->waitLock);
1709 pthread_cond_signal(&t->waitCond);
1710 t->interrupted = true;
1711 pthread_mutex_unlock(&t->waitLock);
1714 /* interruptedThread ***********************************************************
1716 Check if the current thread has been interrupted and reset the
1720 true, if the current thread had been interrupted
1722 *******************************************************************************/
1724 bool interruptedThread()
1729 t = (threadobject*) THREADOBJECT;
1731 intr = t->interrupted;
1733 t->interrupted = false;
1738 /* isInterruptedThread *********************************************************
1740 Check if the given thread has been interrupted
1743 t............the thread to check
1746 true, if the given thread had been interrupted
1748 *******************************************************************************/
1750 bool isInterruptedThread(java_lang_VMThread *thread)
1754 t = (threadobject*) thread;
1756 return t->interrupted;
1759 /* thread_sleep ****************************************************************
1761 Sleep the current thread for the specified amount of time.
1763 *******************************************************************************/
1765 void thread_sleep(s8 millis, s4 nanos)
1768 struct timespec wakeupTime;
1769 bool wasinterrupted;
1771 t = (threadobject *) THREADOBJECT;
1773 calcAbsoluteTime(&wakeupTime, millis, nanos);
1775 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1778 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1786 void setPriorityThread(thread *t, s4 priority)
1788 nativethread *info = &((threadobject*) t->vmThread)->info;
1789 threads_set_thread_priority(info->tid, priority);
1792 void wait_cond_for_object(java_objectheader *o, s8 millis, s4 nanos)
1794 threadobject *t = (threadobject*) THREADOBJECT;
1795 monitorWait(t, o, millis, nanos);
1798 void signal_cond_for_object(java_objectheader *o)
1800 threadobject *t = (threadobject*) THREADOBJECT;
1801 notifyOneOrAll(t, o, true);
1804 void broadcast_cond_for_object(java_objectheader *o)
1806 threadobject *t = (threadobject*) THREADOBJECT;
1807 notifyOneOrAll(t, o, false);
1811 /* threads_dump ****************************************************************
1813 Dumps info for all threads running in the JVM. This function is
1814 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1816 *******************************************************************************/
1818 void threads_dump(void)
1821 java_lang_VMThread *vmt;
1823 java_lang_Thread *t;
1826 tobj = mainthreadobj;
1828 printf("Full thread dump CACAO "VERSION":\n");
1830 /* iterate over all started threads */
1833 /* get thread objects */
1839 /* the thread may be currently in initalization, don't print it */
1842 /* get thread name */
1844 name = javastring_toutf(t->name, false);
1847 utf_display_printable_ascii(name);
1853 #if SIZEOF_VOID_P == 8
1854 printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1856 printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1859 /* send SIGUSR1 to thread to print stacktrace */
1861 pthread_kill(nt->tid, SIGUSR1);
1863 /* sleep this thread a bit, so the signal can reach the thread */
1865 thread_sleep(10, 0);
1868 tobj = tobj->info.next;
1869 } while (tobj && (tobj != mainthreadobj));
1874 * These are local overrides for various environment variables in Emacs.
1875 * Please do not remove this and leave it at the end of the file, where
1876 * Emacs will automagically detect them.
1877 * ---------------------------------------------------------------------
1880 * indent-tabs-mode: t
1884 * vim:noexpandtab:sw=4:ts=4: