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 4911 2006-05-14 12:15:12Z edwin $
39 /* XXX cleanup these includes */
44 #include <sys/types.h>
52 #include <semaphore.h>
58 #if !defined(USE_MD_THREAD_STUFF)
59 #include "machine-instr.h"
61 #include "threads/native/generic-primitives.h"
65 #include "mm/memory.h"
66 #include "native/native.h"
67 #include "native/include/java_lang_Object.h"
68 #include "native/include/java_lang_Throwable.h"
69 #include "native/include/java_lang_Thread.h"
70 #include "native/include/java_lang_ThreadGroup.h"
71 #include "native/include/java_lang_VMThread.h"
72 #include "threads/native/threads.h"
73 #include "toolbox/avl.h"
74 #include "toolbox/logging.h"
75 #include "vm/builtin.h"
76 #include "vm/exceptions.h"
77 #include "vm/global.h"
78 #include "vm/loader.h"
79 #include "vm/options.h"
80 #include "vm/stringlocal.h"
82 #include "vm/jit/asmpart.h"
84 #if !defined(__DARWIN__)
85 #if defined(__LINUX__)
86 #define GC_LINUX_THREADS
87 #elif defined(__MIPS__)
88 #define GC_IRIX_THREADS
90 #include "boehm-gc/include/gc.h"
94 /* internally used constants **************************************************/
96 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
97 #define STOPWORLD_FROM_GC 1
98 #define STOPWORLD_FROM_CLASS_NUMBERING 2
101 /* startupinfo *****************************************************************
103 Struct used to pass info from threads_start_thread to
104 threads_startup_thread.
106 ******************************************************************************/
109 threadobject *thread; /* threadobject for this thread */
110 functionptr function; /* function to run in the new thread */
111 sem_t *psem; /* signals when thread has been entered */
112 /* in the thread list */
113 sem_t *psem_first; /* signals when pthread_create has returned */
117 /* prototypes *****************************************************************/
119 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
122 /******************************************************************************/
123 /* GLOBAL VARIABLES */
124 /******************************************************************************/
126 /* the main thread */
127 threadobject *mainthreadobj;
129 /* the thread object of the current thread */
130 /* This is either a thread-local variable defined with __thread, or */
131 /* a thread-specific value stored with key threads_current_threadobject_key. */
132 #if defined(HAVE___THREAD)
133 __thread threadobject *threads_current_threadobject;
135 pthread_key_t threads_current_threadobject_key;
138 /* global compiler mutex */
139 static pthread_mutex_rec_t compiler_mutex;
141 /* global mutex for changing the thread list */
142 static pthread_mutex_t threadlistlock;
144 /* global mutex for stop-the-world */
145 static pthread_mutex_t stopworldlock;
147 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
149 static volatile int stopworldwhere;
151 /* semaphore used for acknowleding thread suspension */
152 static sem_t suspend_ack;
153 #if defined(__MIPS__)
154 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
155 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
158 static pthread_attr_t threadattr;
160 /* mutexes used by the fake atomic instructions */
161 #if defined(USE_MD_THREAD_STUFF)
162 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
163 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
164 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
168 /******************************************************************************/
169 /* Recursive Mutex Implementation for Darwin */
170 /******************************************************************************/
172 #if defined(MUTEXSIM)
174 /* We need this for older MacOSX (10.1.x) */
176 void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
178 pthread_mutex_init(&m->mutex, NULL);
182 void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
184 pthread_mutex_destroy(&m->mutex);
187 void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
192 pthread_mutex_lock(&m->mutex);
193 m->owner = pthread_self();
198 if (m->owner != pthread_self()) {
199 pthread_mutex_lock(&m->mutex);
209 void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
212 pthread_mutex_unlock(&m->mutex);
215 #endif /* defined(MUTEXSIM) */
218 /* threads_sem_init ************************************************************
220 Initialize a semaphore. Checks against errors and interruptions.
223 sem..............the semaphore to initialize
224 shared...........true if this semaphore will be shared between processes
225 value............the initial value for the semaphore
227 *******************************************************************************/
229 void threads_sem_init(sem_t *sem, bool shared, int value)
236 r = sem_init(sem, shared, value);
239 } while (errno == EINTR);
241 fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
242 errno, strerror(errno));
247 /* threads_sem_wait ************************************************************
249 Wait for a semaphore, non-interruptible.
251 IMPORTANT: Always use this function instead of `sem_wait` directly, as
252 `sem_wait` may be interrupted by signals!
255 sem..............the semaphore to wait on
257 *******************************************************************************/
259 void threads_sem_wait(sem_t *sem)
269 } while (errno == EINTR);
271 fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
272 errno, strerror(errno));
277 /* threads_sem_post ************************************************************
279 Increase the count of a semaphore. Checks for errors.
282 sem..............the semaphore to increase the count of
284 *******************************************************************************/
286 void threads_sem_post(sem_t *sem)
292 /* unlike sem_wait, sem_post is not interruptible */
298 fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
299 errno, strerror(errno));
304 /* threads_set_thread_priority *************************************************
306 Set the priority of the given thread.
309 tid..........thread id
310 priority.....priority to set
312 ******************************************************************************/
314 static void threads_set_thread_priority(pthread_t tid, int priority)
316 struct sched_param schedp;
319 pthread_getschedparam(tid, &policy, &schedp);
320 schedp.sched_priority = priority;
321 pthread_setschedparam(tid, policy, &schedp);
325 /* compiler_lock ***************************************************************
327 Enter the compiler lock.
329 ******************************************************************************/
331 void compiler_lock(void)
333 pthread_mutex_lock_rec(&compiler_mutex);
337 /* compiler_unlock *************************************************************
339 Release the compiler lock.
341 ******************************************************************************/
343 void compiler_unlock(void)
345 pthread_mutex_unlock_rec(&compiler_mutex);
349 /* lock_stopworld **************************************************************
351 Enter the stopworld lock, specifying why the world shall be stopped.
354 where........ STOPWORLD_FROM_GC (1) from within GC
355 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
357 ******************************************************************************/
359 void lock_stopworld(int where)
361 pthread_mutex_lock(&stopworldlock);
362 stopworldwhere = where;
366 /* unlock_stopworld ************************************************************
368 Release the stopworld lock.
370 ******************************************************************************/
372 void unlock_stopworld(void)
375 pthread_mutex_unlock(&stopworldlock);
378 #if !defined(__DARWIN__)
379 /* Caller must hold threadlistlock */
380 static int threads_cast_sendsignals(int sig, int count)
383 threadobject *tobj = mainthreadobj;
384 nativethread *infoself = THREADINFO;
389 tobj = tobj->info.next;
390 } while (tobj != mainthreadobj);
394 nativethread *info = &tobj->info;
395 if (info != infoself)
396 pthread_kill(info->tid, sig);
397 tobj = tobj->info.next;
398 } while (tobj != mainthreadobj);
405 static void threads_cast_darwinstop(void)
407 threadobject *tobj = mainthreadobj;
408 nativethread *infoself = THREADINFO;
411 nativethread *info = &tobj->info;
412 if (info != infoself)
414 thread_state_flavor_t flavor = PPC_THREAD_STATE;
415 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
416 ppc_thread_state_t thread_state;
417 mach_port_t thread = info->mach_thread;
420 r = thread_suspend(thread);
421 if (r != KERN_SUCCESS) {
422 log_text("thread_suspend failed");
426 r = thread_get_state(thread, flavor,
427 (natural_t*)&thread_state, &thread_state_count);
428 if (r != KERN_SUCCESS) {
429 log_text("thread_get_state failed");
433 thread_restartcriticalsection(&thread_state);
435 r = thread_set_state(thread, flavor,
436 (natural_t*)&thread_state, thread_state_count);
437 if (r != KERN_SUCCESS) {
438 log_text("thread_set_state failed");
442 tobj = tobj->info.next;
443 } while (tobj != mainthreadobj);
446 static void threads_cast_darwinresume(void)
448 threadobject *tobj = mainthreadobj;
449 nativethread *infoself = THREADINFO;
452 nativethread *info = &tobj->info;
453 if (info != infoself)
455 mach_port_t thread = info->mach_thread;
458 r = thread_resume(thread);
459 if (r != KERN_SUCCESS) {
460 log_text("thread_resume failed");
464 tobj = tobj->info.next;
465 } while (tobj != mainthreadobj);
470 #if defined(__MIPS__)
471 static void threads_cast_irixresume(void)
473 pthread_mutex_lock(&suspend_ack_lock);
474 pthread_cond_broadcast(&suspend_cond);
475 pthread_mutex_unlock(&suspend_ack_lock);
479 void threads_cast_stopworld(void)
482 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
483 pthread_mutex_lock(&threadlistlock);
484 #if defined(__DARWIN__)
485 threads_cast_darwinstop();
487 count = threads_cast_sendsignals(GC_signum1(), 0);
488 for (i=0; i<count; i++)
489 threads_sem_wait(&suspend_ack);
491 pthread_mutex_unlock(&threadlistlock);
494 void threads_cast_startworld(void)
496 pthread_mutex_lock(&threadlistlock);
497 #if defined(__DARWIN__)
498 threads_cast_darwinresume();
499 #elif defined(__MIPS__)
500 threads_cast_irixresume();
502 threads_cast_sendsignals(GC_signum2(), -1);
504 pthread_mutex_unlock(&threadlistlock);
508 #if !defined(__DARWIN__)
509 static void threads_sigsuspend_handler(ucontext_t *ctx)
514 /* XXX TWISTI: this is just a quick hack */
515 #if defined(ENABLE_JIT)
516 thread_restartcriticalsection(ctx);
519 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
520 (not POSIX async-safe). */
521 #if defined(__IRIX__)
522 pthread_mutex_lock(&suspend_ack_lock);
523 threads_sem_post(&suspend_ack);
524 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
525 pthread_mutex_unlock(&suspend_ack_lock);
527 threads_sem_post(&suspend_ack);
531 sigdelset(&sigs, sig);
536 /* This function is called from Boehm GC code. */
538 int cacao_suspendhandler(ucontext_t *ctx)
540 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
543 threads_sigsuspend_handler(ctx);
549 /* threads_set_current_threadobject ********************************************
551 Set the current thread object.
554 thread.......the thread object to set
556 *******************************************************************************/
558 #if !defined(ENABLE_JVMTI)
559 static void threads_set_current_threadobject(threadobject *thread)
561 void threads_set_current_threadobject(threadobject *thread)
564 #if !defined(HAVE___THREAD)
565 pthread_setspecific(threads_current_threadobject_key, thread);
567 threads_current_threadobject = thread;
572 /* threads_get_current_threadobject ********************************************
574 Return the threadobject of the current thread.
577 the current threadobject * (an instance of java.lang.VMThread)
579 *******************************************************************************/
581 threadobject *threads_get_current_threadobject(void)
587 /* threads_preinit *************************************************************
589 Do some early initialization of stuff required.
591 *******************************************************************************/
593 void threads_preinit(void)
596 pthread_mutexattr_t mutexattr;
597 pthread_mutexattr_init(&mutexattr);
598 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
599 pthread_mutex_init(&compiler_mutex, &mutexattr);
600 pthread_mutexattr_destroy(&mutexattr);
602 pthread_mutex_init_rec(&compiler_mutex);
605 pthread_mutex_init(&threadlistlock, NULL);
606 pthread_mutex_init(&stopworldlock, NULL);
608 /* Allocate something so the garbage collector's signal handlers
610 heap_allocate(1, false, NULL);
612 mainthreadobj = NEW(threadobject);
613 mainthreadobj->info.tid = pthread_self();
614 #if !defined(HAVE___THREAD)
615 pthread_key_create(&threads_current_threadobject_key, NULL);
617 threads_set_current_threadobject(mainthreadobj);
619 /* we need a working dummyLR before initializing the critical
626 threads_sem_init(&suspend_ack, 0, 0);
630 /* threads_init ****************************************************************
632 Initializes the threads required by the JVM: main, finalizer.
634 *******************************************************************************/
636 bool threads_init(u1 *stackbottom)
638 java_lang_String *threadname;
639 java_lang_Thread *mainthread;
640 java_lang_ThreadGroup *threadgroup;
641 threadobject *tempthread;
644 tempthread = mainthreadobj;
646 lock_record_free_pools(mainthreadobj->ee.lrpool);
648 /* This is kinda tricky, we grow the java.lang.Thread object so we
649 can keep the execution environment there. No Thread object must
650 have been created at an earlier time. */
652 class_java_lang_VMThread->instancesize = sizeof(threadobject);
654 /* create a VMThread */
656 mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
661 FREE(tempthread, threadobject);
663 threads_init_threadobject(&mainthreadobj->o);
665 threads_set_current_threadobject(mainthreadobj);
667 lock_init_execution_env(mainthreadobj);
669 mainthreadobj->info.next = mainthreadobj;
670 mainthreadobj->info.prev = mainthreadobj;
672 #if defined(ENABLE_INTRP)
673 /* create interpreter stack */
676 MSET(intrp_main_stack, 0, u1, opt_stacksize);
677 mainthreadobj->info._global_sp = intrp_main_stack + opt_stacksize;
681 threadname = javastring_new(utf_new_char("main"));
683 /* allocate and init ThreadGroup */
685 threadgroup = (java_lang_ThreadGroup *)
686 native_new_and_init(class_java_lang_ThreadGroup);
689 throw_exception_exit();
691 /* create a Thread */
693 mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
696 throw_exception_exit();
698 mainthreadobj->o.thread = mainthread;
700 /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
702 method = class_resolveclassmethod(class_java_lang_Thread,
704 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
705 class_java_lang_Thread,
711 (void) vm_call_method(method, (java_objectheader *) mainthread,
712 mainthreadobj, threadname, 5, false);
717 mainthread->group = threadgroup;
719 /* add mainthread to ThreadGroup */
721 method = class_resolveclassmethod(class_java_lang_ThreadGroup,
722 utf_new_char("addThread"),
723 utf_new_char("(Ljava/lang/Thread;)V"),
724 class_java_lang_ThreadGroup,
730 (void) vm_call_method(method, (java_objectheader *) threadgroup,
736 threads_set_thread_priority(pthread_self(), 5);
738 pthread_attr_init(&threadattr);
739 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
741 /* everything's ok */
747 /* threads_init_threadobject **************************************************
749 Initialize implementation fields of a java.lang.VMThread.
752 t............the java.lang.VMThread
754 ******************************************************************************/
756 void threads_init_threadobject(java_lang_VMThread *t)
758 threadobject *thread = (threadobject*) t;
759 nativethread *info = &thread->info;
760 info->tid = pthread_self();
761 /* TODO destroy all those things */
762 pthread_mutex_init(&info->joinMutex, NULL);
763 pthread_cond_init(&info->joinCond, NULL);
765 pthread_mutex_init(&thread->waitLock, NULL);
766 pthread_cond_init(&thread->waitCond, NULL);
767 thread->interrupted = false;
768 thread->signaled = false;
769 thread->isSleeping = false;
773 /* threads_startup_thread ******************************************************
775 Thread startup function called by pthread_create.
777 NOTE: This function is not called directly by pthread_create. The Boehm GC
778 inserts its own GC_start_routine in between, which then calls
782 t............the argument passed to pthread_create, ie. a pointer to
783 a startupinfo struct. CAUTION: When the `psem` semaphore
784 is posted, the startupinfo struct becomes invalid! (It
785 is allocated on the stack of threads_start_thread.)
787 ******************************************************************************/
789 static void *threads_startup_thread(void *t)
791 startupinfo *startup;
792 threadobject *thread;
797 functionptr function;
799 #if defined(ENABLE_INTRP)
800 u1 *intrp_thread_stack;
802 /* create interpreter stack */
805 intrp_thread_stack = (u1 *) alloca(opt_stacksize);
806 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
808 intrp_thread_stack = NULL;
812 /* get passed startupinfo structure and the values in there */
815 t = NULL; /* make sure it's not used wrongly */
817 thread = startup->thread;
818 function = startup->function;
819 psem = startup->psem;
821 info = &thread->info;
823 /* Seems like we've encountered a situation where info->tid was not set by
824 * pthread_create. We alleviate this problem by waiting for pthread_create
826 threads_sem_wait(startup->psem_first);
828 /* set the thread object */
830 #if defined(__DARWIN__)
831 info->mach_thread = mach_thread_self();
833 threads_set_current_threadobject(thread);
835 /* insert the thread into the threadlist */
837 pthread_mutex_lock(&threadlistlock);
839 info->prev = mainthreadobj;
840 info->next = tnext = mainthreadobj->info.next;
841 mainthreadobj->info.next = thread;
842 tnext->info.prev = thread;
844 pthread_mutex_unlock(&threadlistlock);
846 /* init data structures of this thread */
848 lock_init_execution_env(thread);
850 /* tell threads_startup_thread that we registered ourselves */
851 /* CAUTION: *startup becomes invalid with this! */
854 threads_sem_post(psem);
856 /* set our priority */
858 threads_set_thread_priority(info->tid, thread->o.thread->priority);
860 #if defined(ENABLE_INTRP)
861 /* set interpreter stack */
864 THREADINFO->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
867 /* find and run the Thread.run()V method if no other function was passed */
869 if (function == NULL) {
870 method = class_resolveclassmethod(thread->o.header.vftbl->class,
873 thread->o.header.vftbl->class,
879 (void) vm_call_method(method, (java_objectheader *) thread);
883 /* call passed function, e.g. finalizer_thread */
888 /* Allow lock record pools to be used by other threads. They
889 cannot be deleted so we'd better not waste them. */
891 lock_record_free_pools(thread->ee.lrpool);
893 /* remove thread from thread list, do this inside a lock */
895 pthread_mutex_lock(&threadlistlock);
896 info->next->info.prev = info->prev;
897 info->prev->info.next = info->next;
898 pthread_mutex_unlock(&threadlistlock);
900 /* reset thread id (lock on joinMutex? TWISTI) */
902 pthread_mutex_lock(&info->joinMutex);
904 pthread_mutex_unlock(&info->joinMutex);
906 /* tell everyone that a thread has finished */
908 pthread_cond_broadcast(&info->joinCond);
914 /* threads_start_thread ********************************************************
916 Start a thread in the JVM.
919 t............the java.lang.Thread object
920 function.....function to run in the new thread. NULL means that the
921 "run" method of the object `t` should be called
923 ******************************************************************************/
925 void threads_start_thread(java_lang_Thread *t, functionptr function)
932 info = &((threadobject *) t->vmThread)->info;
934 /* fill startupinfo structure passed by pthread_create to
935 * threads_startup_thread */
937 startup.thread = (threadobject*) t->vmThread;
938 startup.function = function; /* maybe we don't call Thread.run()V */
940 startup.psem_first = &sem_first;
942 threads_sem_init(&sem, 0, 0);
943 threads_sem_init(&sem_first, 0, 0);
945 /* create the thread */
947 if (pthread_create(&info->tid, &threadattr, threads_startup_thread,
949 log_text("pthread_create failed");
953 /* signal that pthread_create has returned, so info->tid is valid */
955 threads_sem_post(&sem_first);
957 /* wait here until the thread has entered itself into the thread list */
959 threads_sem_wait(&sem);
964 sem_destroy(&sem_first);
968 /* threads_find_non_daemon_thread **********************************************
970 Helper function used by threads_join_all_threads for finding non-daemon threads
971 that are still running.
973 *******************************************************************************/
975 /* At the end of the program, we wait for all running non-daemon threads to die
978 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
980 while (thread != mainthreadobj) {
981 if (!thread->o.thread->daemon)
983 thread = thread->info.prev;
990 /* threads_join_all_threads ****************************************************
992 Join all non-daemon threads.
994 *******************************************************************************/
996 void threads_join_all_threads(void)
998 threadobject *thread;
999 pthread_mutex_lock(&threadlistlock);
1000 while ((thread = threads_find_non_daemon_thread(mainthreadobj->info.prev)) != NULL) {
1001 nativethread *info = &thread->info;
1002 pthread_mutex_lock(&info->joinMutex);
1003 pthread_mutex_unlock(&threadlistlock);
1005 pthread_cond_wait(&info->joinCond, &info->joinMutex);
1006 pthread_mutex_unlock(&info->joinMutex);
1007 pthread_mutex_lock(&threadlistlock);
1009 pthread_mutex_unlock(&threadlistlock);
1013 /* threads_timespec_earlier ****************************************************
1015 Return true if timespec tv1 is earlier than timespec tv2.
1018 tv1..........first timespec
1019 tv2..........second timespec
1022 true, if the first timespec is earlier
1024 *******************************************************************************/
1026 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1027 const struct timespec *tv2)
1029 return (tv1->tv_sec < tv2->tv_sec)
1031 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1035 /* threads_current_time_is_earlier_than ****************************************
1037 Check if the current time is earlier than the given timespec.
1040 tv...........the timespec to compare against
1043 true, if the current time is earlier
1045 *******************************************************************************/
1047 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1049 struct timeval tvnow;
1050 struct timespec tsnow;
1052 /* get current time */
1054 if (gettimeofday(&tvnow, NULL) != 0) {
1055 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1056 errno, strerror(errno));
1060 /* convert it to a timespec */
1062 tsnow.tv_sec = tvnow.tv_sec;
1063 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1065 /* compare current time with the given timespec */
1067 return threads_timespec_earlier(&tsnow, tv);
1071 /* threads_wait_with_timeout ***************************************************
1073 Wait until the given point in time on a monitor until either
1074 we are notified, we are interrupted, or the time is up.
1077 t............the current thread
1078 wakeupTime...absolute (latest) wakeup time
1079 If both tv_sec and tv_nsec are zero, this function
1080 waits for an unlimited amount of time.
1083 true.........if the wait has been interrupted,
1084 false........if the wait was ended by notification or timeout
1086 *******************************************************************************/
1088 static bool threads_wait_with_timeout(threadobject *t,
1089 struct timespec *wakeupTime)
1091 bool wasinterrupted;
1093 /* acquire the waitLock */
1095 pthread_mutex_lock(&t->waitLock);
1097 /* mark us as sleeping */
1099 t->isSleeping = true;
1101 /* wait on waitCond */
1103 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1105 while (!t->interrupted && !t->signaled
1106 && threads_current_time_is_earlier_than(wakeupTime))
1108 pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
1113 while (!t->interrupted && !t->signaled)
1114 pthread_cond_wait(&t->waitCond, &t->waitLock);
1117 /* check if we were interrupted */
1119 wasinterrupted = t->interrupted;
1121 /* reset all flags */
1123 t->interrupted = false;
1124 t->signaled = false;
1125 t->isSleeping = false;
1127 /* release the waitLock */
1129 pthread_mutex_unlock(&t->waitLock);
1131 return wasinterrupted;
1135 /* threads_wait_with_timeout_relative ******************************************
1137 Wait for the given maximum amount of time on a monitor until either
1138 we are notified, we are interrupted, or the time is up.
1141 t............the current thread
1142 millis.......milliseconds to wait
1143 nanos........nanoseconds to wait
1146 true.........if the wait has been interrupted,
1147 false........if the wait was ended by notification or timeout
1149 *******************************************************************************/
1151 bool threads_wait_with_timeout_relative(threadobject *t,
1155 struct timespec wakeupTime;
1157 /* calculate the the (latest) wakeup time */
1159 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1163 return threads_wait_with_timeout(t, &wakeupTime);
1167 /* threads_calc_absolute_time **************************************************
1169 Calculate the absolute point in time a given number of ms and ns from now.
1172 millis............milliseconds from now
1173 nanos.............nanoseconds from now
1176 *tm...............receives the timespec of the absolute point in time
1178 *******************************************************************************/
1180 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1182 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1185 gettimeofday(&tv, NULL);
1186 tv.tv_sec += millis / 1000;
1188 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1189 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1190 tm->tv_nsec = nsec % 1000000000;
1199 /* threads_interrupt_thread ****************************************************
1201 Interrupt the given thread.
1203 The thread gets the "waitCond" signal and
1204 its interrupted flag is set to true.
1207 thread............the thread to interrupt
1209 *******************************************************************************/
1211 void threads_interrupt_thread(java_lang_VMThread *thread)
1213 threadobject *t = (threadobject*) thread;
1215 /* signal the thread a "waitCond" and tell it that it has been */
1218 pthread_mutex_lock(&t->waitLock);
1220 pthread_cond_signal(&t->waitCond);
1221 t->interrupted = true;
1222 pthread_mutex_unlock(&t->waitLock);
1226 /* threads_check_if_interrupted_and_reset **************************************
1228 Check if the current thread has been interrupted and reset the
1232 true, if the current thread had been interrupted
1234 *******************************************************************************/
1236 bool threads_check_if_interrupted_and_reset(void)
1241 t = (threadobject*) THREADOBJECT;
1243 intr = t->interrupted;
1245 t->interrupted = false;
1251 /* threads_thread_has_been_interrupted *********************************************************
1253 Check if the given thread has been interrupted
1256 t............the thread to check
1259 true, if the given thread had been interrupted
1261 *******************************************************************************/
1263 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1267 t = (threadobject*) thread;
1269 return t->interrupted;
1273 /* threads_sleep ***************************************************************
1275 Sleep the current thread for the specified amount of time.
1277 *******************************************************************************/
1279 void threads_sleep(s8 millis, s4 nanos)
1282 struct timespec wakeupTime;
1283 bool wasinterrupted;
1285 t = (threadobject *) THREADOBJECT;
1287 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1289 wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1292 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1296 /* threads_yield *****************************************************************
1298 Yield to the scheduler.
1300 *******************************************************************************/
1302 void threads_yield(void)
1308 /* threads_java_lang_Thread_set_priority ***********************************************************
1310 Set the priority for the given java.lang.Thread.
1313 t............the java.lang.Thread
1314 priority.....the priority
1316 *******************************************************************************/
1318 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1320 nativethread *info = &((threadobject*) t->vmThread)->info;
1321 threads_set_thread_priority(info->tid, priority);
1325 /* threads_dump ****************************************************************
1327 Dumps info for all threads running in the JVM. This function is
1328 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1330 *******************************************************************************/
1332 void threads_dump(void)
1335 java_lang_VMThread *vmt;
1337 java_lang_Thread *t;
1340 tobj = mainthreadobj;
1342 printf("Full thread dump CACAO "VERSION":\n");
1344 /* iterate over all started threads */
1347 /* get thread objects */
1353 /* the thread may be currently in initalization, don't print it */
1356 /* get thread name */
1358 name = javastring_toutf(t->name, false);
1361 utf_display_printable_ascii(name);
1367 #if SIZEOF_VOID_P == 8
1368 printf("prio=%d tid=0x%016lx\n", t->priority, nt->tid);
1370 printf("prio=%d tid=0x%08lx\n", t->priority, nt->tid);
1373 /* send SIGUSR1 to thread to print stacktrace */
1375 pthread_kill(nt->tid, SIGUSR1);
1377 /* sleep this thread a bit, so the signal can reach the thread */
1379 threads_sleep(10, 0);
1382 tobj = tobj->info.next;
1383 } while (tobj && (tobj != mainthreadobj));
1388 * These are local overrides for various environment variables in Emacs.
1389 * Please do not remove this and leave it at the end of the file, where
1390 * Emacs will automagically detect them.
1391 * ---------------------------------------------------------------------
1394 * indent-tabs-mode: t
1398 * vim:noexpandtab:sw=4:ts=4: