1 /* src/threads/native/threads.c - native threads support
3 Copyright (C) 1996-2005, 2006, 2007 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 $Id: threads.c 7875 2007-05-07 11:35:30Z twisti $
32 /* XXX cleanup these includes */
37 #include <sys/types.h>
50 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
51 # include "machine-instr.h"
53 # include "threads/native/generic-primitives.h"
56 #include "mm/gc-common.h"
57 #include "mm/memory.h"
59 #include "native/jni.h"
60 #include "native/native.h"
61 #include "native/include/java_lang_Object.h"
62 #include "native/include/java_lang_String.h"
63 #include "native/include/java_lang_Throwable.h"
64 #include "native/include/java_lang_Thread.h"
66 #if defined(ENABLE_JAVASE)
67 # include "native/include/java_lang_ThreadGroup.h"
70 #if defined(WITH_CLASSPATH_GNU)
71 # include "native/include/java_lang_VMThread.h"
74 #include "threads/lock-common.h"
75 #include "threads/threads-common.h"
77 #include "threads/native/threads.h"
79 #include "toolbox/avl.h"
80 #include "toolbox/logging.h"
82 #include "vm/builtin.h"
83 #include "vm/exceptions.h"
84 #include "vm/global.h"
85 #include "vm/stringlocal.h"
88 #include "vm/jit/asmpart.h"
90 #include "vmcore/options.h"
92 #if defined(ENABLE_STATISTICS)
93 # include "vmcore/statistics.h"
96 #if !defined(__DARWIN__)
97 # if defined(__LINUX__)
98 # define GC_LINUX_THREADS
99 # elif defined(__MIPS__)
100 # define GC_IRIX_THREADS
102 # include <semaphore.h>
103 # if defined(ENABLE_GC_BOEHM)
104 # include "mm/boehm-gc/include/gc.h"
108 #if defined(ENABLE_JVMTI)
109 #include "native/jvmti/cacaodbg.h"
112 #if defined(__DARWIN__)
113 /* Darwin has no working semaphore implementation. This one is taken
117 This is a very simple semaphore implementation for darwin. It
118 is implemented in terms of pthreads calls so it isn't async signal
119 safe. This isn't a problem because signals aren't used to
120 suspend threads on darwin.
123 static int sem_init(sem_t *sem, int pshared, int value)
130 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
133 if (pthread_cond_init(&sem->cond, NULL) < 0)
139 static int sem_post(sem_t *sem)
141 if (pthread_mutex_lock(&sem->mutex) < 0)
146 if (pthread_cond_signal(&sem->cond) < 0) {
147 pthread_mutex_unlock(&sem->mutex);
151 if (pthread_mutex_unlock(&sem->mutex) < 0)
157 static int sem_wait(sem_t *sem)
159 if (pthread_mutex_lock(&sem->mutex) < 0)
162 while (sem->value == 0) {
163 pthread_cond_wait(&sem->cond, &sem->mutex);
168 if (pthread_mutex_unlock(&sem->mutex) < 0)
174 static int sem_destroy(sem_t *sem)
176 if (pthread_cond_destroy(&sem->cond) < 0)
179 if (pthread_mutex_destroy(&sem->mutex) < 0)
184 #endif /* defined(__DARWIN__) */
187 /* internally used constants **************************************************/
189 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
190 #define STOPWORLD_FROM_GC 1
191 #define STOPWORLD_FROM_CLASS_NUMBERING 2
194 /* startupinfo *****************************************************************
196 Struct used to pass info from threads_start_thread to
197 threads_startup_thread.
199 ******************************************************************************/
202 threadobject *thread; /* threadobject for this thread */
203 functionptr function; /* function to run in the new thread */
204 sem_t *psem; /* signals when thread has been entered */
205 /* in the thread list */
206 sem_t *psem_first; /* signals when pthread_create has returned */
210 /* prototypes *****************************************************************/
212 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
215 /******************************************************************************/
216 /* GLOBAL VARIABLES */
217 /******************************************************************************/
219 /* the main thread */
220 threadobject *mainthreadobj;
222 static methodinfo *method_thread_init;
224 /* the thread object of the current thread */
225 /* This is either a thread-local variable defined with __thread, or */
226 /* a thread-specific value stored with key threads_current_threadobject_key. */
227 #if defined(HAVE___THREAD)
228 __thread threadobject *threads_current_threadobject;
230 pthread_key_t threads_current_threadobject_key;
233 /* global mutex for the threads table */
234 static pthread_mutex_t mutex_threads_table;
236 /* global mutex for stop-the-world */
237 static pthread_mutex_t stopworldlock;
239 /* global mutex and condition for joining threads on exit */
240 static pthread_mutex_t mutex_join;
241 static pthread_cond_t cond_join;
243 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
245 static volatile int stopworldwhere;
247 /* semaphore used for acknowleding thread suspension */
248 static sem_t suspend_ack;
249 #if defined(__MIPS__)
250 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
251 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
254 static pthread_attr_t threadattr;
256 /* mutexes used by the fake atomic instructions */
257 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
258 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
259 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
260 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
264 /* threads_sem_init ************************************************************
266 Initialize a semaphore. Checks against errors and interruptions.
269 sem..............the semaphore to initialize
270 shared...........true if this semaphore will be shared between processes
271 value............the initial value for the semaphore
273 *******************************************************************************/
275 void threads_sem_init(sem_t *sem, bool shared, int value)
282 r = sem_init(sem, shared, value);
285 } while (errno == EINTR);
287 vm_abort("sem_init failed: %s", strerror(errno));
291 /* threads_sem_wait ************************************************************
293 Wait for a semaphore, non-interruptible.
295 IMPORTANT: Always use this function instead of `sem_wait` directly, as
296 `sem_wait` may be interrupted by signals!
299 sem..............the semaphore to wait on
301 *******************************************************************************/
303 void threads_sem_wait(sem_t *sem)
313 } while (errno == EINTR);
315 vm_abort("sem_wait failed: %s", strerror(errno));
319 /* threads_sem_post ************************************************************
321 Increase the count of a semaphore. Checks for errors.
324 sem..............the semaphore to increase the count of
326 *******************************************************************************/
328 void threads_sem_post(sem_t *sem)
334 /* unlike sem_wait, sem_post is not interruptible */
340 vm_abort("sem_post failed: %s", strerror(errno));
344 /* lock_stopworld **************************************************************
346 Enter the stopworld lock, specifying why the world shall be stopped.
349 where........ STOPWORLD_FROM_GC (1) from within GC
350 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
352 ******************************************************************************/
354 void lock_stopworld(int where)
356 pthread_mutex_lock(&stopworldlock);
357 stopworldwhere = where;
361 /* unlock_stopworld ************************************************************
363 Release the stopworld lock.
365 ******************************************************************************/
367 void unlock_stopworld(void)
370 pthread_mutex_unlock(&stopworldlock);
373 #if !defined(__DARWIN__)
374 /* Caller must hold threadlistlock */
375 static void threads_cast_sendsignals(int sig)
382 /* iterate over all started threads */
384 for (t = threads_table_first(); t != NULL; t = threads_table_next(t)) {
385 /* don't send the signal to ourself */
388 pthread_kill(t->tid, sig);
394 static void threads_cast_darwinstop(void)
396 threadobject *tobj = mainthreadobj;
397 threadobject *self = THREADOBJECT;
402 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
403 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
404 #if defined(__I386__)
405 i386_thread_state_t thread_state;
407 ppc_thread_state_t thread_state;
409 mach_port_t thread = tobj->mach_thread;
412 r = thread_suspend(thread);
414 if (r != KERN_SUCCESS)
415 vm_abort("thread_suspend failed");
417 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
418 &thread_state_count);
420 if (r != KERN_SUCCESS)
421 vm_abort("thread_get_state failed");
423 md_critical_section_restart((ucontext_t *) &thread_state);
425 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
428 if (r != KERN_SUCCESS)
429 vm_abort("thread_set_state failed");
433 } while (tobj != mainthreadobj);
436 static void threads_cast_darwinresume(void)
438 threadobject *tobj = mainthreadobj;
439 threadobject *self = THREADOBJECT;
444 mach_port_t thread = tobj->mach_thread;
447 r = thread_resume(thread);
449 if (r != KERN_SUCCESS)
450 vm_abort("thread_resume failed");
454 } while (tobj != mainthreadobj);
459 #if defined(__MIPS__)
460 static void threads_cast_irixresume(void)
462 pthread_mutex_lock(&suspend_ack_lock);
463 pthread_cond_broadcast(&suspend_cond);
464 pthread_mutex_unlock(&suspend_ack_lock);
468 #if !defined(DISABLE_GC)
470 void threads_cast_stopworld(void)
472 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
476 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
478 /* lock the threads table */
480 threads_table_lock();
482 #if defined(__DARWIN__)
483 threads_cast_darwinstop();
484 #elif defined(__CYGWIN__)
488 /* send all threads the suspend signal */
490 threads_cast_sendsignals(GC_signum1());
492 /* wait for all threads to suspend (except the current one) */
494 count = threads_table_get_threads() - 1;
496 for (i = 0; i < count; i++)
497 threads_sem_wait(&suspend_ack);
500 /* unlock the threads table */
502 threads_table_unlock();
505 void threads_cast_startworld(void)
507 /* lock the threads table */
509 threads_table_lock();
511 #if defined(__DARWIN__)
512 threads_cast_darwinresume();
513 #elif defined(__MIPS__)
514 threads_cast_irixresume();
515 #elif defined(__CYGWIN__)
519 threads_cast_sendsignals(GC_signum2());
522 /* unlock the threads table */
524 threads_table_unlock();
530 #if !defined(__DARWIN__)
531 static void threads_sigsuspend_handler(ucontext_t *_uc)
536 /* XXX TWISTI: this is just a quick hack */
537 #if defined(ENABLE_JIT)
538 md_critical_section_restart(_uc);
541 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
542 (not POSIX async-safe). */
543 #if defined(__IRIX__)
544 pthread_mutex_lock(&suspend_ack_lock);
545 threads_sem_post(&suspend_ack);
546 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
547 pthread_mutex_unlock(&suspend_ack_lock);
548 #elif defined(__CYGWIN__)
552 threads_sem_post(&suspend_ack);
556 sigdelset(&sigs, sig);
561 /* This function is called from Boehm GC code. */
563 int cacao_suspendhandler(ucontext_t *_uc)
565 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
568 threads_sigsuspend_handler(_uc);
573 #endif /* DISABLE_GC */
576 /* threads_set_current_threadobject ********************************************
578 Set the current thread object.
581 thread.......the thread object to set
583 *******************************************************************************/
585 void threads_set_current_threadobject(threadobject *thread)
587 #if !defined(HAVE___THREAD)
588 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
589 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
591 threads_current_threadobject = thread;
596 /* threads_init_threadobject **************************************************
598 Initialize implementation fields of a threadobject.
601 thread............the threadobject
603 ******************************************************************************/
605 void threads_init_threadobject(threadobject *thread)
607 /* get the pthread id */
609 thread->tid = pthread_self();
613 /* TODO destroy all those things */
615 pthread_mutex_init(&(thread->waitmutex), NULL);
616 pthread_cond_init(&(thread->waitcond), NULL);
618 thread->interrupted = false;
619 thread->signaled = false;
620 thread->sleeping = false;
624 /* threads_get_current_threadobject ********************************************
626 Return the threadobject of the current thread.
629 the current threadobject * (an instance of java.lang.Thread)
631 *******************************************************************************/
633 threadobject *threads_get_current_threadobject(void)
639 /* threads_impl_preinit ********************************************************
641 Do some early initialization of stuff required.
643 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
644 is called AFTER this function!
646 *******************************************************************************/
648 void threads_impl_preinit(void)
650 pthread_mutex_init(&stopworldlock, NULL);
652 /* initialize exit mutex and condition (on exit we join all
655 pthread_mutex_init(&mutex_join, NULL);
656 pthread_cond_init(&cond_join, NULL);
658 #if !defined(HAVE___THREAD)
659 pthread_key_create(&threads_current_threadobject_key, NULL);
662 threads_sem_init(&suspend_ack, 0, 0);
666 /* threads_table_lock **********************************************************
668 Initialize threads table mutex.
670 *******************************************************************************/
672 void threads_impl_table_init(void)
674 pthread_mutex_init(&mutex_threads_table, NULL);
678 /* threads_table_lock **********************************************************
680 Enter the threads table mutex.
682 NOTE: We need this function as we can't use an internal lock for
683 the threads table because the thread's lock is initialized in
684 threads_table_add (when we have the thread index), but we
685 already need the lock at the entry of the function.
687 *******************************************************************************/
689 void threads_table_lock(void)
691 if (pthread_mutex_lock(&mutex_threads_table) != 0)
692 vm_abort("threads_table_lock: pthread_mutex_lock failed: %s",
697 /* threads_table_unlock ********************************************************
699 Leave the threads table mutex.
701 *******************************************************************************/
703 void threads_table_unlock(void)
705 if (pthread_mutex_unlock(&mutex_threads_table) != 0)
706 vm_abort("threads_table_unlock: pthread_mutex_unlock failed: %s",
711 /* threads_init ****************************************************************
713 Initializes the threads required by the JVM: main, finalizer.
715 *******************************************************************************/
717 bool threads_init(void)
719 threadobject *mainthread;
720 java_objectheader *threadname;
722 java_objectheader *o;
724 #if defined(ENABLE_JAVASE)
725 java_lang_ThreadGroup *threadgroup;
729 #if defined(WITH_CLASSPATH_GNU)
730 java_lang_VMThread *vmt;
733 /* get methods we need in this file */
735 #if defined(WITH_CLASSPATH_GNU)
737 class_resolveclassmethod(class_java_lang_Thread,
739 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
740 class_java_lang_Thread,
744 class_resolveclassmethod(class_java_lang_Thread,
746 utf_new_char("(Ljava/lang/String;)V"),
747 class_java_lang_Thread,
751 if (method_thread_init == NULL)
754 /* Get the main-thread (NOTE: The main threads is always the first
755 thread in the table). */
757 mainthread = threads_table_first();
759 /* create a java.lang.Thread for the main thread */
761 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
766 /* set the object in the internal data structure */
768 mainthread->object = t;
770 #if defined(ENABLE_INTRP)
771 /* create interpreter stack */
774 MSET(intrp_main_stack, 0, u1, opt_stacksize);
775 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
779 threadname = javastring_new(utf_new_char("main"));
781 #if defined(ENABLE_JAVASE)
782 /* allocate and init ThreadGroup */
784 threadgroup = (java_lang_ThreadGroup *)
785 native_new_and_init(class_java_lang_ThreadGroup);
787 if (threadgroup == NULL)
791 #if defined(WITH_CLASSPATH_GNU)
792 /* create a java.lang.VMThread for the main thread */
794 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
802 vmt->vmdata = (java_lang_Object *) mainthread;
804 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
805 o = (java_objectheader *) t;
807 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
809 #elif defined(WITH_CLASSPATH_CLDC1_1)
812 t->vm_thread = (java_lang_Object *) mainthread;
814 /* call public Thread(String name) */
816 o = (java_objectheader *) t;
818 (void) vm_call_method(method_thread_init, o, threadname);
824 #if defined(ENABLE_JAVASE)
825 t->group = threadgroup;
827 /* add main thread to java.lang.ThreadGroup */
829 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
831 utf_java_lang_Thread__V,
832 class_java_lang_ThreadGroup,
835 o = (java_objectheader *) threadgroup;
837 (void) vm_call_method(m, o, t);
843 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
845 /* initialize the thread attribute object */
847 if (pthread_attr_init(&threadattr)) {
848 log_println("pthread_attr_init failed: %s", strerror(errno));
852 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
854 /* everything's ok */
860 /* threads_startup_thread ******************************************************
862 Thread startup function called by pthread_create.
864 Thread which have a startup.function != NULL are marked as internal
865 threads. All other threads are threated as normal Java threads.
867 NOTE: This function is not called directly by pthread_create. The Boehm GC
868 inserts its own GC_start_routine in between, which then calls
872 t............the argument passed to pthread_create, ie. a pointer to
873 a startupinfo struct. CAUTION: When the `psem` semaphore
874 is posted, the startupinfo struct becomes invalid! (It
875 is allocated on the stack of threads_start_thread.)
877 ******************************************************************************/
879 static void *threads_startup_thread(void *t)
881 startupinfo *startup;
882 threadobject *thread;
883 #if defined(WITH_CLASSPATH_GNU)
884 java_lang_VMThread *vmt;
889 java_objectheader *o;
890 functionptr function;
892 #if defined(ENABLE_INTRP)
893 u1 *intrp_thread_stack;
895 /* create interpreter stack */
898 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
899 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
902 intrp_thread_stack = NULL;
905 /* get passed startupinfo structure and the values in there */
908 t = NULL; /* make sure it's not used wrongly */
910 thread = startup->thread;
911 function = startup->function;
912 psem = startup->psem;
914 /* Seems like we've encountered a situation where thread->tid was not set by
915 * pthread_create. We alleviate this problem by waiting for pthread_create
917 threads_sem_wait(startup->psem_first);
919 #if defined(__DARWIN__)
920 thread->mach_thread = mach_thread_self();
923 /* store the internal thread data-structure in the TSD */
925 threads_set_current_threadobject(thread);
927 /* thread is running */
929 thread->state = THREAD_STATE_RUNNABLE;
931 /* insert the thread into the threads table */
933 threads_table_add(thread);
935 /* tell threads_startup_thread that we registered ourselves */
936 /* CAUTION: *startup becomes invalid with this! */
939 threads_sem_post(psem);
941 /* set our priority */
943 threads_set_thread_priority(thread->tid, thread->object->priority);
945 #if defined(ENABLE_INTRP)
946 /* set interpreter stack */
949 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
952 #if defined(ENABLE_JVMTI)
953 /* fire thread start event */
956 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
959 /* find and run the Thread.run()V method if no other function was passed */
961 if (function == NULL) {
962 /* this is a normal Java thread */
964 thread->flags |= THREAD_FLAG_JAVA;
966 #if defined(WITH_CLASSPATH_GNU)
967 /* We need to start the run method of
968 java.lang.VMThread. Since this is a final class, we can use
969 the class object directly. */
971 c = class_java_lang_VMThread;
972 #elif defined(WITH_CLASSPATH_CLDC1_1)
973 c = thread->object->header.vftbl->class;
976 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
979 vm_abort("threads_startup_thread: run() method not found in class");
981 /* set ThreadMXBean variables */
983 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
984 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
986 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
987 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
988 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
989 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
991 #if defined(WITH_CLASSPATH_GNU)
992 /* we need to start the run method of java.lang.VMThread */
994 vmt = (java_lang_VMThread *) thread->object->vmThread;
995 o = (java_objectheader *) vmt;
997 #elif defined(WITH_CLASSPATH_CLDC1_1)
998 o = (java_objectheader *) thread->object;
1001 /* run the thread */
1003 (void) vm_call_method(m, o);
1006 /* this is an internal thread */
1008 thread->flags |= THREAD_FLAG_INTERNAL;
1010 /* set ThreadMXBean variables */
1012 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1013 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1015 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1016 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1017 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1018 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1020 /* call passed function, e.g. finalizer_thread */
1025 #if defined(ENABLE_JVMTI)
1026 /* fire thread end event */
1029 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1032 if (!threads_detach_thread(thread))
1033 vm_abort("threads_startup_thread: threads_detach_thread failed");
1035 /* set ThreadMXBean variables */
1037 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1043 /* threads_impl_thread_start ***************************************************
1045 Start a thread in the JVM. Both (vm internal and java) thread
1049 thread....the thread object
1050 f.........function to run in the new thread. NULL means that the
1051 "run" method of the object `t` should be called
1053 ******************************************************************************/
1055 void threads_impl_thread_start(threadobject *thread, functionptr f)
1059 pthread_attr_t attr;
1060 startupinfo startup;
1062 /* fill startupinfo structure passed by pthread_create to
1063 * threads_startup_thread */
1065 startup.thread = thread;
1066 startup.function = f; /* maybe we don't call Thread.run()V */
1067 startup.psem = &sem;
1068 startup.psem_first = &sem_first;
1070 threads_sem_init(&sem, 0, 0);
1071 threads_sem_init(&sem_first, 0, 0);
1073 /* initialize thread attribute object */
1075 if (pthread_attr_init(&attr))
1076 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1078 /* initialize thread stacksize */
1080 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1081 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1083 /* create the thread */
1085 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1086 vm_abort("pthread_create failed: %s", strerror(errno));
1088 /* signal that pthread_create has returned, so thread->tid is valid */
1090 threads_sem_post(&sem_first);
1092 /* wait here until the thread has entered itself into the thread list */
1094 threads_sem_wait(&sem);
1099 sem_destroy(&sem_first);
1103 /* threads_set_thread_priority *************************************************
1105 Set the priority of the given thread.
1108 tid..........thread id
1109 priority.....priority to set
1111 ******************************************************************************/
1113 void threads_set_thread_priority(pthread_t tid, int priority)
1115 struct sched_param schedp;
1118 pthread_getschedparam(tid, &policy, &schedp);
1119 schedp.sched_priority = priority;
1120 pthread_setschedparam(tid, policy, &schedp);
1124 /* threads_attach_current_thread ***********************************************
1126 Attaches the current thread to the VM. Used in JNI.
1128 *******************************************************************************/
1130 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1132 threadobject *thread;
1134 java_objectheader *s;
1135 java_objectheader *o;
1136 java_lang_Thread *t;
1138 #if defined(ENABLE_JAVASE)
1139 java_lang_ThreadGroup *group;
1140 threadobject *mainthread;
1144 #if defined(WITH_CLASSPATH_GNU)
1145 java_lang_VMThread *vmt;
1148 /* create internal thread data-structure */
1150 thread = threads_create_thread();
1152 /* create a java.lang.Thread object */
1154 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1161 /* thread is a Java thread and running */
1163 thread->flags = THREAD_FLAG_JAVA;
1166 thread->flags |= THREAD_FLAG_DAEMON;
1168 thread->state = THREAD_STATE_RUNNABLE;
1170 /* insert the thread into the threads table */
1172 threads_table_add(thread);
1174 #if defined(ENABLE_INTRP)
1175 /* create interpreter stack */
1178 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1179 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1183 #if defined(WITH_CLASSPATH_GNU)
1184 /* create a java.lang.VMThread object */
1186 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1191 /* set the thread */
1194 vmt->vmdata = (java_lang_Object *) thread;
1195 #elif defined(WITH_CLASSPATH_CLDC1_1)
1196 t->vm_thread = (java_lang_Object *) thread;
1199 if (vm_aargs != NULL) {
1200 u = utf_new_char(vm_aargs->name);
1201 #if defined(ENABLE_JAVASE)
1202 group = (java_lang_ThreadGroup *) vm_aargs->group;
1207 #if defined(ENABLE_JAVASE)
1208 /* get the main thread */
1210 mainthread = threads_table_first();
1211 group = mainthread->object->group;
1215 /* the the thread name */
1217 s = javastring_new(u);
1219 /* for convenience */
1221 o = (java_objectheader *) thread->object;
1223 #if defined(WITH_CLASSPATH_GNU)
1224 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1226 #elif defined(WITH_CLASSPATH_CLDC1_1)
1227 (void) vm_call_method(method_thread_init, o, s);
1233 #if defined(ENABLE_JAVASE)
1234 /* store the thread group in the object */
1236 thread->object->group = group;
1238 /* add thread to given thread-group */
1240 m = class_resolveclassmethod(group->header.vftbl->class,
1242 utf_java_lang_Thread__V,
1243 class_java_lang_ThreadGroup,
1246 o = (java_objectheader *) group;
1248 (void) vm_call_method(m, o, t);
1258 /* threads_detach_thread *******************************************************
1260 Detaches the passed thread from the VM. Used in JNI.
1262 *******************************************************************************/
1264 bool threads_detach_thread(threadobject *thread)
1266 #if defined(ENABLE_JAVASE)
1267 java_lang_ThreadGroup *group;
1269 java_objectheader *o;
1270 java_lang_Thread *t;
1273 /* Allow lock record pools to be used by other threads. They
1274 cannot be deleted so we'd better not waste them. */
1276 /* XXX We have to find a new way to free lock records */
1277 /* with the new locking algorithm. */
1278 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1280 /* XXX implement uncaught exception stuff (like JamVM does) */
1282 #if defined(ENABLE_JAVASE)
1283 /* remove thread from the thread group */
1285 group = thread->object->group;
1287 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1289 if (group != NULL) {
1290 m = class_resolveclassmethod(group->header.vftbl->class,
1292 utf_java_lang_Thread__V,
1293 class_java_lang_ThreadGroup,
1299 o = (java_objectheader *) group;
1302 (void) vm_call_method(m, o, t);
1309 /* thread is terminated */
1311 thread->state = THREAD_STATE_TERMINATED;
1313 /* remove thread from the threads table */
1315 threads_table_remove(thread);
1317 /* signal that this thread has finished */
1319 pthread_mutex_lock(&mutex_join);
1320 pthread_cond_signal(&cond_join);
1321 pthread_mutex_unlock(&mutex_join);
1323 /* free the vm internal thread object */
1325 #if defined(ENABLE_GC_BOEHM)
1328 FREE(thread, threadobject);
1331 #if defined(ENABLE_STATISTICS)
1333 size_threadobject -= sizeof(threadobject);
1340 /* threads_join_all_threads ****************************************************
1342 Join all non-daemon threads.
1344 *******************************************************************************/
1346 void threads_join_all_threads(void)
1348 threadobject *thread;
1350 /* get current thread */
1352 thread = THREADOBJECT;
1354 /* this thread is waiting for all non-daemon threads to exit */
1356 thread->state = THREAD_STATE_WAITING;
1358 /* enter join mutex */
1360 pthread_mutex_lock(&mutex_join);
1362 /* Wait for condition as long as we have non-daemon threads. We
1363 compare against 1 because the current (main thread) is also a
1364 non-daemon thread. */
1366 while (threads_table_get_non_daemons() > 1)
1367 pthread_cond_wait(&cond_join, &mutex_join);
1369 /* leave join mutex */
1371 pthread_mutex_unlock(&mutex_join);
1375 /* threads_timespec_earlier ****************************************************
1377 Return true if timespec tv1 is earlier than timespec tv2.
1380 tv1..........first timespec
1381 tv2..........second timespec
1384 true, if the first timespec is earlier
1386 *******************************************************************************/
1388 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1389 const struct timespec *tv2)
1391 return (tv1->tv_sec < tv2->tv_sec)
1393 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1397 /* threads_current_time_is_earlier_than ****************************************
1399 Check if the current time is earlier than the given timespec.
1402 tv...........the timespec to compare against
1405 true, if the current time is earlier
1407 *******************************************************************************/
1409 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1411 struct timeval tvnow;
1412 struct timespec tsnow;
1414 /* get current time */
1416 if (gettimeofday(&tvnow, NULL) != 0)
1417 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1419 /* convert it to a timespec */
1421 tsnow.tv_sec = tvnow.tv_sec;
1422 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1424 /* compare current time with the given timespec */
1426 return threads_timespec_earlier(&tsnow, tv);
1430 /* threads_wait_with_timeout ***************************************************
1432 Wait until the given point in time on a monitor until either
1433 we are notified, we are interrupted, or the time is up.
1436 t............the current thread
1437 wakeupTime...absolute (latest) wakeup time
1438 If both tv_sec and tv_nsec are zero, this function
1439 waits for an unlimited amount of time.
1442 true.........if the wait has been interrupted,
1443 false........if the wait was ended by notification or timeout
1445 *******************************************************************************/
1447 static bool threads_wait_with_timeout(threadobject *thread,
1448 struct timespec *wakeupTime)
1450 bool wasinterrupted;
1452 /* acquire the waitmutex */
1454 pthread_mutex_lock(&thread->waitmutex);
1456 /* mark us as sleeping */
1458 thread->sleeping = true;
1460 /* wait on waitcond */
1462 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1464 while (!thread->interrupted && !thread->signaled
1465 && threads_current_time_is_earlier_than(wakeupTime))
1467 thread->state = THREAD_STATE_TIMED_WAITING;
1469 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1472 thread->state = THREAD_STATE_RUNNABLE;
1477 while (!thread->interrupted && !thread->signaled) {
1478 thread->state = THREAD_STATE_WAITING;
1480 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1482 thread->state = THREAD_STATE_RUNNABLE;
1486 /* check if we were interrupted */
1488 wasinterrupted = thread->interrupted;
1490 /* reset all flags */
1492 thread->interrupted = false;
1493 thread->signaled = false;
1494 thread->sleeping = false;
1496 /* release the waitmutex */
1498 pthread_mutex_unlock(&thread->waitmutex);
1500 return wasinterrupted;
1504 /* threads_wait_with_timeout_relative ******************************************
1506 Wait for the given maximum amount of time on a monitor until either
1507 we are notified, we are interrupted, or the time is up.
1510 t............the current thread
1511 millis.......milliseconds to wait
1512 nanos........nanoseconds to wait
1515 true.........if the wait has been interrupted,
1516 false........if the wait was ended by notification or timeout
1518 *******************************************************************************/
1520 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1523 struct timespec wakeupTime;
1525 /* calculate the the (latest) wakeup time */
1527 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1531 return threads_wait_with_timeout(thread, &wakeupTime);
1535 /* threads_calc_absolute_time **************************************************
1537 Calculate the absolute point in time a given number of ms and ns from now.
1540 millis............milliseconds from now
1541 nanos.............nanoseconds from now
1544 *tm...............receives the timespec of the absolute point in time
1546 *******************************************************************************/
1548 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1550 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1553 gettimeofday(&tv, NULL);
1554 tv.tv_sec += millis / 1000;
1556 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1557 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1558 tm->tv_nsec = nsec % 1000000000;
1567 /* threads_thread_interrupt ****************************************************
1569 Interrupt the given thread.
1571 The thread gets the "waitcond" signal and
1572 its interrupted flag is set to true.
1575 thread............the thread to interrupt
1577 *******************************************************************************/
1579 void threads_thread_interrupt(threadobject *thread)
1581 /* Signal the thread a "waitcond" and tell it that it has been
1584 pthread_mutex_lock(&thread->waitmutex);
1586 /* Interrupt blocking system call using a signal. */
1588 pthread_kill(thread->tid, SIGHUP);
1590 if (thread->sleeping)
1591 pthread_cond_signal(&thread->waitcond);
1593 thread->interrupted = true;
1595 pthread_mutex_unlock(&thread->waitmutex);
1599 /* threads_check_if_interrupted_and_reset **************************************
1601 Check if the current thread has been interrupted and reset the
1605 true, if the current thread had been interrupted
1607 *******************************************************************************/
1609 bool threads_check_if_interrupted_and_reset(void)
1611 threadobject *thread;
1614 thread = THREADOBJECT;
1616 /* get interrupted flag */
1618 intr = thread->interrupted;
1620 /* reset interrupted flag */
1622 thread->interrupted = false;
1628 /* threads_thread_has_been_interrupted *****************************************
1630 Check if the given thread has been interrupted
1633 t............the thread to check
1636 true, if the given thread had been interrupted
1638 *******************************************************************************/
1640 bool threads_thread_has_been_interrupted(threadobject *thread)
1642 return thread->interrupted;
1646 /* threads_sleep ***************************************************************
1648 Sleep the current thread for the specified amount of time.
1650 *******************************************************************************/
1652 void threads_sleep(s8 millis, s4 nanos)
1654 threadobject *thread;
1655 struct timespec wakeupTime;
1656 bool wasinterrupted;
1658 thread = THREADOBJECT;
1660 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1662 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1665 exceptions_throw_interruptedexception();
1669 /* threads_yield ***************************************************************
1671 Yield to the scheduler.
1673 *******************************************************************************/
1675 void threads_yield(void)
1682 * These are local overrides for various environment variables in Emacs.
1683 * Please do not remove this and leave it at the end of the file, where
1684 * Emacs will automagically detect them.
1685 * ---------------------------------------------------------------------
1688 * indent-tabs-mode: t
1692 * vim:noexpandtab:sw=4:ts=4: