1 /* src/threads/native/threads.c - native threads support
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 /* XXX cleanup these includes */
33 #include <sys/types.h>
46 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
47 # include "machine-instr.h"
49 # include "threads/native/generic-primitives.h"
52 #include "mm/gc-common.h"
53 #include "mm/memory.h"
55 #if defined(ENABLE_GC_CACAO)
56 # include "mm/cacao-gc/gc.h"
59 #include "native/jni.h"
60 #include "native/llni.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Object.h"
63 #include "native/include/java_lang_String.h"
64 #include "native/include/java_lang_Throwable.h"
65 #include "native/include/java_lang_Thread.h"
67 #if defined(ENABLE_JAVASE)
68 # include "native/include/java_lang_ThreadGroup.h"
71 #if defined(WITH_CLASSPATH_GNU)
72 # include "native/include/java_lang_VMThread.h"
75 #include "threads/lock-common.h"
76 #include "threads/threadlist.h"
77 #include "threads/threads-common.h"
79 #include "threads/native/threads.h"
81 #include "toolbox/logging.h"
83 #include "vm/builtin.h"
84 #include "vm/exceptions.h"
85 #include "vm/global.h"
86 #include "vm/stringlocal.h"
89 #include "vm/jit/asmpart.h"
91 #include "vmcore/options.h"
93 #if defined(ENABLE_STATISTICS)
94 # include "vmcore/statistics.h"
97 #if !defined(__DARWIN__)
98 # if defined(__LINUX__)
99 # define GC_LINUX_THREADS
100 # elif defined(__IRIX__)
101 # define GC_IRIX_THREADS
103 # include <semaphore.h>
104 # if defined(ENABLE_GC_BOEHM)
105 # include "mm/boehm-gc/include/gc.h"
109 #if defined(ENABLE_JVMTI)
110 #include "native/jvmti/cacaodbg.h"
113 #if defined(__DARWIN__)
114 /* Darwin has no working semaphore implementation. This one is taken
118 This is a very simple semaphore implementation for darwin. It
119 is implemented in terms of pthreads calls so it isn't async signal
120 safe. This isn't a problem because signals aren't used to
121 suspend threads on darwin.
124 static int sem_init(sem_t *sem, int pshared, int value)
131 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
134 if (pthread_cond_init(&sem->cond, NULL) < 0)
140 static int sem_post(sem_t *sem)
142 if (pthread_mutex_lock(&sem->mutex) < 0)
147 if (pthread_cond_signal(&sem->cond) < 0) {
148 pthread_mutex_unlock(&sem->mutex);
152 if (pthread_mutex_unlock(&sem->mutex) < 0)
158 static int sem_wait(sem_t *sem)
160 if (pthread_mutex_lock(&sem->mutex) < 0)
163 while (sem->value == 0) {
164 pthread_cond_wait(&sem->cond, &sem->mutex);
169 if (pthread_mutex_unlock(&sem->mutex) < 0)
175 static int sem_destroy(sem_t *sem)
177 if (pthread_cond_destroy(&sem->cond) < 0)
180 if (pthread_mutex_destroy(&sem->mutex) < 0)
185 #endif /* defined(__DARWIN__) */
188 /* internally used constants **************************************************/
190 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
191 #define STOPWORLD_FROM_GC 1
192 #define STOPWORLD_FROM_CLASS_NUMBERING 2
195 /* startupinfo *****************************************************************
197 Struct used to pass info from threads_start_thread to
198 threads_startup_thread.
200 ******************************************************************************/
203 threadobject *thread; /* threadobject for this thread */
204 functionptr function; /* function to run in the new thread */
205 sem_t *psem; /* signals when thread has been entered */
206 /* in the thread list */
207 sem_t *psem_first; /* signals when pthread_create has returned */
211 /* prototypes *****************************************************************/
213 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
216 /******************************************************************************/
217 /* GLOBAL VARIABLES */
218 /******************************************************************************/
220 static methodinfo *method_thread_init;
222 /* the thread object of the current thread */
223 /* This is either a thread-local variable defined with __thread, or */
224 /* a thread-specific value stored with key threads_current_threadobject_key. */
225 #if defined(HAVE___THREAD)
226 __thread threadobject *threads_current_threadobject;
228 pthread_key_t threads_current_threadobject_key;
231 /* global mutex for the threads table */
232 static pthread_mutex_t mutex_threads_list;
234 /* global mutex for stop-the-world */
235 static pthread_mutex_t stopworldlock;
237 #if defined(ENABLE_GC_CACAO)
238 /* global mutex for the GC */
239 static pthread_mutex_t mutex_gc;
242 /* global mutex and condition for joining threads on exit */
243 static pthread_mutex_t mutex_join;
244 static pthread_cond_t cond_join;
246 /* XXX We disable that whole bunch of code until we have the exact-GC
251 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
253 static volatile int stopworldwhere;
255 /* semaphore used for acknowleding thread suspension */
256 static sem_t suspend_ack;
257 #if defined(__IRIX__)
258 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
259 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
264 /* mutexes used by the fake atomic instructions */
265 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
266 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
267 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
268 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
272 /* threads_sem_init ************************************************************
274 Initialize a semaphore. Checks against errors and interruptions.
277 sem..............the semaphore to initialize
278 shared...........true if this semaphore will be shared between processes
279 value............the initial value for the semaphore
281 *******************************************************************************/
283 void threads_sem_init(sem_t *sem, bool shared, int value)
290 r = sem_init(sem, shared, value);
293 } while (errno == EINTR);
295 vm_abort("sem_init failed: %s", strerror(errno));
299 /* threads_sem_wait ************************************************************
301 Wait for a semaphore, non-interruptible.
303 IMPORTANT: Always use this function instead of `sem_wait` directly, as
304 `sem_wait` may be interrupted by signals!
307 sem..............the semaphore to wait on
309 *******************************************************************************/
311 void threads_sem_wait(sem_t *sem)
321 } while (errno == EINTR);
323 vm_abort("sem_wait failed: %s", strerror(errno));
327 /* threads_sem_post ************************************************************
329 Increase the count of a semaphore. Checks for errors.
332 sem..............the semaphore to increase the count of
334 *******************************************************************************/
336 void threads_sem_post(sem_t *sem)
342 /* unlike sem_wait, sem_post is not interruptible */
348 vm_abort("sem_post failed: %s", strerror(errno));
352 /* lock_stopworld **************************************************************
354 Enter the stopworld lock, specifying why the world shall be stopped.
357 where........ STOPWORLD_FROM_GC (1) from within GC
358 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
360 ******************************************************************************/
362 void lock_stopworld(int where)
364 pthread_mutex_lock(&stopworldlock);
365 /* stopworldwhere = where; */
369 /* unlock_stopworld ************************************************************
371 Release the stopworld lock.
373 ******************************************************************************/
375 void unlock_stopworld(void)
377 /* stopworldwhere = 0; */
378 pthread_mutex_unlock(&stopworldlock);
381 /* XXX We disable that whole bunch of code until we have the exact-GC
386 #if !defined(__DARWIN__)
387 /* Caller must hold threadlistlock */
388 static s4 threads_cast_sendsignals(s4 sig)
396 /* iterate over all started threads */
400 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
401 /* don't send the signal to ourself */
406 /* don't send the signal to NEW threads (because they are not
407 completely initialized) */
409 if (t->state == THREAD_STATE_NEW)
412 /* send the signal */
414 pthread_kill(t->tid, sig);
416 /* increase threads count */
426 static void threads_cast_darwinstop(void)
428 threadobject *tobj = mainthreadobj;
429 threadobject *self = THREADOBJECT;
434 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
435 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
436 #if defined(__I386__)
437 i386_thread_state_t thread_state;
439 ppc_thread_state_t thread_state;
441 mach_port_t thread = tobj->mach_thread;
444 r = thread_suspend(thread);
446 if (r != KERN_SUCCESS)
447 vm_abort("thread_suspend failed");
449 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
450 &thread_state_count);
452 if (r != KERN_SUCCESS)
453 vm_abort("thread_get_state failed");
455 md_critical_section_restart((ucontext_t *) &thread_state);
457 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
460 if (r != KERN_SUCCESS)
461 vm_abort("thread_set_state failed");
465 } while (tobj != mainthreadobj);
468 static void threads_cast_darwinresume(void)
470 threadobject *tobj = mainthreadobj;
471 threadobject *self = THREADOBJECT;
476 mach_port_t thread = tobj->mach_thread;
479 r = thread_resume(thread);
481 if (r != KERN_SUCCESS)
482 vm_abort("thread_resume failed");
486 } while (tobj != mainthreadobj);
491 #if defined(__IRIX__)
492 static void threads_cast_irixresume(void)
494 pthread_mutex_lock(&suspend_ack_lock);
495 pthread_cond_broadcast(&suspend_cond);
496 pthread_mutex_unlock(&suspend_ack_lock);
500 #if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
501 static void threads_sigsuspend_handler(ucontext_t *_uc)
506 /* XXX TWISTI: this is just a quick hack */
507 #if defined(ENABLE_JIT)
508 md_critical_section_restart(_uc);
511 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
512 (not POSIX async-safe). */
513 #if defined(__IRIX__)
514 pthread_mutex_lock(&suspend_ack_lock);
515 threads_sem_post(&suspend_ack);
516 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
517 pthread_mutex_unlock(&suspend_ack_lock);
518 #elif defined(__CYGWIN__)
525 sigdelset(&sigs, sig);
534 /* threads_stopworld ***********************************************************
536 Stops the world from turning. All threads except the calling one
537 are suspended. The function returns as soon as all threads have
538 acknowledged their suspension.
540 *******************************************************************************/
542 #if !defined(DISABLE_GC)
543 void threads_stopworld(void)
545 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
552 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
554 /* lock the threads lists */
558 #if defined(__DARWIN__)
559 /*threads_cast_darwinstop();*/
561 #elif defined(__CYGWIN__)
567 DEBUGTHREADS("stops World", self);
571 /* suspend all running threads */
572 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
573 /* don't send the signal to ourself */
578 /* don't send the signal to NEW threads (because they are not
579 completely initialized) */
581 if (t->state == THREAD_STATE_NEW)
584 /* send the signal */
586 result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
589 /* increase threads count */
594 /* wait for all threads signaled to suspend */
595 for (i = 0; i < count; i++)
596 threads_sem_wait(&suspend_ack);
599 /* ATTENTION: Don't unlock the threads-lists here so that
600 non-signaled NEW threads can't change their state and execute
603 #endif /* !defined(DISABLE_GC) */
606 /* threads_startworld **********************************************************
608 Starts the world again after it has previously been stopped.
610 *******************************************************************************/
612 #if !defined(DISABLE_GC)
613 void threads_startworld(void)
615 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
622 #if defined(__DARWIN__)
623 /*threads_cast_darwinresume();*/
625 #elif defined(__IRIX__)
626 threads_cast_irixresume();
627 #elif defined(__CYGWIN__)
633 DEBUGTHREADS("starts World", self);
637 /* resume all thread we haltet */
638 for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
639 /* don't send the signal to ourself */
644 /* don't send the signal to NEW threads (because they are not
645 completely initialized) */
647 if (t->state == THREAD_STATE_NEW)
650 /* send the signal */
652 result = threads_resume_thread(t);
655 /* increase threads count */
660 /* wait for all threads signaled to suspend */
661 for (i = 0; i < count; i++)
662 threads_sem_wait(&suspend_ack);
666 /* unlock the threads lists */
668 threads_list_unlock();
675 /* threads_set_current_threadobject ********************************************
677 Set the current thread object.
680 thread.......the thread object to set
682 *******************************************************************************/
684 void threads_set_current_threadobject(threadobject *thread)
686 #if !defined(HAVE___THREAD)
687 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
688 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
690 threads_current_threadobject = thread;
695 /* threads_impl_thread_init ****************************************************
697 Initialize OS-level locking constructs in threadobject.
700 t....the threadobject
702 *******************************************************************************/
704 void threads_impl_thread_init(threadobject *t)
708 /* initialize the mutex and the condition */
710 result = pthread_mutex_init(&t->flc_lock, NULL);
712 vm_abort_errnum(result, "threads_impl_thread_new: pthread_mutex_init failed");
714 result = pthread_cond_init(&t->flc_cond, NULL);
716 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
718 result = pthread_mutex_init(&(t->waitmutex), NULL);
720 vm_abort_errnum(result, "threads_impl_thread_new: pthread_mutex_init failed");
722 result = pthread_cond_init(&(t->waitcond), NULL);
724 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
726 result = pthread_mutex_init(&(t->suspendmutex), NULL);
728 vm_abort_errnum(result, "threads_impl_thread_new: pthread_mutex_init failed");
730 result = pthread_cond_init(&(t->suspendcond), NULL);
732 vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
735 /* threads_impl_thread_clear ***************************************************
737 Clears all fields in threadobject the way an MZERO would have
738 done. MZERO cannot be used anymore because it would mess up the
742 t....the threadobject
744 *******************************************************************************/
746 void threads_impl_thread_clear(threadobject *t)
758 #if defined(__DARWIN__)
762 t->interrupted = false;
766 t->suspended = false;
767 t->suspend_reason = 0;
771 t->_exceptionptr = NULL;
772 t->_stackframeinfo = NULL;
773 t->_localref_table = NULL;
775 #if defined(ENABLE_INTRP)
776 t->_global_sp = NULL;
779 #if defined(ENABLE_GC_CACAO)
780 t->gc_critical = false;
786 MZERO(&t->dumpinfo, dumpinfo_t, 1);
789 /* threads_impl_thread_reuse ***************************************************
791 Resets some implementation fields in threadobject. This was
792 previously done in threads_impl_thread_new.
795 t....the threadobject
797 *******************************************************************************/
799 void threads_impl_thread_reuse(threadobject *t)
801 /* get the pthread id */
803 t->tid = pthread_self();
805 #if defined(ENABLE_DEBUG_FILTER)
806 /* Initialize filter counters */
807 t->filterverbosecallctr[0] = 0;
808 t->filterverbosecallctr[1] = 0;
812 t->tracejavacallindent = 0;
813 t->tracejavacallcount = 0;
820 /* not really needed */
821 t->flc_object = NULL;
825 /* threads_impl_thread_free ****************************************************
827 Cleanup thread stuff.
830 t....the threadobject
832 *******************************************************************************/
836 void threads_impl_thread_free(threadobject *t)
840 /* Destroy the mutex and the condition. */
842 result = pthread_mutex_destroy(&(t->flc_lock));
845 vm_abort_errnum(result, "threads_impl_thread_free: pthread_mutex_destroy failed");
847 result = pthread_cond_destroy(&(t->flc_cond));
850 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
852 result = pthread_mutex_destroy(&(t->waitmutex));
855 vm_abort_errnum(result, "threads_impl_thread_free: pthread_mutex_destroy failed");
857 result = pthread_cond_destroy(&(t->waitcond));
860 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
862 result = pthread_mutex_destroy(&(t->suspendmutex));
865 vm_abort_errnum(result, "threads_impl_thread_free: pthread_mutex_destroy failed");
867 result = pthread_cond_destroy(&(t->suspendcond));
870 vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
875 /* threads_get_current_threadobject ********************************************
877 Return the threadobject of the current thread.
880 the current threadobject *
882 *******************************************************************************/
884 threadobject *threads_get_current_threadobject(void)
890 /* threads_impl_preinit ********************************************************
892 Do some early initialization of stuff required.
894 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
895 is called AFTER this function!
897 *******************************************************************************/
899 void threads_impl_preinit(void)
903 result = pthread_mutex_init(&stopworldlock, NULL);
905 vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
907 /* initialize exit mutex and condition (on exit we join all
910 result = pthread_mutex_init(&mutex_join, NULL);
912 vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
914 result = pthread_cond_init(&cond_join, NULL);
916 vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
918 #if defined(ENABLE_GC_CACAO)
919 /* initialize the GC mutext */
921 result = pthread_mutex_init(&mutex_gc, NULL);
923 vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
926 /* initialize the threads-list mutex */
928 result = pthread_mutex_init(&mutex_threads_list, NULL);
930 vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
932 #if !defined(HAVE___THREAD)
933 result = pthread_key_create(&threads_current_threadobject_key, NULL);
935 vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
938 threads_sem_init(&suspend_ack, 0, 0);
942 /* threads_list_lock ***********************************************************
944 Enter the threads table mutex.
946 NOTE: We need this function as we can't use an internal lock for
947 the threads lists because the thread's lock is initialized in
948 threads_table_add (when we have the thread index), but we
949 already need the lock at the entry of the function.
951 *******************************************************************************/
953 void threads_list_lock(void)
957 result = pthread_mutex_lock(&mutex_threads_list);
960 vm_abort_errnum(result, "threads_list_lock: pthread_mutex_lock failed");
964 /* threads_list_unlock *********************************************************
966 Leave the threads list mutex.
968 *******************************************************************************/
970 void threads_list_unlock(void)
974 result = pthread_mutex_unlock(&mutex_threads_list);
977 vm_abort_errnum(result, "threads_list_unlock: pthread_mutex_unlock failed");
981 /* threads_mutex_gc_lock *******************************************************
983 Enter the global GC mutex.
985 *******************************************************************************/
987 #if defined(ENABLE_GC_CACAO)
988 void threads_mutex_gc_lock(void)
992 result = pthread_mutex_lock(&mutex_gc);
995 vm_abort_errnum(result, "threads_mutex_gc_lock: pthread_mutex_lock failed");
1000 /* threads_mutex_gc_unlock *****************************************************
1002 Leave the global GC mutex.
1004 *******************************************************************************/
1006 #if defined(ENABLE_GC_CACAO)
1007 void threads_mutex_gc_unlock(void)
1011 result = pthread_mutex_unlock(&mutex_gc);
1014 vm_abort_errnum(result, "threads_mutex_gc_unlock: pthread_mutex_unlock failed");
1018 /* threads_mutex_join_lock *****************************************************
1020 Enter the join mutex.
1022 *******************************************************************************/
1024 void threads_mutex_join_lock(void)
1028 result = pthread_mutex_lock(&mutex_join);
1031 vm_abort_errnum(result, "threads_mutex_join_lock: pthread_mutex_lock failed");
1035 /* threads_mutex_join_unlock ***************************************************
1037 Leave the join mutex.
1039 *******************************************************************************/
1041 void threads_mutex_join_unlock(void)
1045 result = pthread_mutex_unlock(&mutex_join);
1048 vm_abort_errnum(result, "threads_mutex_join_unlock: pthread_mutex_unlock failed");
1052 /* threads_init ****************************************************************
1054 Initializes the threads required by the JVM: main, finalizer.
1056 *******************************************************************************/
1058 bool threads_init(void)
1060 threadobject *mainthread;
1061 java_handle_t *threadname;
1062 java_lang_Thread *t;
1065 #if defined(ENABLE_JAVASE)
1066 java_lang_ThreadGroup *threadgroup;
1070 #if defined(WITH_CLASSPATH_GNU)
1071 java_lang_VMThread *vmt;
1074 pthread_attr_t attr;
1076 TRACESUBSYSTEMINITIALIZATION("threads_init");
1078 /* get methods we need in this file */
1080 #if defined(WITH_CLASSPATH_GNU)
1081 method_thread_init =
1082 class_resolveclassmethod(class_java_lang_Thread,
1084 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
1085 class_java_lang_Thread,
1087 #elif defined(WITH_CLASSPATH_SUN)
1088 method_thread_init =
1089 class_resolveclassmethod(class_java_lang_Thread,
1091 utf_new_char("(Ljava/lang/String;)V"),
1092 class_java_lang_Thread,
1094 #elif defined(WITH_CLASSPATH_CLDC1_1)
1095 method_thread_init =
1096 class_resolveclassmethod(class_java_lang_Thread,
1098 utf_new_char("(Ljava/lang/String;)V"),
1099 class_java_lang_Thread,
1102 # error unknown classpath configuration
1105 if (method_thread_init == NULL)
1108 /* Get the main-thread (NOTE: The main threads is always the first
1109 thread in the list). */
1111 mainthread = threadlist_first();
1113 /* create a java.lang.Thread for the main thread */
1115 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1120 /* set the object in the internal data structure */
1122 threads_thread_set_object(mainthread, (java_handle_t *) t);
1124 #if defined(ENABLE_INTRP)
1125 /* create interpreter stack */
1128 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1129 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
1133 threadname = javastring_new(utf_new_char("main"));
1135 #if defined(ENABLE_JAVASE)
1136 /* allocate and init ThreadGroup */
1138 threadgroup = (java_lang_ThreadGroup *)
1139 native_new_and_init(class_java_lang_ThreadGroup);
1141 if (threadgroup == NULL)
1145 #if defined(WITH_CLASSPATH_GNU)
1146 /* create a java.lang.VMThread for the main thread */
1148 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1153 /* set the thread */
1155 LLNI_field_set_ref(vmt, thread, t);
1156 LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) mainthread);
1158 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
1159 o = (java_handle_t *) t;
1161 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
1164 #elif defined(WITH_CLASSPATH_SUN)
1166 /* We trick java.lang.Thread.<init>, which sets the priority of
1167 the current thread to the parent's one. */
1169 t->priority = NORM_PRIORITY;
1171 /* Call java.lang.Thread.<init>(Ljava/lang/String;)V */
1173 o = (java_object_t *) t;
1175 (void) vm_call_method(method_thread_init, o, threadname);
1177 #elif defined(WITH_CLASSPATH_CLDC1_1)
1179 /* set the thread */
1181 t->vm_thread = (java_lang_Object *) mainthread;
1183 /* call public Thread(String name) */
1185 o = (java_handle_t *) t;
1187 (void) vm_call_method(method_thread_init, o, threadname);
1189 # error unknown classpath configuration
1192 if (exceptions_get_exception())
1195 #if defined(ENABLE_JAVASE)
1196 LLNI_field_set_ref(t, group, threadgroup);
1198 # if defined(WITH_CLASSPATH_GNU)
1199 /* add main thread to java.lang.ThreadGroup */
1201 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
1203 utf_java_lang_Thread__V,
1204 class_java_lang_ThreadGroup,
1207 o = (java_handle_t *) threadgroup;
1209 (void) vm_call_method(m, o, t);
1211 if (exceptions_get_exception())
1214 # warning Do not know what to do here
1218 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
1220 /* initialize the thread attribute object */
1222 if (pthread_attr_init(&attr) != 0)
1223 vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
1225 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
1226 vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
1229 DEBUGTHREADS("starting (main)", mainthread);
1231 /* everything's ok */
1237 /* threads_startup_thread ******************************************************
1239 Thread startup function called by pthread_create.
1241 Thread which have a startup.function != NULL are marked as internal
1242 threads. All other threads are threated as normal Java threads.
1244 NOTE: This function is not called directly by pthread_create. The Boehm GC
1245 inserts its own GC_start_routine in between, which then calls
1249 arg..........the argument passed to pthread_create, ie. a pointer to
1250 a startupinfo struct. CAUTION: When the `psem` semaphore
1251 is posted, the startupinfo struct becomes invalid! (It
1252 is allocated on the stack of threads_start_thread.)
1254 ******************************************************************************/
1256 static void *threads_startup_thread(void *arg)
1258 startupinfo *startup;
1259 threadobject *thread;
1260 java_lang_Thread *object;
1261 #if defined(WITH_CLASSPATH_GNU)
1262 java_lang_VMThread *vmt;
1268 functionptr function;
1270 #if defined(ENABLE_INTRP)
1271 u1 *intrp_thread_stack;
1273 /* create interpreter stack */
1276 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1277 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1280 intrp_thread_stack = NULL;
1283 /* get passed startupinfo structure and the values in there */
1287 thread = startup->thread;
1288 function = startup->function;
1289 psem = startup->psem;
1291 /* Seems like we've encountered a situation where thread->tid was
1292 not set by pthread_create. We alleviate this problem by waiting
1293 for pthread_create to return. */
1295 threads_sem_wait(startup->psem_first);
1297 #if defined(__DARWIN__)
1298 thread->mach_thread = mach_thread_self();
1301 /* store the internal thread data-structure in the TSD */
1303 threads_set_current_threadobject(thread);
1305 /* get the java.lang.Thread object for this thread */
1307 object = (java_lang_Thread *) threads_thread_get_object(thread);
1309 /* set our priority */
1311 threads_set_thread_priority(thread->tid, LLNI_field_direct(object, priority));
1313 /* thread is completely initialized */
1315 threads_thread_state_runnable(thread);
1317 /* tell threads_startup_thread that we registered ourselves */
1318 /* CAUTION: *startup becomes invalid with this! */
1321 threads_sem_post(psem);
1323 #if defined(ENABLE_INTRP)
1324 /* set interpreter stack */
1327 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1330 #if defined(ENABLE_JVMTI)
1331 /* fire thread start event */
1334 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1337 DEBUGTHREADS("starting", thread);
1339 /* find and run the Thread.run()V method if no other function was passed */
1341 if (function == NULL) {
1342 #if defined(WITH_CLASSPATH_GNU)
1343 /* We need to start the run method of
1344 java.lang.VMThread. Since this is a final class, we can use
1345 the class object directly. */
1347 c = class_java_lang_VMThread;
1348 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1349 LLNI_class_get(object, c);
1351 # error unknown classpath configuration
1354 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1357 vm_abort("threads_startup_thread: run() method not found in class");
1359 /* set ThreadMXBean variables */
1361 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1362 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1364 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1365 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1366 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1367 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1369 #if defined(WITH_CLASSPATH_GNU)
1370 /* we need to start the run method of java.lang.VMThread */
1372 LLNI_field_get_ref(object, vmThread, vmt);
1373 o = (java_handle_t *) vmt;
1375 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1376 o = (java_handle_t *) object;
1378 # error unknown classpath configuration
1381 /* run the thread */
1383 (void) vm_call_method(m, o);
1386 /* set ThreadMXBean variables */
1388 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1389 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1391 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1392 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1393 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1394 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1396 /* call passed function, e.g. finalizer_thread */
1401 DEBUGTHREADS("stopping", thread);
1403 #if defined(ENABLE_JVMTI)
1404 /* fire thread end event */
1407 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1410 /* We ignore the return value. */
1412 (void) threads_detach_thread(thread);
1414 /* set ThreadMXBean variables */
1416 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1422 /* threads_impl_thread_start ***************************************************
1424 Start a thread in the JVM. Both (vm internal and java) thread
1428 thread....the thread object
1429 f.........function to run in the new thread. NULL means that the
1430 "run" method of the object `t` should be called
1432 ******************************************************************************/
1434 void threads_impl_thread_start(threadobject *thread, functionptr f)
1438 pthread_attr_t attr;
1439 startupinfo startup;
1442 /* fill startupinfo structure passed by pthread_create to
1443 * threads_startup_thread */
1445 startup.thread = thread;
1446 startup.function = f; /* maybe we don't call Thread.run()V */
1447 startup.psem = &sem;
1448 startup.psem_first = &sem_first;
1450 threads_sem_init(&sem, 0, 0);
1451 threads_sem_init(&sem_first, 0, 0);
1453 /* Initialize thread attributes. */
1455 result = pthread_attr_init(&attr);
1458 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
1460 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1463 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
1465 /* initialize thread stacksize */
1467 result = pthread_attr_setstacksize(&attr, opt_stacksize);
1470 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
1472 /* create the thread */
1474 result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1477 vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
1479 /* destroy the thread attributes */
1481 result = pthread_attr_destroy(&attr);
1484 vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
1486 /* signal that pthread_create has returned, so thread->tid is valid */
1488 threads_sem_post(&sem_first);
1490 /* wait here until the thread has entered itself into the thread list */
1492 threads_sem_wait(&sem);
1497 sem_destroy(&sem_first);
1501 /* threads_set_thread_priority *************************************************
1503 Set the priority of the given thread.
1506 tid..........thread id
1507 priority.....priority to set
1509 ******************************************************************************/
1511 void threads_set_thread_priority(pthread_t tid, int priority)
1513 struct sched_param schedp;
1516 pthread_getschedparam(tid, &policy, &schedp);
1517 schedp.sched_priority = priority;
1518 pthread_setschedparam(tid, policy, &schedp);
1522 /* threads_attach_current_thread ***********************************************
1524 Attaches the current thread to the VM. Used in JNI.
1526 *******************************************************************************/
1528 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1530 threadobject *thread;
1534 java_lang_Thread *t;
1536 #if defined(ENABLE_JAVASE)
1537 java_lang_ThreadGroup *group;
1538 threadobject *mainthread;
1539 java_lang_Thread *mainthreado;
1544 #if defined(WITH_CLASSPATH_GNU)
1545 java_lang_VMThread *vmt;
1548 /* Enter the join-mutex, so if the main-thread is currently
1549 waiting to join all threads, the number of non-daemon threads
1552 threads_mutex_join_lock();
1554 /* create internal thread data-structure */
1556 thread = threads_thread_new();
1558 /* thread is a Java thread and running */
1560 thread->flags = THREAD_FLAG_JAVA;
1563 thread->flags |= THREAD_FLAG_DAEMON;
1565 /* The thread is flagged and (non-)daemon thread, we can leave the
1568 threads_mutex_join_unlock();
1570 /* create a java.lang.Thread object */
1572 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1574 /* XXX memory leak!!! */
1578 threads_thread_set_object(thread, (java_handle_t *) t);
1580 /* thread is completely initialized */
1582 threads_thread_state_runnable(thread);
1584 DEBUGTHREADS("attaching", thread);
1586 #if defined(ENABLE_INTRP)
1587 /* create interpreter stack */
1590 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1591 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1595 #if defined(WITH_CLASSPATH_GNU)
1597 /* create a java.lang.VMThread object */
1599 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1601 /* XXX memory leak!!! */
1605 /* set the thread */
1607 LLNI_field_set_ref(vmt, thread, t);
1608 LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
1610 #elif defined(WITH_CLASSPATH_SUN)
1612 vm_abort("threads_attach_current_thread: IMPLEMENT ME!");
1614 #elif defined(WITH_CLASSPATH_CLDC1_1)
1616 LLNI_field_set_val(t, vm_thread, (java_lang_Object *) thread);
1619 # error unknown classpath configuration
1622 if (vm_aargs != NULL) {
1623 u = utf_new_char(vm_aargs->name);
1624 #if defined(ENABLE_JAVASE)
1625 group = (java_lang_ThreadGroup *) vm_aargs->group;
1630 #if defined(ENABLE_JAVASE)
1631 /* get the main thread */
1633 mainthread = threadlist_first();
1634 mainthreado = (java_lang_Thread *) threads_thread_get_object(mainthread);
1635 LLNI_field_get_ref(mainthreado, group, group);
1639 /* the the thread name */
1641 s = javastring_new(u);
1643 /* for convenience */
1645 o = (java_handle_t *) t;
1647 #if defined(WITH_CLASSPATH_GNU)
1648 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1650 #elif defined(WITH_CLASSPATH_CLDC1_1)
1651 (void) vm_call_method(method_thread_init, o, s);
1654 if (exceptions_get_exception())
1657 #if defined(ENABLE_JAVASE)
1658 /* store the thread group in the object */
1660 LLNI_field_set_ref(t, group, group);
1662 /* add thread to given thread-group */
1664 LLNI_class_get(group, c);
1666 m = class_resolveclassmethod(c,
1668 utf_java_lang_Thread__V,
1669 class_java_lang_ThreadGroup,
1672 o = (java_handle_t *) group;
1674 (void) vm_call_method(m, o, t);
1676 if (exceptions_get_exception())
1684 /* threads_detach_thread *******************************************************
1686 Detaches the passed thread from the VM. Used in JNI.
1688 *******************************************************************************/
1690 bool threads_detach_thread(threadobject *t)
1692 java_lang_Thread *object;
1694 #if defined(ENABLE_JAVASE)
1695 java_lang_ThreadGroup *group;
1697 java_lang_Object *handler;
1702 DEBUGTHREADS("detaching", t);
1704 object = (java_lang_Thread *) threads_thread_get_object(t);
1706 #if defined(ENABLE_JAVASE)
1707 LLNI_field_get_ref(object, group, group);
1709 /* If there's an uncaught exception, call uncaughtException on the
1710 thread's exception handler, or the thread's group if this is
1713 e = exceptions_get_and_clear_exception();
1716 /* We use a java_lang_Object here, as it's not trivial to
1717 build the java_lang_Thread_UncaughtExceptionHandler header
1720 # if defined(WITH_CLASSPATH_GNU)
1721 LLNI_field_get_ref(object, exceptionHandler, handler);
1722 # elif defined(WITH_CLASSPATH_SUN)
1723 LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
1726 if (handler != NULL) {
1727 LLNI_class_get(handler, c);
1728 o = (java_handle_t *) handler;
1731 LLNI_class_get(group, c);
1732 o = (java_handle_t *) group;
1735 m = class_resolveclassmethod(c,
1736 utf_uncaughtException,
1737 utf_java_lang_Thread_java_lang_Throwable__V,
1744 (void) vm_call_method(m, o, object, e);
1746 if (exceptions_get_exception())
1750 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1752 /* Remove thread from the thread group. */
1754 if (group != NULL) {
1755 LLNI_class_get(group, c);
1757 # if defined(WITH_CLASSPATH_GNU)
1758 m = class_resolveclassmethod(c,
1760 utf_java_lang_Thread__V,
1761 class_java_lang_ThreadGroup,
1763 # elif defined(WITH_CLASSPATH_SUN)
1764 m = class_resolveclassmethod(c,
1766 utf_java_lang_Thread__V,
1767 class_java_lang_ThreadGroup,
1770 # error unknown classpath configuration
1776 o = (java_handle_t *) group;
1778 (void) vm_call_method(m, o, object);
1780 if (exceptions_get_exception())
1785 /* Thread has terminated. */
1787 threads_thread_state_terminated(t);
1789 /* Notify all threads waiting on this thread. These are joining
1792 o = (java_handle_t *) object;
1794 /* XXX Care about exceptions? */
1795 (void) lock_monitor_enter(o);
1797 lock_notify_all_object(o);
1799 /* XXX Care about exceptions? */
1800 (void) lock_monitor_exit(o);
1802 /* Enter the join-mutex before calling threads_thread_free, so
1803 threads_join_all_threads gets the correct number of non-daemon
1806 threads_mutex_join_lock();
1808 /* free the vm internal thread object */
1810 threads_thread_free(t);
1812 /* Signal that this thread has finished and leave the mutex. */
1814 pthread_cond_signal(&cond_join);
1815 threads_mutex_join_unlock();
1821 /* threads_suspend_thread ******************************************************
1823 Suspend the passed thread. Execution stops until the thread
1824 is explicitly resumend again.
1827 reason.....Reason for suspending this thread.
1829 *******************************************************************************/
1831 bool threads_suspend_thread(threadobject *thread, s4 reason)
1833 /* acquire the suspendmutex */
1834 if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
1835 vm_abort("threads_suspend_thread: pthread_mutex_lock failed: %s",
1838 if (thread->suspended) {
1839 pthread_mutex_unlock(&(thread->suspendmutex));
1843 /* set the reason for the suspension */
1844 thread->suspend_reason = reason;
1846 /* send the suspend signal to the thread */
1847 assert(thread != THREADOBJECT);
1848 if (pthread_kill(thread->tid, SIGUSR1) != 0)
1849 vm_abort("threads_suspend_thread: pthread_kill failed: %s",
1852 /* REMEMBER: do not release the suspendmutex, this is done
1853 by the thread itself in threads_suspend_ack(). */
1859 /* threads_suspend_ack *********************************************************
1861 Acknowledges the suspension of the current thread.
1864 pc.....The PC where the thread suspended its execution.
1865 sp.....The SP before the thread suspended its execution.
1867 *******************************************************************************/
1869 void threads_suspend_ack(u1* pc, u1* sp)
1871 threadobject *thread;
1873 thread = THREADOBJECT;
1875 assert(thread->suspend_reason != 0);
1877 /* TODO: remember dump memory size */
1879 #if defined(ENABLE_GC_CACAO)
1880 /* inform the GC about the suspension */
1881 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
1883 /* check if the GC wants to leave the thread running */
1884 if (!gc_suspend(thread, pc, sp)) {
1886 /* REMEMBER: we do not unlock the suspendmutex because the thread
1887 will suspend itself again at a later time */
1894 /* mark this thread as suspended and remember the PC */
1896 thread->suspended = true;
1898 /* if we are stopping the world, we should send a global ack */
1899 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1900 threads_sem_post(&suspend_ack);
1903 DEBUGTHREADS("suspending", thread);
1905 /* release the suspension mutex and wait till we are resumed */
1906 pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
1908 DEBUGTHREADS("resuming", thread);
1910 /* if we are stopping the world, we should send a global ack */
1911 if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
1912 threads_sem_post(&suspend_ack);
1915 /* TODO: free dump memory */
1917 /* release the suspendmutex */
1918 if (pthread_mutex_unlock(&(thread->suspendmutex)) != 0)
1919 vm_abort("threads_suspend_ack: pthread_mutex_unlock failed: %s",
1924 /* threads_resume_thread *******************************************************
1926 Resumes the execution of the passed thread.
1928 *******************************************************************************/
1930 bool threads_resume_thread(threadobject *thread)
1932 /* acquire the suspendmutex */
1933 if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
1934 vm_abort("threads_resume_ack: pthread_mutex_unlock failed: %s",
1937 if (!thread->suspended) {
1938 pthread_mutex_unlock(&(thread->suspendmutex));
1942 thread->suspended = false;
1944 /* tell everyone that the thread should resume */
1945 assert(thread != THREADOBJECT);
1946 pthread_cond_broadcast(&(thread->suspendcond));
1948 /* release the suspendmutex */
1949 pthread_mutex_unlock(&(thread->suspendmutex));
1955 /* threads_join_all_threads ****************************************************
1957 Join all non-daemon threads.
1959 *******************************************************************************/
1961 void threads_join_all_threads(void)
1965 /* get current thread */
1969 /* this thread is waiting for all non-daemon threads to exit */
1971 threads_thread_state_waiting(t);
1973 /* enter join mutex */
1975 threads_mutex_join_lock();
1977 /* Wait for condition as long as we have non-daemon threads. We
1978 compare against 1 because the current (main thread) is also a
1979 non-daemon thread. */
1981 while (threadlist_get_non_daemons() > 1)
1982 pthread_cond_wait(&cond_join, &mutex_join);
1984 /* leave join mutex */
1986 threads_mutex_join_unlock();
1990 /* threads_timespec_earlier ****************************************************
1992 Return true if timespec tv1 is earlier than timespec tv2.
1995 tv1..........first timespec
1996 tv2..........second timespec
1999 true, if the first timespec is earlier
2001 *******************************************************************************/
2003 static inline bool threads_timespec_earlier(const struct timespec *tv1,
2004 const struct timespec *tv2)
2006 return (tv1->tv_sec < tv2->tv_sec)
2008 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
2012 /* threads_current_time_is_earlier_than ****************************************
2014 Check if the current time is earlier than the given timespec.
2017 tv...........the timespec to compare against
2020 true, if the current time is earlier
2022 *******************************************************************************/
2024 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
2026 struct timeval tvnow;
2027 struct timespec tsnow;
2029 /* get current time */
2031 if (gettimeofday(&tvnow, NULL) != 0)
2032 vm_abort("gettimeofday failed: %s\n", strerror(errno));
2034 /* convert it to a timespec */
2036 tsnow.tv_sec = tvnow.tv_sec;
2037 tsnow.tv_nsec = tvnow.tv_usec * 1000;
2039 /* compare current time with the given timespec */
2041 return threads_timespec_earlier(&tsnow, tv);
2045 /* threads_wait_with_timeout ***************************************************
2047 Wait until the given point in time on a monitor until either
2048 we are notified, we are interrupted, or the time is up.
2051 t............the current thread
2052 wakeupTime...absolute (latest) wakeup time
2053 If both tv_sec and tv_nsec are zero, this function
2054 waits for an unlimited amount of time.
2056 *******************************************************************************/
2058 static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
2060 /* acquire the waitmutex */
2062 pthread_mutex_lock(&t->waitmutex);
2064 /* mark us as sleeping */
2068 /* wait on waitcond */
2070 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
2072 while (!t->interrupted && !t->signaled
2073 && threads_current_time_is_earlier_than(wakeupTime))
2075 threads_thread_state_timed_waiting(t);
2077 pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
2080 threads_thread_state_runnable(t);
2085 while (!t->interrupted && !t->signaled) {
2086 threads_thread_state_waiting(t);
2088 pthread_cond_wait(&t->waitcond, &t->waitmutex);
2090 threads_thread_state_runnable(t);
2094 t->sleeping = false;
2096 /* release the waitmutex */
2098 pthread_mutex_unlock(&t->waitmutex);
2102 /* threads_wait_with_timeout_relative ******************************************
2104 Wait for the given maximum amount of time on a monitor until either
2105 we are notified, we are interrupted, or the time is up.
2108 t............the current thread
2109 millis.......milliseconds to wait
2110 nanos........nanoseconds to wait
2112 *******************************************************************************/
2114 void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
2117 struct timespec wakeupTime;
2119 /* calculate the the (latest) wakeup time */
2121 threads_calc_absolute_time(&wakeupTime, millis, nanos);
2125 threads_wait_with_timeout(thread, &wakeupTime);
2129 /* threads_calc_absolute_time **************************************************
2131 Calculate the absolute point in time a given number of ms and ns from now.
2134 millis............milliseconds from now
2135 nanos.............nanoseconds from now
2138 *tm...............receives the timespec of the absolute point in time
2140 *******************************************************************************/
2142 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
2144 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
2147 gettimeofday(&tv, NULL);
2148 tv.tv_sec += millis / 1000;
2150 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
2151 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
2152 tm->tv_nsec = nsec % 1000000000;
2161 /* threads_thread_interrupt ****************************************************
2163 Interrupt the given thread.
2165 The thread gets the "waitcond" signal and
2166 its interrupted flag is set to true.
2169 thread............the thread to interrupt
2171 *******************************************************************************/
2173 void threads_thread_interrupt(threadobject *thread)
2175 /* Signal the thread a "waitcond" and tell it that it has been
2178 pthread_mutex_lock(&thread->waitmutex);
2180 DEBUGTHREADS("interrupted", thread);
2182 /* Interrupt blocking system call using a signal. */
2184 pthread_kill(thread->tid, SIGHUP);
2186 if (thread->sleeping)
2187 pthread_cond_signal(&thread->waitcond);
2189 thread->interrupted = true;
2191 pthread_mutex_unlock(&thread->waitmutex);
2195 /* threads_check_if_interrupted_and_reset **************************************
2197 Check if the current thread has been interrupted and reset the
2201 true, if the current thread had been interrupted
2203 *******************************************************************************/
2205 bool threads_check_if_interrupted_and_reset(void)
2207 threadobject *thread;
2210 thread = THREADOBJECT;
2212 pthread_mutex_lock(&thread->waitmutex);
2214 /* get interrupted flag */
2216 intr = thread->interrupted;
2218 /* reset interrupted flag */
2220 thread->interrupted = false;
2222 pthread_mutex_unlock(&thread->waitmutex);
2228 /* threads_thread_has_been_interrupted *****************************************
2230 Check if the given thread has been interrupted
2233 t............the thread to check
2236 true, if the given thread had been interrupted
2238 *******************************************************************************/
2240 bool threads_thread_has_been_interrupted(threadobject *thread)
2242 return thread->interrupted;
2246 /* threads_sleep ***************************************************************
2248 Sleep the current thread for the specified amount of time.
2250 *******************************************************************************/
2252 void threads_sleep(s8 millis, s4 nanos)
2254 threadobject *thread;
2255 struct timespec wakeupTime;
2256 bool wasinterrupted;
2258 thread = THREADOBJECT;
2260 threads_calc_absolute_time(&wakeupTime, millis, nanos);
2262 threads_wait_with_timeout(thread, &wakeupTime);
2264 wasinterrupted = threads_check_if_interrupted_and_reset();
2267 exceptions_throw_interruptedexception();
2271 /* threads_yield ***************************************************************
2273 Yield to the scheduler.
2275 *******************************************************************************/
2277 void threads_yield(void)
2284 * These are local overrides for various environment variables in Emacs.
2285 * Please do not remove this and leave it at the end of the file, where
2286 * Emacs will automagically detect them.
2287 * ---------------------------------------------------------------------
2290 * indent-tabs-mode: t
2294 * vim:noexpandtab:sw=4:ts=4: