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 8132 2007-06-22 11:15:47Z 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/logging.h"
81 #include "vm/builtin.h"
82 #include "vm/exceptions.h"
83 #include "vm/global.h"
84 #include "vm/stringlocal.h"
87 #include "vm/jit/asmpart.h"
89 #include "vmcore/options.h"
91 #if defined(ENABLE_STATISTICS)
92 # include "vmcore/statistics.h"
95 #if !defined(__DARWIN__)
96 # if defined(__LINUX__)
97 # define GC_LINUX_THREADS
98 # elif defined(__MIPS__)
99 # define GC_IRIX_THREADS
101 # include <semaphore.h>
102 # if defined(ENABLE_GC_BOEHM)
103 # include "mm/boehm-gc/include/gc.h"
107 #if defined(ENABLE_JVMTI)
108 #include "native/jvmti/cacaodbg.h"
111 #if defined(__DARWIN__)
112 /* Darwin has no working semaphore implementation. This one is taken
116 This is a very simple semaphore implementation for darwin. It
117 is implemented in terms of pthreads calls so it isn't async signal
118 safe. This isn't a problem because signals aren't used to
119 suspend threads on darwin.
122 static int sem_init(sem_t *sem, int pshared, int value)
129 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
132 if (pthread_cond_init(&sem->cond, NULL) < 0)
138 static int sem_post(sem_t *sem)
140 if (pthread_mutex_lock(&sem->mutex) < 0)
145 if (pthread_cond_signal(&sem->cond) < 0) {
146 pthread_mutex_unlock(&sem->mutex);
150 if (pthread_mutex_unlock(&sem->mutex) < 0)
156 static int sem_wait(sem_t *sem)
158 if (pthread_mutex_lock(&sem->mutex) < 0)
161 while (sem->value == 0) {
162 pthread_cond_wait(&sem->cond, &sem->mutex);
167 if (pthread_mutex_unlock(&sem->mutex) < 0)
173 static int sem_destroy(sem_t *sem)
175 if (pthread_cond_destroy(&sem->cond) < 0)
178 if (pthread_mutex_destroy(&sem->mutex) < 0)
183 #endif /* defined(__DARWIN__) */
186 /* internally used constants **************************************************/
188 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
189 #define STOPWORLD_FROM_GC 1
190 #define STOPWORLD_FROM_CLASS_NUMBERING 2
193 /* startupinfo *****************************************************************
195 Struct used to pass info from threads_start_thread to
196 threads_startup_thread.
198 ******************************************************************************/
201 threadobject *thread; /* threadobject for this thread */
202 functionptr function; /* function to run in the new thread */
203 sem_t *psem; /* signals when thread has been entered */
204 /* in the thread list */
205 sem_t *psem_first; /* signals when pthread_create has returned */
209 /* prototypes *****************************************************************/
211 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
214 /******************************************************************************/
215 /* GLOBAL VARIABLES */
216 /******************************************************************************/
218 static methodinfo *method_thread_init;
220 /* the thread object of the current thread */
221 /* This is either a thread-local variable defined with __thread, or */
222 /* a thread-specific value stored with key threads_current_threadobject_key. */
223 #if defined(HAVE___THREAD)
224 __thread threadobject *threads_current_threadobject;
226 pthread_key_t threads_current_threadobject_key;
229 /* global mutex for the threads table */
230 static pthread_mutex_t mutex_threads_list;
232 /* global mutex for stop-the-world */
233 static pthread_mutex_t stopworldlock;
235 /* global mutex and condition for joining threads on exit */
236 static pthread_mutex_t mutex_join;
237 static pthread_cond_t cond_join;
239 /* XXX We disable that whole bunch of code until we have the exact-GC
244 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
246 static volatile int stopworldwhere;
248 /* semaphore used for acknowleding thread suspension */
249 static sem_t suspend_ack;
250 #if defined(__MIPS__)
251 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
252 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
257 /* mutexes used by the fake atomic instructions */
258 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
259 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
260 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
261 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
265 /* threads_sem_init ************************************************************
267 Initialize a semaphore. Checks against errors and interruptions.
270 sem..............the semaphore to initialize
271 shared...........true if this semaphore will be shared between processes
272 value............the initial value for the semaphore
274 *******************************************************************************/
276 void threads_sem_init(sem_t *sem, bool shared, int value)
283 r = sem_init(sem, shared, value);
286 } while (errno == EINTR);
288 vm_abort("sem_init failed: %s", strerror(errno));
292 /* threads_sem_wait ************************************************************
294 Wait for a semaphore, non-interruptible.
296 IMPORTANT: Always use this function instead of `sem_wait` directly, as
297 `sem_wait` may be interrupted by signals!
300 sem..............the semaphore to wait on
302 *******************************************************************************/
304 void threads_sem_wait(sem_t *sem)
314 } while (errno == EINTR);
316 vm_abort("sem_wait failed: %s", strerror(errno));
320 /* threads_sem_post ************************************************************
322 Increase the count of a semaphore. Checks for errors.
325 sem..............the semaphore to increase the count of
327 *******************************************************************************/
329 void threads_sem_post(sem_t *sem)
335 /* unlike sem_wait, sem_post is not interruptible */
341 vm_abort("sem_post failed: %s", strerror(errno));
345 /* lock_stopworld **************************************************************
347 Enter the stopworld lock, specifying why the world shall be stopped.
350 where........ STOPWORLD_FROM_GC (1) from within GC
351 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
353 ******************************************************************************/
355 void lock_stopworld(int where)
357 pthread_mutex_lock(&stopworldlock);
358 /* stopworldwhere = where; */
362 /* unlock_stopworld ************************************************************
364 Release the stopworld lock.
366 ******************************************************************************/
368 void unlock_stopworld(void)
370 /* stopworldwhere = 0; */
371 pthread_mutex_unlock(&stopworldlock);
374 /* XXX We disable that whole bunch of code until we have the exact-GC
379 #if !defined(__DARWIN__)
380 /* Caller must hold threadlistlock */
381 static s4 threads_cast_sendsignals(s4 sig)
389 /* iterate over all started threads */
393 for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
394 /* don't send the signal to ourself */
399 /* don't send the signal to NEW threads (because they are not
400 completely initialized) */
402 if (t->state == THREAD_STATE_NEW)
405 /* send the signal */
407 pthread_kill(t->tid, sig);
409 /* increase threads count */
419 static void threads_cast_darwinstop(void)
421 threadobject *tobj = mainthreadobj;
422 threadobject *self = THREADOBJECT;
427 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
428 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
429 #if defined(__I386__)
430 i386_thread_state_t thread_state;
432 ppc_thread_state_t thread_state;
434 mach_port_t thread = tobj->mach_thread;
437 r = thread_suspend(thread);
439 if (r != KERN_SUCCESS)
440 vm_abort("thread_suspend failed");
442 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
443 &thread_state_count);
445 if (r != KERN_SUCCESS)
446 vm_abort("thread_get_state failed");
448 md_critical_section_restart((ucontext_t *) &thread_state);
450 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
453 if (r != KERN_SUCCESS)
454 vm_abort("thread_set_state failed");
458 } while (tobj != mainthreadobj);
461 static void threads_cast_darwinresume(void)
463 threadobject *tobj = mainthreadobj;
464 threadobject *self = THREADOBJECT;
469 mach_port_t thread = tobj->mach_thread;
472 r = thread_resume(thread);
474 if (r != KERN_SUCCESS)
475 vm_abort("thread_resume failed");
479 } while (tobj != mainthreadobj);
484 #if defined(__MIPS__)
485 static void threads_cast_irixresume(void)
487 pthread_mutex_lock(&suspend_ack_lock);
488 pthread_cond_broadcast(&suspend_cond);
489 pthread_mutex_unlock(&suspend_ack_lock);
493 #if !defined(DISABLE_GC)
495 void threads_cast_stopworld(void)
497 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
501 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
503 /* lock the threads lists */
507 #if defined(__DARWIN__)
508 threads_cast_darwinstop();
509 #elif defined(__CYGWIN__)
513 /* send all threads the suspend signal */
515 count = threads_cast_sendsignals(GC_signum1());
517 /* wait for all threads signaled to suspend */
519 for (i = 0; i < count; i++)
520 threads_sem_wait(&suspend_ack);
523 /* ATTENTION: Don't unlock the threads-lists here so that
524 non-signaled NEW threads can't change their state and execute
529 void threads_cast_startworld(void)
531 #if defined(__DARWIN__)
532 threads_cast_darwinresume();
533 #elif defined(__MIPS__)
534 threads_cast_irixresume();
535 #elif defined(__CYGWIN__)
539 (void) threads_cast_sendsignals(GC_signum2());
542 /* unlock the threads lists */
544 threads_list_unlock();
550 #if !defined(__DARWIN__)
551 static void threads_sigsuspend_handler(ucontext_t *_uc)
556 /* XXX TWISTI: this is just a quick hack */
557 #if defined(ENABLE_JIT)
558 md_critical_section_restart(_uc);
561 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
562 (not POSIX async-safe). */
563 #if defined(__IRIX__)
564 pthread_mutex_lock(&suspend_ack_lock);
565 threads_sem_post(&suspend_ack);
566 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
567 pthread_mutex_unlock(&suspend_ack_lock);
568 #elif defined(__CYGWIN__)
572 threads_sem_post(&suspend_ack);
576 sigdelset(&sigs, sig);
584 /* This function is called from Boehm GC code. */
586 int cacao_suspendhandler(ucontext_t *_uc)
588 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
591 threads_sigsuspend_handler(_uc);
595 #endif /* DISABLE_GC */
600 /* threads_set_current_threadobject ********************************************
602 Set the current thread object.
605 thread.......the thread object to set
607 *******************************************************************************/
609 void threads_set_current_threadobject(threadobject *thread)
611 #if !defined(HAVE___THREAD)
612 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
613 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
615 threads_current_threadobject = thread;
620 /* threads_impl_thread_new *****************************************************
622 Initialize implementation fields of a threadobject.
625 t....the threadobject
627 *******************************************************************************/
629 void threads_impl_thread_new(threadobject *t)
631 /* get the pthread id */
633 t->tid = pthread_self();
635 /* initialize the mutex and the condition */
637 pthread_mutex_init(&(t->waitmutex), NULL);
638 pthread_cond_init(&(t->waitcond), NULL);
640 #if defined(ENABLE_DEBUG_FILTER)
641 /* Initialize filter counters */
642 t->filterverbosecallctr[0] = 0;
643 t->filterverbosecallctr[1] = 0;
648 /* threads_impl_thread_free ****************************************************
650 Cleanup thread stuff.
653 t....the threadobject
655 *******************************************************************************/
657 void threads_impl_thread_free(threadobject *t)
659 /* destroy the mutex and the condition */
661 if (pthread_mutex_destroy(&(t->waitmutex)) != 0)
662 vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
665 if (pthread_cond_destroy(&(t->waitcond)) != 0)
666 vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
671 /* threads_get_current_threadobject ********************************************
673 Return the threadobject of the current thread.
676 the current threadobject * (an instance of java.lang.Thread)
678 *******************************************************************************/
680 threadobject *threads_get_current_threadobject(void)
686 /* threads_impl_preinit ********************************************************
688 Do some early initialization of stuff required.
690 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
691 is called AFTER this function!
693 *******************************************************************************/
695 void threads_impl_preinit(void)
697 pthread_mutex_init(&stopworldlock, NULL);
699 /* initialize exit mutex and condition (on exit we join all
702 pthread_mutex_init(&mutex_join, NULL);
703 pthread_cond_init(&cond_join, NULL);
705 /* initialize the threads-list mutex */
707 pthread_mutex_init(&mutex_threads_list, NULL);
709 #if !defined(HAVE___THREAD)
710 pthread_key_create(&threads_current_threadobject_key, NULL);
713 /* threads_sem_init(&suspend_ack, 0, 0); */
717 /* threads_list_lock ***********************************************************
719 Enter the threads table mutex.
721 NOTE: We need this function as we can't use an internal lock for
722 the threads lists because the thread's lock is initialized in
723 threads_table_add (when we have the thread index), but we
724 already need the lock at the entry of the function.
726 *******************************************************************************/
728 void threads_list_lock(void)
730 if (pthread_mutex_lock(&mutex_threads_list) != 0)
731 vm_abort("threads_list_lock: pthread_mutex_lock failed: %s",
736 /* threads_list_unlock *********************************************************
738 Leave the threads list mutex.
740 *******************************************************************************/
742 void threads_list_unlock(void)
744 if (pthread_mutex_unlock(&mutex_threads_list) != 0)
745 vm_abort("threads_list_unlock: pthread_mutex_unlock failed: %s",
750 /* threads_mutex_join_lock *****************************************************
752 Enter the join mutex.
754 *******************************************************************************/
756 void threads_mutex_join_lock(void)
758 if (pthread_mutex_lock(&mutex_join) != 0)
759 vm_abort("threads_mutex_join_lock: pthread_mutex_lock failed: %s",
764 /* threads_mutex_join_unlock ***************************************************
766 Leave the join mutex.
768 *******************************************************************************/
770 void threads_mutex_join_unlock(void)
772 if (pthread_mutex_unlock(&mutex_join) != 0)
773 vm_abort("threads_mutex_join_unlock: pthread_mutex_unlock failed: %s",
778 /* threads_init ****************************************************************
780 Initializes the threads required by the JVM: main, finalizer.
782 *******************************************************************************/
784 bool threads_init(void)
786 threadobject *mainthread;
787 java_objectheader *threadname;
789 java_objectheader *o;
791 #if defined(ENABLE_JAVASE)
792 java_lang_ThreadGroup *threadgroup;
796 #if defined(WITH_CLASSPATH_GNU)
797 java_lang_VMThread *vmt;
802 /* get methods we need in this file */
804 #if defined(WITH_CLASSPATH_GNU)
806 class_resolveclassmethod(class_java_lang_Thread,
808 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
809 class_java_lang_Thread,
813 class_resolveclassmethod(class_java_lang_Thread,
815 utf_new_char("(Ljava/lang/String;)V"),
816 class_java_lang_Thread,
820 if (method_thread_init == NULL)
823 /* Get the main-thread (NOTE: The main threads is always the first
824 thread in the list). */
826 mainthread = threads_list_first();
828 /* create a java.lang.Thread for the main thread */
830 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
835 /* set the object in the internal data structure */
837 mainthread->object = t;
839 #if defined(ENABLE_INTRP)
840 /* create interpreter stack */
843 MSET(intrp_main_stack, 0, u1, opt_stacksize);
844 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
848 threadname = javastring_new(utf_new_char("main"));
850 #if defined(ENABLE_JAVASE)
851 /* allocate and init ThreadGroup */
853 threadgroup = (java_lang_ThreadGroup *)
854 native_new_and_init(class_java_lang_ThreadGroup);
856 if (threadgroup == NULL)
860 #if defined(WITH_CLASSPATH_GNU)
861 /* create a java.lang.VMThread for the main thread */
863 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
871 vmt->vmdata = (java_lang_Object *) mainthread;
873 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
874 o = (java_objectheader *) t;
876 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
879 #elif defined(WITH_CLASSPATH_SUN)
881 /* We trick java.lang.Thread.init, which sets the priority of the
882 current thread to the parent's one. */
884 t->priority = NORM_PRIORITY;
886 #elif defined(WITH_CLASSPATH_CLDC1_1)
890 t->vm_thread = (java_lang_Object *) mainthread;
892 /* call public Thread(String name) */
894 o = (java_objectheader *) t;
896 (void) vm_call_method(method_thread_init, o, threadname);
898 # error unknown classpath configuration
901 if (exceptions_get_exception())
904 #if defined(ENABLE_JAVASE)
905 t->group = threadgroup;
907 # if defined(WITH_CLASSPATH_GNU)
908 /* add main thread to java.lang.ThreadGroup */
910 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
912 utf_java_lang_Thread__V,
913 class_java_lang_ThreadGroup,
916 o = (java_objectheader *) threadgroup;
918 (void) vm_call_method(m, o, t);
920 if (exceptions_get_exception())
923 # warning Do not know what to do here
927 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
929 /* initialize the thread attribute object */
931 if (pthread_attr_init(&attr) != 0)
932 vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
934 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
935 vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
939 if (opt_verbosethreads) {
940 printf("[Starting thread ");
941 threads_thread_print_info(mainthread);
946 /* everything's ok */
952 /* threads_startup_thread ******************************************************
954 Thread startup function called by pthread_create.
956 Thread which have a startup.function != NULL are marked as internal
957 threads. All other threads are threated as normal Java threads.
959 NOTE: This function is not called directly by pthread_create. The Boehm GC
960 inserts its own GC_start_routine in between, which then calls
964 arg..........the argument passed to pthread_create, ie. a pointer to
965 a startupinfo struct. CAUTION: When the `psem` semaphore
966 is posted, the startupinfo struct becomes invalid! (It
967 is allocated on the stack of threads_start_thread.)
969 ******************************************************************************/
971 static void *threads_startup_thread(void *arg)
973 startupinfo *startup;
974 threadobject *thread;
975 #if defined(WITH_CLASSPATH_GNU)
976 java_lang_VMThread *vmt;
981 java_objectheader *o;
982 functionptr function;
984 #if defined(ENABLE_INTRP)
985 u1 *intrp_thread_stack;
987 /* create interpreter stack */
990 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
991 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
994 intrp_thread_stack = NULL;
997 /* get passed startupinfo structure and the values in there */
1001 thread = startup->thread;
1002 function = startup->function;
1003 psem = startup->psem;
1005 /* Seems like we've encountered a situation where thread->tid was
1006 not set by pthread_create. We alleviate this problem by waiting
1007 for pthread_create to return. */
1009 threads_sem_wait(startup->psem_first);
1011 #if defined(__DARWIN__)
1012 thread->mach_thread = mach_thread_self();
1015 /* store the internal thread data-structure in the TSD */
1017 threads_set_current_threadobject(thread);
1019 /* set our priority */
1021 threads_set_thread_priority(thread->tid, thread->object->priority);
1023 /* thread is completely initialized */
1025 threads_thread_state_runnable(thread);
1027 /* tell threads_startup_thread that we registered ourselves */
1028 /* CAUTION: *startup becomes invalid with this! */
1031 threads_sem_post(psem);
1033 #if defined(ENABLE_INTRP)
1034 /* set interpreter stack */
1037 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1040 #if defined(ENABLE_JVMTI)
1041 /* fire thread start event */
1044 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1047 #if !defined(NDEBUG)
1048 if (opt_verbosethreads) {
1049 printf("[Starting thread ");
1050 threads_thread_print_info(thread);
1055 /* find and run the Thread.run()V method if no other function was passed */
1057 if (function == NULL) {
1058 #if defined(WITH_CLASSPATH_GNU)
1059 /* We need to start the run method of
1060 java.lang.VMThread. Since this is a final class, we can use
1061 the class object directly. */
1063 c = class_java_lang_VMThread;
1064 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1065 c = thread->object->header.vftbl->class;
1067 # error unknown classpath configuration
1070 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1073 vm_abort("threads_startup_thread: run() method not found in class");
1075 /* set ThreadMXBean variables */
1077 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1078 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1080 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1081 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1082 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1083 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1085 #if defined(WITH_CLASSPATH_GNU)
1086 /* we need to start the run method of java.lang.VMThread */
1088 vmt = (java_lang_VMThread *) thread->object->vmThread;
1089 o = (java_objectheader *) vmt;
1091 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1092 o = (java_objectheader *) thread->object;
1094 # error unknown classpath configuration
1097 /* run the thread */
1099 (void) vm_call_method(m, o);
1102 /* set ThreadMXBean variables */
1104 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1105 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1107 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1108 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1109 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1110 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1112 /* call passed function, e.g. finalizer_thread */
1117 #if !defined(NDEBUG)
1118 if (opt_verbosethreads) {
1119 printf("[Stopping thread ");
1120 threads_thread_print_info(thread);
1125 #if defined(ENABLE_JVMTI)
1126 /* fire thread end event */
1129 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1132 if (!threads_detach_thread(thread))
1133 vm_abort("threads_startup_thread: threads_detach_thread failed");
1135 /* set ThreadMXBean variables */
1137 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1143 /* threads_impl_thread_start ***************************************************
1145 Start a thread in the JVM. Both (vm internal and java) thread
1149 thread....the thread object
1150 f.........function to run in the new thread. NULL means that the
1151 "run" method of the object `t` should be called
1153 ******************************************************************************/
1155 void threads_impl_thread_start(threadobject *thread, functionptr f)
1159 pthread_attr_t attr;
1160 startupinfo startup;
1163 /* fill startupinfo structure passed by pthread_create to
1164 * threads_startup_thread */
1166 startup.thread = thread;
1167 startup.function = f; /* maybe we don't call Thread.run()V */
1168 startup.psem = &sem;
1169 startup.psem_first = &sem_first;
1171 threads_sem_init(&sem, 0, 0);
1172 threads_sem_init(&sem_first, 0, 0);
1174 /* initialize thread attributes */
1176 if (pthread_attr_init(&attr) != 0)
1177 vm_abort("threads_impl_thread_start: pthread_attr_init failed: %s",
1180 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
1181 vm_abort("threads_impl_thread_start: pthread_attr_setdetachstate failed: %s",
1184 /* initialize thread stacksize */
1186 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1187 vm_abort("threads_impl_thread_start: pthread_attr_setstacksize failed: %s",
1190 /* create the thread */
1192 ret = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1194 /* destroy the thread attributes */
1196 if (pthread_attr_destroy(&attr) != 0)
1197 vm_abort("threads_impl_thread_start: pthread_attr_destroy failed: %s",
1200 /* check for pthread_create error */
1203 vm_abort("threads_impl_thread_start: pthread_create failed: %s",
1206 /* signal that pthread_create has returned, so thread->tid is valid */
1208 threads_sem_post(&sem_first);
1210 /* wait here until the thread has entered itself into the thread list */
1212 threads_sem_wait(&sem);
1217 sem_destroy(&sem_first);
1221 /* threads_set_thread_priority *************************************************
1223 Set the priority of the given thread.
1226 tid..........thread id
1227 priority.....priority to set
1229 ******************************************************************************/
1231 void threads_set_thread_priority(pthread_t tid, int priority)
1233 struct sched_param schedp;
1236 pthread_getschedparam(tid, &policy, &schedp);
1237 schedp.sched_priority = priority;
1238 pthread_setschedparam(tid, policy, &schedp);
1242 /* threads_attach_current_thread ***********************************************
1244 Attaches the current thread to the VM. Used in JNI.
1246 *******************************************************************************/
1248 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1250 threadobject *thread;
1252 java_objectheader *s;
1253 java_objectheader *o;
1254 java_lang_Thread *t;
1256 #if defined(ENABLE_JAVASE)
1257 java_lang_ThreadGroup *group;
1258 threadobject *mainthread;
1262 #if defined(WITH_CLASSPATH_GNU)
1263 java_lang_VMThread *vmt;
1266 /* Enter the join-mutex, so if the main-thread is currently
1267 waiting to join all threads, the number of non-daemon threads
1270 threads_mutex_join_lock();
1272 /* create internal thread data-structure */
1274 thread = threads_thread_new();
1276 /* thread is a Java thread and running */
1278 thread->flags = THREAD_FLAG_JAVA;
1281 thread->flags |= THREAD_FLAG_DAEMON;
1283 /* The thread is flagged and (non-)daemon thread, we can leave the
1286 threads_mutex_join_unlock();
1288 /* create a java.lang.Thread object */
1290 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1292 /* XXX memory leak!!! */
1298 /* thread is completely initialized */
1300 threads_thread_state_runnable(thread);
1302 #if !defined(NDEBUG)
1303 if (opt_verbosethreads) {
1304 printf("[Attaching thread ");
1305 threads_thread_print_info(thread);
1310 #if defined(ENABLE_INTRP)
1311 /* create interpreter stack */
1314 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1315 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1319 #if defined(WITH_CLASSPATH_GNU)
1321 /* create a java.lang.VMThread object */
1323 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1325 /* XXX memory leak!!! */
1329 /* set the thread */
1332 vmt->vmdata = (java_lang_Object *) thread;
1334 #elif defined(WITH_CLASSPATH_SUN)
1336 vm_abort("threads_attach_current_thread: IMPLEMENT ME!");
1338 #elif defined(WITH_CLASSPATH_CLDC1_1)
1340 t->vm_thread = (java_lang_Object *) thread;
1343 # error unknown classpath configuration
1346 if (vm_aargs != NULL) {
1347 u = utf_new_char(vm_aargs->name);
1348 #if defined(ENABLE_JAVASE)
1349 group = (java_lang_ThreadGroup *) vm_aargs->group;
1354 #if defined(ENABLE_JAVASE)
1355 /* get the main thread */
1357 mainthread = threads_list_first();
1358 group = mainthread->object->group;
1362 /* the the thread name */
1364 s = javastring_new(u);
1366 /* for convenience */
1368 o = (java_objectheader *) thread->object;
1370 #if defined(WITH_CLASSPATH_GNU)
1371 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1373 #elif defined(WITH_CLASSPATH_CLDC1_1)
1374 (void) vm_call_method(method_thread_init, o, s);
1377 if (exceptions_get_exception())
1380 #if defined(ENABLE_JAVASE)
1381 /* store the thread group in the object */
1383 thread->object->group = group;
1385 /* add thread to given thread-group */
1387 m = class_resolveclassmethod(group->header.vftbl->class,
1389 utf_java_lang_Thread__V,
1390 class_java_lang_ThreadGroup,
1393 o = (java_objectheader *) group;
1395 (void) vm_call_method(m, o, t);
1397 if (exceptions_get_exception())
1405 /* threads_detach_thread *******************************************************
1407 Detaches the passed thread from the VM. Used in JNI.
1409 *******************************************************************************/
1411 bool threads_detach_thread(threadobject *thread)
1413 #if defined(ENABLE_JAVASE)
1414 java_lang_ThreadGroup *group;
1416 java_objectheader *o;
1417 java_lang_Thread *t;
1420 /* XXX implement uncaught exception stuff (like JamVM does) */
1422 #if defined(ENABLE_JAVASE)
1423 /* remove thread from the thread group */
1425 group = thread->object->group;
1427 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1429 if (group != NULL) {
1430 # if defined(WITH_CLASSPATH_GNU)
1431 m = class_resolveclassmethod(group->header.vftbl->class,
1433 utf_java_lang_Thread__V,
1434 class_java_lang_ThreadGroup,
1436 # elif defined(WITH_CLASSPATH_SUN)
1437 m = class_resolveclassmethod(group->header.vftbl->class,
1439 utf_java_lang_Thread__V,
1440 class_java_lang_ThreadGroup,
1443 # error unknown classpath configuration
1449 o = (java_objectheader *) group;
1452 (void) vm_call_method(m, o, t);
1454 if (exceptions_get_exception())
1459 /* thread is terminated */
1461 threads_thread_state_terminated(thread);
1463 #if !defined(NDEBUG)
1464 if (opt_verbosethreads) {
1465 printf("[Detaching thread ");
1466 threads_thread_print_info(thread);
1471 /* Enter the join-mutex before calling threads_thread_free, so
1472 threads_join_all_threads gets the correct number of non-daemon
1475 threads_mutex_join_lock();
1477 /* free the vm internal thread object */
1479 threads_thread_free(thread);
1481 /* Signal that this thread has finished and leave the mutex. */
1483 pthread_cond_signal(&cond_join);
1484 threads_mutex_join_unlock();
1490 /* threads_join_all_threads ****************************************************
1492 Join all non-daemon threads.
1494 *******************************************************************************/
1496 void threads_join_all_threads(void)
1500 /* get current thread */
1504 /* this thread is waiting for all non-daemon threads to exit */
1506 threads_thread_state_waiting(t);
1508 /* enter join mutex */
1510 threads_mutex_join_lock();
1512 /* Wait for condition as long as we have non-daemon threads. We
1513 compare against 1 because the current (main thread) is also a
1514 non-daemon thread. */
1516 while (threads_list_get_non_daemons() > 1)
1517 pthread_cond_wait(&cond_join, &mutex_join);
1519 /* leave join mutex */
1521 threads_mutex_join_unlock();
1525 /* threads_timespec_earlier ****************************************************
1527 Return true if timespec tv1 is earlier than timespec tv2.
1530 tv1..........first timespec
1531 tv2..........second timespec
1534 true, if the first timespec is earlier
1536 *******************************************************************************/
1538 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1539 const struct timespec *tv2)
1541 return (tv1->tv_sec < tv2->tv_sec)
1543 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1547 /* threads_current_time_is_earlier_than ****************************************
1549 Check if the current time is earlier than the given timespec.
1552 tv...........the timespec to compare against
1555 true, if the current time is earlier
1557 *******************************************************************************/
1559 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1561 struct timeval tvnow;
1562 struct timespec tsnow;
1564 /* get current time */
1566 if (gettimeofday(&tvnow, NULL) != 0)
1567 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1569 /* convert it to a timespec */
1571 tsnow.tv_sec = tvnow.tv_sec;
1572 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1574 /* compare current time with the given timespec */
1576 return threads_timespec_earlier(&tsnow, tv);
1580 /* threads_wait_with_timeout ***************************************************
1582 Wait until the given point in time on a monitor until either
1583 we are notified, we are interrupted, or the time is up.
1586 t............the current thread
1587 wakeupTime...absolute (latest) wakeup time
1588 If both tv_sec and tv_nsec are zero, this function
1589 waits for an unlimited amount of time.
1592 true.........if the wait has been interrupted,
1593 false........if the wait was ended by notification or timeout
1595 *******************************************************************************/
1597 static bool threads_wait_with_timeout(threadobject *thread,
1598 struct timespec *wakeupTime)
1600 bool wasinterrupted;
1602 /* acquire the waitmutex */
1604 pthread_mutex_lock(&thread->waitmutex);
1606 /* mark us as sleeping */
1608 thread->sleeping = true;
1610 /* wait on waitcond */
1612 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1614 while (!thread->interrupted && !thread->signaled
1615 && threads_current_time_is_earlier_than(wakeupTime))
1617 threads_thread_state_timed_waiting(thread);
1619 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1622 threads_thread_state_runnable(thread);
1627 while (!thread->interrupted && !thread->signaled) {
1628 threads_thread_state_waiting(thread);
1630 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1632 threads_thread_state_runnable(thread);
1636 /* check if we were interrupted */
1638 wasinterrupted = thread->interrupted;
1640 /* reset all flags */
1642 thread->interrupted = false;
1643 thread->signaled = false;
1644 thread->sleeping = false;
1646 /* release the waitmutex */
1648 pthread_mutex_unlock(&thread->waitmutex);
1650 return wasinterrupted;
1654 /* threads_wait_with_timeout_relative ******************************************
1656 Wait for the given maximum amount of time on a monitor until either
1657 we are notified, we are interrupted, or the time is up.
1660 t............the current thread
1661 millis.......milliseconds to wait
1662 nanos........nanoseconds to wait
1665 true.........if the wait has been interrupted,
1666 false........if the wait was ended by notification or timeout
1668 *******************************************************************************/
1670 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1673 struct timespec wakeupTime;
1675 /* calculate the the (latest) wakeup time */
1677 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1681 return threads_wait_with_timeout(thread, &wakeupTime);
1685 /* threads_calc_absolute_time **************************************************
1687 Calculate the absolute point in time a given number of ms and ns from now.
1690 millis............milliseconds from now
1691 nanos.............nanoseconds from now
1694 *tm...............receives the timespec of the absolute point in time
1696 *******************************************************************************/
1698 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1700 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1703 gettimeofday(&tv, NULL);
1704 tv.tv_sec += millis / 1000;
1706 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1707 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1708 tm->tv_nsec = nsec % 1000000000;
1717 /* threads_thread_interrupt ****************************************************
1719 Interrupt the given thread.
1721 The thread gets the "waitcond" signal and
1722 its interrupted flag is set to true.
1725 thread............the thread to interrupt
1727 *******************************************************************************/
1729 void threads_thread_interrupt(threadobject *thread)
1731 /* Signal the thread a "waitcond" and tell it that it has been
1734 pthread_mutex_lock(&thread->waitmutex);
1736 /* Interrupt blocking system call using a signal. */
1738 pthread_kill(thread->tid, SIGHUP);
1740 if (thread->sleeping)
1741 pthread_cond_signal(&thread->waitcond);
1743 thread->interrupted = true;
1745 pthread_mutex_unlock(&thread->waitmutex);
1749 /* threads_check_if_interrupted_and_reset **************************************
1751 Check if the current thread has been interrupted and reset the
1755 true, if the current thread had been interrupted
1757 *******************************************************************************/
1759 bool threads_check_if_interrupted_and_reset(void)
1761 threadobject *thread;
1764 thread = THREADOBJECT;
1766 /* get interrupted flag */
1768 intr = thread->interrupted;
1770 /* reset interrupted flag */
1772 thread->interrupted = false;
1778 /* threads_thread_has_been_interrupted *****************************************
1780 Check if the given thread has been interrupted
1783 t............the thread to check
1786 true, if the given thread had been interrupted
1788 *******************************************************************************/
1790 bool threads_thread_has_been_interrupted(threadobject *thread)
1792 return thread->interrupted;
1796 /* threads_sleep ***************************************************************
1798 Sleep the current thread for the specified amount of time.
1800 *******************************************************************************/
1802 void threads_sleep(s8 millis, s4 nanos)
1804 threadobject *thread;
1805 struct timespec wakeupTime;
1806 bool wasinterrupted;
1808 thread = THREADOBJECT;
1810 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1812 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1815 exceptions_throw_interruptedexception();
1819 /* threads_yield ***************************************************************
1821 Yield to the scheduler.
1823 *******************************************************************************/
1825 void threads_yield(void)
1832 * These are local overrides for various environment variables in Emacs.
1833 * Please do not remove this and leave it at the end of the file, where
1834 * Emacs will automagically detect them.
1835 * ---------------------------------------------------------------------
1838 * indent-tabs-mode: t
1842 * vim:noexpandtab:sw=4:ts=4: