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 7894 2007-05-10 14:04:05Z 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 static methodinfo *method_thread_init;
221 /* the thread object of the current thread */
222 /* This is either a thread-local variable defined with __thread, or */
223 /* a thread-specific value stored with key threads_current_threadobject_key. */
224 #if defined(HAVE___THREAD)
225 __thread threadobject *threads_current_threadobject;
227 pthread_key_t threads_current_threadobject_key;
230 /* global mutex for the threads table */
231 static pthread_mutex_t mutex_threads_table;
233 /* global mutex for stop-the-world */
234 static pthread_mutex_t stopworldlock;
236 /* global mutex and condition for joining threads on exit */
237 static pthread_mutex_t mutex_join;
238 static pthread_cond_t cond_join;
240 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
242 static volatile int stopworldwhere;
244 /* semaphore used for acknowleding thread suspension */
245 static sem_t suspend_ack;
246 #if defined(__MIPS__)
247 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
248 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
251 static pthread_attr_t threadattr;
253 /* mutexes used by the fake atomic instructions */
254 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
255 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
256 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
257 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
261 /* threads_sem_init ************************************************************
263 Initialize a semaphore. Checks against errors and interruptions.
266 sem..............the semaphore to initialize
267 shared...........true if this semaphore will be shared between processes
268 value............the initial value for the semaphore
270 *******************************************************************************/
272 void threads_sem_init(sem_t *sem, bool shared, int value)
279 r = sem_init(sem, shared, value);
282 } while (errno == EINTR);
284 vm_abort("sem_init failed: %s", strerror(errno));
288 /* threads_sem_wait ************************************************************
290 Wait for a semaphore, non-interruptible.
292 IMPORTANT: Always use this function instead of `sem_wait` directly, as
293 `sem_wait` may be interrupted by signals!
296 sem..............the semaphore to wait on
298 *******************************************************************************/
300 void threads_sem_wait(sem_t *sem)
310 } while (errno == EINTR);
312 vm_abort("sem_wait failed: %s", strerror(errno));
316 /* threads_sem_post ************************************************************
318 Increase the count of a semaphore. Checks for errors.
321 sem..............the semaphore to increase the count of
323 *******************************************************************************/
325 void threads_sem_post(sem_t *sem)
331 /* unlike sem_wait, sem_post is not interruptible */
337 vm_abort("sem_post failed: %s", strerror(errno));
341 /* lock_stopworld **************************************************************
343 Enter the stopworld lock, specifying why the world shall be stopped.
346 where........ STOPWORLD_FROM_GC (1) from within GC
347 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
349 ******************************************************************************/
351 void lock_stopworld(int where)
353 pthread_mutex_lock(&stopworldlock);
354 stopworldwhere = where;
358 /* unlock_stopworld ************************************************************
360 Release the stopworld lock.
362 ******************************************************************************/
364 void unlock_stopworld(void)
367 pthread_mutex_unlock(&stopworldlock);
370 #if !defined(__DARWIN__)
371 /* Caller must hold threadlistlock */
372 static void threads_cast_sendsignals(int sig)
379 /* iterate over all started threads */
381 for (t = threads_table_first(); t != NULL; t = threads_table_next(t)) {
382 /* don't send the signal to ourself */
385 pthread_kill(t->tid, sig);
391 static void threads_cast_darwinstop(void)
393 threadobject *tobj = mainthreadobj;
394 threadobject *self = THREADOBJECT;
399 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
400 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
401 #if defined(__I386__)
402 i386_thread_state_t thread_state;
404 ppc_thread_state_t thread_state;
406 mach_port_t thread = tobj->mach_thread;
409 r = thread_suspend(thread);
411 if (r != KERN_SUCCESS)
412 vm_abort("thread_suspend failed");
414 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
415 &thread_state_count);
417 if (r != KERN_SUCCESS)
418 vm_abort("thread_get_state failed");
420 md_critical_section_restart((ucontext_t *) &thread_state);
422 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
425 if (r != KERN_SUCCESS)
426 vm_abort("thread_set_state failed");
430 } while (tobj != mainthreadobj);
433 static void threads_cast_darwinresume(void)
435 threadobject *tobj = mainthreadobj;
436 threadobject *self = THREADOBJECT;
441 mach_port_t thread = tobj->mach_thread;
444 r = thread_resume(thread);
446 if (r != KERN_SUCCESS)
447 vm_abort("thread_resume failed");
451 } while (tobj != mainthreadobj);
456 #if defined(__MIPS__)
457 static void threads_cast_irixresume(void)
459 pthread_mutex_lock(&suspend_ack_lock);
460 pthread_cond_broadcast(&suspend_cond);
461 pthread_mutex_unlock(&suspend_ack_lock);
465 #if !defined(DISABLE_GC)
467 void threads_cast_stopworld(void)
469 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
473 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
475 /* lock the threads table */
477 threads_table_lock();
479 #if defined(__DARWIN__)
480 threads_cast_darwinstop();
481 #elif defined(__CYGWIN__)
485 /* send all threads the suspend signal */
487 threads_cast_sendsignals(GC_signum1());
489 /* wait for all threads to suspend (except the current one) */
491 count = threads_table_get_threads() - 1;
493 for (i = 0; i < count; i++)
494 threads_sem_wait(&suspend_ack);
497 /* unlock the threads table */
499 threads_table_unlock();
502 void threads_cast_startworld(void)
504 /* lock the threads table */
506 threads_table_lock();
508 #if defined(__DARWIN__)
509 threads_cast_darwinresume();
510 #elif defined(__MIPS__)
511 threads_cast_irixresume();
512 #elif defined(__CYGWIN__)
516 threads_cast_sendsignals(GC_signum2());
519 /* unlock the threads table */
521 threads_table_unlock();
527 #if !defined(__DARWIN__)
528 static void threads_sigsuspend_handler(ucontext_t *_uc)
533 /* XXX TWISTI: this is just a quick hack */
534 #if defined(ENABLE_JIT)
535 md_critical_section_restart(_uc);
538 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
539 (not POSIX async-safe). */
540 #if defined(__IRIX__)
541 pthread_mutex_lock(&suspend_ack_lock);
542 threads_sem_post(&suspend_ack);
543 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
544 pthread_mutex_unlock(&suspend_ack_lock);
545 #elif defined(__CYGWIN__)
549 threads_sem_post(&suspend_ack);
553 sigdelset(&sigs, sig);
558 /* This function is called from Boehm GC code. */
560 int cacao_suspendhandler(ucontext_t *_uc)
562 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
565 threads_sigsuspend_handler(_uc);
570 #endif /* DISABLE_GC */
573 /* threads_set_current_threadobject ********************************************
575 Set the current thread object.
578 thread.......the thread object to set
580 *******************************************************************************/
582 void threads_set_current_threadobject(threadobject *thread)
584 #if !defined(HAVE___THREAD)
585 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
586 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
588 threads_current_threadobject = thread;
593 /* threads_init_threadobject **************************************************
595 Initialize implementation fields of a threadobject.
598 thread............the threadobject
600 ******************************************************************************/
602 void threads_init_threadobject(threadobject *thread)
604 /* get the pthread id */
606 thread->tid = pthread_self();
610 /* TODO destroy all those things */
612 pthread_mutex_init(&(thread->waitmutex), NULL);
613 pthread_cond_init(&(thread->waitcond), NULL);
615 thread->interrupted = false;
616 thread->signaled = false;
617 thread->sleeping = false;
621 /* threads_get_current_threadobject ********************************************
623 Return the threadobject of the current thread.
626 the current threadobject * (an instance of java.lang.Thread)
628 *******************************************************************************/
630 threadobject *threads_get_current_threadobject(void)
636 /* threads_impl_preinit ********************************************************
638 Do some early initialization of stuff required.
640 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
641 is called AFTER this function!
643 *******************************************************************************/
645 void threads_impl_preinit(void)
647 pthread_mutex_init(&stopworldlock, NULL);
649 /* initialize exit mutex and condition (on exit we join all
652 pthread_mutex_init(&mutex_join, NULL);
653 pthread_cond_init(&cond_join, NULL);
655 #if !defined(HAVE___THREAD)
656 pthread_key_create(&threads_current_threadobject_key, NULL);
659 threads_sem_init(&suspend_ack, 0, 0);
663 /* threads_table_lock **********************************************************
665 Initialize threads table mutex.
667 *******************************************************************************/
669 void threads_impl_table_init(void)
671 pthread_mutex_init(&mutex_threads_table, NULL);
675 /* threads_table_lock **********************************************************
677 Enter the threads table mutex.
679 NOTE: We need this function as we can't use an internal lock for
680 the threads table because the thread's lock is initialized in
681 threads_table_add (when we have the thread index), but we
682 already need the lock at the entry of the function.
684 *******************************************************************************/
686 void threads_table_lock(void)
688 if (pthread_mutex_lock(&mutex_threads_table) != 0)
689 vm_abort("threads_table_lock: pthread_mutex_lock failed: %s",
694 /* threads_table_unlock ********************************************************
696 Leave the threads table mutex.
698 *******************************************************************************/
700 void threads_table_unlock(void)
702 if (pthread_mutex_unlock(&mutex_threads_table) != 0)
703 vm_abort("threads_table_unlock: pthread_mutex_unlock failed: %s",
708 /* threads_init ****************************************************************
710 Initializes the threads required by the JVM: main, finalizer.
712 *******************************************************************************/
714 bool threads_init(void)
716 threadobject *mainthread;
717 java_objectheader *threadname;
719 java_objectheader *o;
721 #if defined(ENABLE_JAVASE)
722 java_lang_ThreadGroup *threadgroup;
726 #if defined(WITH_CLASSPATH_GNU)
727 java_lang_VMThread *vmt;
730 /* get methods we need in this file */
732 #if defined(WITH_CLASSPATH_GNU)
734 class_resolveclassmethod(class_java_lang_Thread,
736 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
737 class_java_lang_Thread,
741 class_resolveclassmethod(class_java_lang_Thread,
743 utf_new_char("(Ljava/lang/String;)V"),
744 class_java_lang_Thread,
748 if (method_thread_init == NULL)
751 /* Get the main-thread (NOTE: The main threads is always the first
752 thread in the table). */
754 mainthread = threads_table_first();
756 /* create a java.lang.Thread for the main thread */
758 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
763 /* set the object in the internal data structure */
765 mainthread->object = t;
767 #if defined(ENABLE_INTRP)
768 /* create interpreter stack */
771 MSET(intrp_main_stack, 0, u1, opt_stacksize);
772 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
776 threadname = javastring_new(utf_new_char("main"));
778 #if defined(ENABLE_JAVASE)
779 /* allocate and init ThreadGroup */
781 threadgroup = (java_lang_ThreadGroup *)
782 native_new_and_init(class_java_lang_ThreadGroup);
784 if (threadgroup == NULL)
788 #if defined(WITH_CLASSPATH_GNU)
789 /* create a java.lang.VMThread for the main thread */
791 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
799 vmt->vmdata = (java_lang_Object *) mainthread;
801 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
802 o = (java_objectheader *) t;
804 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
806 #elif defined(WITH_CLASSPATH_CLDC1_1)
809 t->vm_thread = (java_lang_Object *) mainthread;
811 /* call public Thread(String name) */
813 o = (java_objectheader *) t;
815 (void) vm_call_method(method_thread_init, o, threadname);
821 #if defined(ENABLE_JAVASE)
822 t->group = threadgroup;
824 /* add main thread to java.lang.ThreadGroup */
826 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
828 utf_java_lang_Thread__V,
829 class_java_lang_ThreadGroup,
832 o = (java_objectheader *) threadgroup;
834 (void) vm_call_method(m, o, t);
840 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
842 /* initialize the thread attribute object */
844 if (pthread_attr_init(&threadattr)) {
845 log_println("pthread_attr_init failed: %s", strerror(errno));
849 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
852 if (opt_verbosethreads) {
853 printf("[Starting thread ");
854 threads_thread_print_info(mainthread);
859 /* everything's ok */
865 /* threads_startup_thread ******************************************************
867 Thread startup function called by pthread_create.
869 Thread which have a startup.function != NULL are marked as internal
870 threads. All other threads are threated as normal Java threads.
872 NOTE: This function is not called directly by pthread_create. The Boehm GC
873 inserts its own GC_start_routine in between, which then calls
877 t............the argument passed to pthread_create, ie. a pointer to
878 a startupinfo struct. CAUTION: When the `psem` semaphore
879 is posted, the startupinfo struct becomes invalid! (It
880 is allocated on the stack of threads_start_thread.)
882 ******************************************************************************/
884 static void *threads_startup_thread(void *t)
886 startupinfo *startup;
887 threadobject *thread;
888 #if defined(WITH_CLASSPATH_GNU)
889 java_lang_VMThread *vmt;
894 java_objectheader *o;
895 functionptr function;
897 #if defined(ENABLE_INTRP)
898 u1 *intrp_thread_stack;
900 /* create interpreter stack */
903 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
904 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
907 intrp_thread_stack = NULL;
910 /* get passed startupinfo structure and the values in there */
913 t = NULL; /* make sure it's not used wrongly */
915 thread = startup->thread;
916 function = startup->function;
917 psem = startup->psem;
919 /* Seems like we've encountered a situation where thread->tid was
920 not set by pthread_create. We alleviate this problem by waiting
921 for pthread_create to return. */
923 threads_sem_wait(startup->psem_first);
925 #if defined(__DARWIN__)
926 thread->mach_thread = mach_thread_self();
929 /* store the internal thread data-structure in the TSD */
931 threads_set_current_threadobject(thread);
933 /* thread is running */
935 thread->state = THREAD_STATE_RUNNABLE;
937 /* insert the thread into the threads table */
939 threads_table_add(thread);
941 /* tell threads_startup_thread that we registered ourselves */
942 /* CAUTION: *startup becomes invalid with this! */
945 threads_sem_post(psem);
947 /* set our priority */
949 threads_set_thread_priority(thread->tid, thread->object->priority);
951 #if defined(ENABLE_INTRP)
952 /* set interpreter stack */
955 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
958 #if defined(ENABLE_JVMTI)
959 /* fire thread start event */
962 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
966 if (opt_verbosethreads) {
967 printf("[Starting thread ");
968 threads_thread_print_info(thread);
973 /* find and run the Thread.run()V method if no other function was passed */
975 if (function == NULL) {
976 #if defined(WITH_CLASSPATH_GNU)
977 /* We need to start the run method of
978 java.lang.VMThread. Since this is a final class, we can use
979 the class object directly. */
981 c = class_java_lang_VMThread;
982 #elif defined(WITH_CLASSPATH_CLDC1_1)
983 c = thread->object->header.vftbl->class;
986 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
989 vm_abort("threads_startup_thread: run() method not found in class");
991 /* set ThreadMXBean variables */
993 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
994 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
996 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
997 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
998 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
999 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1001 #if defined(WITH_CLASSPATH_GNU)
1002 /* we need to start the run method of java.lang.VMThread */
1004 vmt = (java_lang_VMThread *) thread->object->vmThread;
1005 o = (java_objectheader *) vmt;
1007 #elif defined(WITH_CLASSPATH_CLDC1_1)
1008 o = (java_objectheader *) thread->object;
1011 /* run the thread */
1013 (void) vm_call_method(m, o);
1016 /* set ThreadMXBean variables */
1018 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1019 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1021 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1022 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1023 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1024 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1026 /* call passed function, e.g. finalizer_thread */
1031 #if !defined(NDEBUG)
1032 if (opt_verbosethreads) {
1033 printf("[Stopping thread ");
1034 threads_thread_print_info(thread);
1039 #if defined(ENABLE_JVMTI)
1040 /* fire thread end event */
1043 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1046 if (!threads_detach_thread(thread))
1047 vm_abort("threads_startup_thread: threads_detach_thread failed");
1049 /* set ThreadMXBean variables */
1051 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1057 /* threads_impl_thread_start ***************************************************
1059 Start a thread in the JVM. Both (vm internal and java) thread
1063 thread....the thread object
1064 f.........function to run in the new thread. NULL means that the
1065 "run" method of the object `t` should be called
1067 ******************************************************************************/
1069 void threads_impl_thread_start(threadobject *thread, functionptr f)
1073 pthread_attr_t attr;
1074 startupinfo startup;
1076 /* fill startupinfo structure passed by pthread_create to
1077 * threads_startup_thread */
1079 startup.thread = thread;
1080 startup.function = f; /* maybe we don't call Thread.run()V */
1081 startup.psem = &sem;
1082 startup.psem_first = &sem_first;
1084 threads_sem_init(&sem, 0, 0);
1085 threads_sem_init(&sem_first, 0, 0);
1087 /* initialize thread attribute object */
1089 if (pthread_attr_init(&attr))
1090 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1092 /* initialize thread stacksize */
1094 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1095 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1097 /* create the thread */
1099 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1100 vm_abort("pthread_create failed: %s", strerror(errno));
1102 /* signal that pthread_create has returned, so thread->tid is valid */
1104 threads_sem_post(&sem_first);
1106 /* wait here until the thread has entered itself into the thread list */
1108 threads_sem_wait(&sem);
1113 sem_destroy(&sem_first);
1117 /* threads_set_thread_priority *************************************************
1119 Set the priority of the given thread.
1122 tid..........thread id
1123 priority.....priority to set
1125 ******************************************************************************/
1127 void threads_set_thread_priority(pthread_t tid, int priority)
1129 struct sched_param schedp;
1132 pthread_getschedparam(tid, &policy, &schedp);
1133 schedp.sched_priority = priority;
1134 pthread_setschedparam(tid, policy, &schedp);
1138 /* threads_attach_current_thread ***********************************************
1140 Attaches the current thread to the VM. Used in JNI.
1142 *******************************************************************************/
1144 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1146 threadobject *thread;
1148 java_objectheader *s;
1149 java_objectheader *o;
1150 java_lang_Thread *t;
1152 #if defined(ENABLE_JAVASE)
1153 java_lang_ThreadGroup *group;
1154 threadobject *mainthread;
1158 #if defined(WITH_CLASSPATH_GNU)
1159 java_lang_VMThread *vmt;
1162 /* create internal thread data-structure */
1164 thread = threads_create_thread();
1166 /* create a java.lang.Thread object */
1168 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1175 /* thread is a Java thread and running */
1177 thread->flags = THREAD_FLAG_JAVA;
1180 thread->flags |= THREAD_FLAG_DAEMON;
1182 thread->state = THREAD_STATE_RUNNABLE;
1184 /* insert the thread into the threads table */
1186 threads_table_add(thread);
1188 #if !defined(NDEBUG)
1189 if (opt_verbosethreads) {
1190 printf("[Attaching thread ");
1191 threads_thread_print_info(thread);
1196 #if defined(ENABLE_INTRP)
1197 /* create interpreter stack */
1200 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1201 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1205 #if defined(WITH_CLASSPATH_GNU)
1206 /* create a java.lang.VMThread object */
1208 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1213 /* set the thread */
1216 vmt->vmdata = (java_lang_Object *) thread;
1217 #elif defined(WITH_CLASSPATH_CLDC1_1)
1218 t->vm_thread = (java_lang_Object *) thread;
1221 if (vm_aargs != NULL) {
1222 u = utf_new_char(vm_aargs->name);
1223 #if defined(ENABLE_JAVASE)
1224 group = (java_lang_ThreadGroup *) vm_aargs->group;
1229 #if defined(ENABLE_JAVASE)
1230 /* get the main thread */
1232 mainthread = threads_table_first();
1233 group = mainthread->object->group;
1237 /* the the thread name */
1239 s = javastring_new(u);
1241 /* for convenience */
1243 o = (java_objectheader *) thread->object;
1245 #if defined(WITH_CLASSPATH_GNU)
1246 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1248 #elif defined(WITH_CLASSPATH_CLDC1_1)
1249 (void) vm_call_method(method_thread_init, o, s);
1255 #if defined(ENABLE_JAVASE)
1256 /* store the thread group in the object */
1258 thread->object->group = group;
1260 /* add thread to given thread-group */
1262 m = class_resolveclassmethod(group->header.vftbl->class,
1264 utf_java_lang_Thread__V,
1265 class_java_lang_ThreadGroup,
1268 o = (java_objectheader *) group;
1270 (void) vm_call_method(m, o, t);
1280 /* threads_detach_thread *******************************************************
1282 Detaches the passed thread from the VM. Used in JNI.
1284 *******************************************************************************/
1286 bool threads_detach_thread(threadobject *thread)
1288 #if defined(ENABLE_JAVASE)
1289 java_lang_ThreadGroup *group;
1291 java_objectheader *o;
1292 java_lang_Thread *t;
1295 /* Allow lock record pools to be used by other threads. They
1296 cannot be deleted so we'd better not waste them. */
1298 /* XXX We have to find a new way to free lock records */
1299 /* with the new locking algorithm. */
1300 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1302 /* XXX implement uncaught exception stuff (like JamVM does) */
1304 #if defined(ENABLE_JAVASE)
1305 /* remove thread from the thread group */
1307 group = thread->object->group;
1309 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1311 if (group != NULL) {
1312 m = class_resolveclassmethod(group->header.vftbl->class,
1314 utf_java_lang_Thread__V,
1315 class_java_lang_ThreadGroup,
1321 o = (java_objectheader *) group;
1324 (void) vm_call_method(m, o, t);
1331 /* thread is terminated */
1333 thread->state = THREAD_STATE_TERMINATED;
1335 /* remove thread from the threads table */
1337 threads_table_remove(thread);
1339 #if !defined(NDEBUG)
1340 if (opt_verbosethreads) {
1341 printf("[Detaching thread ");
1342 threads_thread_print_info(thread);
1347 /* signal that this thread has finished */
1349 pthread_mutex_lock(&mutex_join);
1350 pthread_cond_signal(&cond_join);
1351 pthread_mutex_unlock(&mutex_join);
1353 /* free the vm internal thread object */
1355 #if defined(ENABLE_GC_BOEHM)
1358 FREE(thread, threadobject);
1361 #if defined(ENABLE_STATISTICS)
1363 size_threadobject -= sizeof(threadobject);
1370 /* threads_join_all_threads ****************************************************
1372 Join all non-daemon threads.
1374 *******************************************************************************/
1376 void threads_join_all_threads(void)
1378 threadobject *thread;
1380 /* get current thread */
1382 thread = THREADOBJECT;
1384 /* this thread is waiting for all non-daemon threads to exit */
1386 thread->state = THREAD_STATE_WAITING;
1388 /* enter join mutex */
1390 pthread_mutex_lock(&mutex_join);
1392 /* Wait for condition as long as we have non-daemon threads. We
1393 compare against 1 because the current (main thread) is also a
1394 non-daemon thread. */
1396 while (threads_table_get_non_daemons() > 1)
1397 pthread_cond_wait(&cond_join, &mutex_join);
1399 /* leave join mutex */
1401 pthread_mutex_unlock(&mutex_join);
1405 /* threads_timespec_earlier ****************************************************
1407 Return true if timespec tv1 is earlier than timespec tv2.
1410 tv1..........first timespec
1411 tv2..........second timespec
1414 true, if the first timespec is earlier
1416 *******************************************************************************/
1418 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1419 const struct timespec *tv2)
1421 return (tv1->tv_sec < tv2->tv_sec)
1423 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1427 /* threads_current_time_is_earlier_than ****************************************
1429 Check if the current time is earlier than the given timespec.
1432 tv...........the timespec to compare against
1435 true, if the current time is earlier
1437 *******************************************************************************/
1439 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1441 struct timeval tvnow;
1442 struct timespec tsnow;
1444 /* get current time */
1446 if (gettimeofday(&tvnow, NULL) != 0)
1447 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1449 /* convert it to a timespec */
1451 tsnow.tv_sec = tvnow.tv_sec;
1452 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1454 /* compare current time with the given timespec */
1456 return threads_timespec_earlier(&tsnow, tv);
1460 /* threads_wait_with_timeout ***************************************************
1462 Wait until the given point in time on a monitor until either
1463 we are notified, we are interrupted, or the time is up.
1466 t............the current thread
1467 wakeupTime...absolute (latest) wakeup time
1468 If both tv_sec and tv_nsec are zero, this function
1469 waits for an unlimited amount of time.
1472 true.........if the wait has been interrupted,
1473 false........if the wait was ended by notification or timeout
1475 *******************************************************************************/
1477 static bool threads_wait_with_timeout(threadobject *thread,
1478 struct timespec *wakeupTime)
1480 bool wasinterrupted;
1482 /* acquire the waitmutex */
1484 pthread_mutex_lock(&thread->waitmutex);
1486 /* mark us as sleeping */
1488 thread->sleeping = true;
1490 /* wait on waitcond */
1492 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1494 while (!thread->interrupted && !thread->signaled
1495 && threads_current_time_is_earlier_than(wakeupTime))
1497 thread->state = THREAD_STATE_TIMED_WAITING;
1499 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1502 thread->state = THREAD_STATE_RUNNABLE;
1507 while (!thread->interrupted && !thread->signaled) {
1508 thread->state = THREAD_STATE_WAITING;
1510 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1512 thread->state = THREAD_STATE_RUNNABLE;
1516 /* check if we were interrupted */
1518 wasinterrupted = thread->interrupted;
1520 /* reset all flags */
1522 thread->interrupted = false;
1523 thread->signaled = false;
1524 thread->sleeping = false;
1526 /* release the waitmutex */
1528 pthread_mutex_unlock(&thread->waitmutex);
1530 return wasinterrupted;
1534 /* threads_wait_with_timeout_relative ******************************************
1536 Wait for the given maximum amount of time on a monitor until either
1537 we are notified, we are interrupted, or the time is up.
1540 t............the current thread
1541 millis.......milliseconds to wait
1542 nanos........nanoseconds to wait
1545 true.........if the wait has been interrupted,
1546 false........if the wait was ended by notification or timeout
1548 *******************************************************************************/
1550 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1553 struct timespec wakeupTime;
1555 /* calculate the the (latest) wakeup time */
1557 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1561 return threads_wait_with_timeout(thread, &wakeupTime);
1565 /* threads_calc_absolute_time **************************************************
1567 Calculate the absolute point in time a given number of ms and ns from now.
1570 millis............milliseconds from now
1571 nanos.............nanoseconds from now
1574 *tm...............receives the timespec of the absolute point in time
1576 *******************************************************************************/
1578 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1580 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1583 gettimeofday(&tv, NULL);
1584 tv.tv_sec += millis / 1000;
1586 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1587 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1588 tm->tv_nsec = nsec % 1000000000;
1597 /* threads_thread_interrupt ****************************************************
1599 Interrupt the given thread.
1601 The thread gets the "waitcond" signal and
1602 its interrupted flag is set to true.
1605 thread............the thread to interrupt
1607 *******************************************************************************/
1609 void threads_thread_interrupt(threadobject *thread)
1611 /* Signal the thread a "waitcond" and tell it that it has been
1614 pthread_mutex_lock(&thread->waitmutex);
1616 /* Interrupt blocking system call using a signal. */
1618 pthread_kill(thread->tid, SIGHUP);
1620 if (thread->sleeping)
1621 pthread_cond_signal(&thread->waitcond);
1623 thread->interrupted = true;
1625 pthread_mutex_unlock(&thread->waitmutex);
1629 /* threads_check_if_interrupted_and_reset **************************************
1631 Check if the current thread has been interrupted and reset the
1635 true, if the current thread had been interrupted
1637 *******************************************************************************/
1639 bool threads_check_if_interrupted_and_reset(void)
1641 threadobject *thread;
1644 thread = THREADOBJECT;
1646 /* get interrupted flag */
1648 intr = thread->interrupted;
1650 /* reset interrupted flag */
1652 thread->interrupted = false;
1658 /* threads_thread_has_been_interrupted *****************************************
1660 Check if the given thread has been interrupted
1663 t............the thread to check
1666 true, if the given thread had been interrupted
1668 *******************************************************************************/
1670 bool threads_thread_has_been_interrupted(threadobject *thread)
1672 return thread->interrupted;
1676 /* threads_sleep ***************************************************************
1678 Sleep the current thread for the specified amount of time.
1680 *******************************************************************************/
1682 void threads_sleep(s8 millis, s4 nanos)
1684 threadobject *thread;
1685 struct timespec wakeupTime;
1686 bool wasinterrupted;
1688 thread = THREADOBJECT;
1690 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1692 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1695 exceptions_throw_interruptedexception();
1699 /* threads_yield ***************************************************************
1701 Yield to the scheduler.
1703 *******************************************************************************/
1705 void threads_yield(void)
1712 * These are local overrides for various environment variables in Emacs.
1713 * Please do not remove this and leave it at the end of the file, where
1714 * Emacs will automagically detect them.
1715 * ---------------------------------------------------------------------
1718 * indent-tabs-mode: t
1722 * vim:noexpandtab:sw=4:ts=4: