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 8304 2007-08-14 19:57:20Z pm $
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/llni.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Object.h"
63 #include "native/include/java_lang_String.h"
64 #include "native/include/java_lang_Throwable.h"
65 #include "native/include/java_lang_Thread.h"
67 #if defined(ENABLE_JAVASE)
68 # include "native/include/java_lang_ThreadGroup.h"
71 #if defined(WITH_CLASSPATH_GNU)
72 # include "native/include/java_lang_VMThread.h"
75 #include "threads/lock-common.h"
76 #include "threads/threads-common.h"
78 #include "threads/native/threads.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_list;
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 /* XXX We disable that whole bunch of code until we have the exact-GC
245 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
247 static volatile int stopworldwhere;
249 /* semaphore used for acknowleding thread suspension */
250 static sem_t suspend_ack;
251 #if defined(__MIPS__)
252 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
253 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
258 /* mutexes used by the fake atomic instructions */
259 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
260 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
261 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
262 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
266 /* threads_sem_init ************************************************************
268 Initialize a semaphore. Checks against errors and interruptions.
271 sem..............the semaphore to initialize
272 shared...........true if this semaphore will be shared between processes
273 value............the initial value for the semaphore
275 *******************************************************************************/
277 void threads_sem_init(sem_t *sem, bool shared, int value)
284 r = sem_init(sem, shared, value);
287 } while (errno == EINTR);
289 vm_abort("sem_init failed: %s", strerror(errno));
293 /* threads_sem_wait ************************************************************
295 Wait for a semaphore, non-interruptible.
297 IMPORTANT: Always use this function instead of `sem_wait` directly, as
298 `sem_wait` may be interrupted by signals!
301 sem..............the semaphore to wait on
303 *******************************************************************************/
305 void threads_sem_wait(sem_t *sem)
315 } while (errno == EINTR);
317 vm_abort("sem_wait failed: %s", strerror(errno));
321 /* threads_sem_post ************************************************************
323 Increase the count of a semaphore. Checks for errors.
326 sem..............the semaphore to increase the count of
328 *******************************************************************************/
330 void threads_sem_post(sem_t *sem)
336 /* unlike sem_wait, sem_post is not interruptible */
342 vm_abort("sem_post failed: %s", strerror(errno));
346 /* lock_stopworld **************************************************************
348 Enter the stopworld lock, specifying why the world shall be stopped.
351 where........ STOPWORLD_FROM_GC (1) from within GC
352 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
354 ******************************************************************************/
356 void lock_stopworld(int where)
358 pthread_mutex_lock(&stopworldlock);
359 /* stopworldwhere = where; */
363 /* unlock_stopworld ************************************************************
365 Release the stopworld lock.
367 ******************************************************************************/
369 void unlock_stopworld(void)
371 /* stopworldwhere = 0; */
372 pthread_mutex_unlock(&stopworldlock);
375 /* XXX We disable that whole bunch of code until we have the exact-GC
380 #if !defined(__DARWIN__)
381 /* Caller must hold threadlistlock */
382 static s4 threads_cast_sendsignals(s4 sig)
390 /* iterate over all started threads */
394 for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
395 /* don't send the signal to ourself */
400 /* don't send the signal to NEW threads (because they are not
401 completely initialized) */
403 if (t->state == THREAD_STATE_NEW)
406 /* send the signal */
408 pthread_kill(t->tid, sig);
410 /* increase threads count */
420 static void threads_cast_darwinstop(void)
422 threadobject *tobj = mainthreadobj;
423 threadobject *self = THREADOBJECT;
428 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
429 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
430 #if defined(__I386__)
431 i386_thread_state_t thread_state;
433 ppc_thread_state_t thread_state;
435 mach_port_t thread = tobj->mach_thread;
438 r = thread_suspend(thread);
440 if (r != KERN_SUCCESS)
441 vm_abort("thread_suspend failed");
443 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
444 &thread_state_count);
446 if (r != KERN_SUCCESS)
447 vm_abort("thread_get_state failed");
449 md_critical_section_restart((ucontext_t *) &thread_state);
451 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
454 if (r != KERN_SUCCESS)
455 vm_abort("thread_set_state failed");
459 } while (tobj != mainthreadobj);
462 static void threads_cast_darwinresume(void)
464 threadobject *tobj = mainthreadobj;
465 threadobject *self = THREADOBJECT;
470 mach_port_t thread = tobj->mach_thread;
473 r = thread_resume(thread);
475 if (r != KERN_SUCCESS)
476 vm_abort("thread_resume failed");
480 } while (tobj != mainthreadobj);
485 #if defined(__MIPS__)
486 static void threads_cast_irixresume(void)
488 pthread_mutex_lock(&suspend_ack_lock);
489 pthread_cond_broadcast(&suspend_cond);
490 pthread_mutex_unlock(&suspend_ack_lock);
494 #if !defined(DISABLE_GC)
496 void threads_cast_stopworld(void)
498 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
502 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
504 /* lock the threads lists */
508 #if defined(__DARWIN__)
509 threads_cast_darwinstop();
510 #elif defined(__CYGWIN__)
514 /* send all threads the suspend signal */
516 count = threads_cast_sendsignals(GC_signum1());
518 /* wait for all threads signaled to suspend */
520 for (i = 0; i < count; i++)
521 threads_sem_wait(&suspend_ack);
524 /* ATTENTION: Don't unlock the threads-lists here so that
525 non-signaled NEW threads can't change their state and execute
530 void threads_cast_startworld(void)
532 #if defined(__DARWIN__)
533 threads_cast_darwinresume();
534 #elif defined(__MIPS__)
535 threads_cast_irixresume();
536 #elif defined(__CYGWIN__)
540 (void) threads_cast_sendsignals(GC_signum2());
543 /* unlock the threads lists */
545 threads_list_unlock();
551 #if !defined(__DARWIN__)
552 static void threads_sigsuspend_handler(ucontext_t *_uc)
557 /* XXX TWISTI: this is just a quick hack */
558 #if defined(ENABLE_JIT)
559 md_critical_section_restart(_uc);
562 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
563 (not POSIX async-safe). */
564 #if defined(__IRIX__)
565 pthread_mutex_lock(&suspend_ack_lock);
566 threads_sem_post(&suspend_ack);
567 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
568 pthread_mutex_unlock(&suspend_ack_lock);
569 #elif defined(__CYGWIN__)
573 threads_sem_post(&suspend_ack);
577 sigdelset(&sigs, sig);
585 /* This function is called from Boehm GC code. */
587 int cacao_suspendhandler(ucontext_t *_uc)
589 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
592 threads_sigsuspend_handler(_uc);
596 #endif /* DISABLE_GC */
601 /* threads_set_current_threadobject ********************************************
603 Set the current thread object.
606 thread.......the thread object to set
608 *******************************************************************************/
610 void threads_set_current_threadobject(threadobject *thread)
612 #if !defined(HAVE___THREAD)
613 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
614 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
616 threads_current_threadobject = thread;
621 /* threads_impl_thread_new *****************************************************
623 Initialize implementation fields of a threadobject.
626 t....the threadobject
628 *******************************************************************************/
630 void threads_impl_thread_new(threadobject *t)
632 /* get the pthread id */
634 t->tid = pthread_self();
636 /* initialize the mutex and the condition */
638 pthread_mutex_init(&(t->waitmutex), NULL);
639 pthread_cond_init(&(t->waitcond), NULL);
641 #if defined(ENABLE_DEBUG_FILTER)
642 /* Initialize filter counters */
643 t->filterverbosecallctr[0] = 0;
644 t->filterverbosecallctr[1] = 0;
648 t->tracejavacallindent = 0;
649 t->tracejavacallcount = 0;
654 /* threads_impl_thread_free ****************************************************
656 Cleanup thread stuff.
659 t....the threadobject
661 *******************************************************************************/
663 void threads_impl_thread_free(threadobject *t)
665 /* destroy the mutex and the condition */
667 if (pthread_mutex_destroy(&(t->waitmutex)) != 0)
668 vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
671 if (pthread_cond_destroy(&(t->waitcond)) != 0)
672 vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
677 /* threads_get_current_threadobject ********************************************
679 Return the threadobject of the current thread.
682 the current threadobject * (an instance of java.lang.Thread)
684 *******************************************************************************/
686 threadobject *threads_get_current_threadobject(void)
692 /* threads_impl_preinit ********************************************************
694 Do some early initialization of stuff required.
696 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
697 is called AFTER this function!
699 *******************************************************************************/
701 void threads_impl_preinit(void)
703 pthread_mutex_init(&stopworldlock, NULL);
705 /* initialize exit mutex and condition (on exit we join all
708 pthread_mutex_init(&mutex_join, NULL);
709 pthread_cond_init(&cond_join, NULL);
711 /* initialize the threads-list mutex */
713 pthread_mutex_init(&mutex_threads_list, NULL);
715 #if !defined(HAVE___THREAD)
716 pthread_key_create(&threads_current_threadobject_key, NULL);
719 /* threads_sem_init(&suspend_ack, 0, 0); */
723 /* threads_list_lock ***********************************************************
725 Enter the threads table mutex.
727 NOTE: We need this function as we can't use an internal lock for
728 the threads lists because the thread's lock is initialized in
729 threads_table_add (when we have the thread index), but we
730 already need the lock at the entry of the function.
732 *******************************************************************************/
734 void threads_list_lock(void)
736 if (pthread_mutex_lock(&mutex_threads_list) != 0)
737 vm_abort("threads_list_lock: pthread_mutex_lock failed: %s",
742 /* threads_list_unlock *********************************************************
744 Leave the threads list mutex.
746 *******************************************************************************/
748 void threads_list_unlock(void)
750 if (pthread_mutex_unlock(&mutex_threads_list) != 0)
751 vm_abort("threads_list_unlock: pthread_mutex_unlock failed: %s",
756 /* threads_mutex_join_lock *****************************************************
758 Enter the join mutex.
760 *******************************************************************************/
762 void threads_mutex_join_lock(void)
764 if (pthread_mutex_lock(&mutex_join) != 0)
765 vm_abort("threads_mutex_join_lock: pthread_mutex_lock failed: %s",
770 /* threads_mutex_join_unlock ***************************************************
772 Leave the join mutex.
774 *******************************************************************************/
776 void threads_mutex_join_unlock(void)
778 if (pthread_mutex_unlock(&mutex_join) != 0)
779 vm_abort("threads_mutex_join_unlock: pthread_mutex_unlock failed: %s",
784 /* threads_init ****************************************************************
786 Initializes the threads required by the JVM: main, finalizer.
788 *******************************************************************************/
790 bool threads_init(void)
792 threadobject *mainthread;
793 java_handle_t *threadname;
797 #if defined(ENABLE_JAVASE)
798 java_lang_ThreadGroup *threadgroup;
802 #if defined(WITH_CLASSPATH_GNU)
803 java_lang_VMThread *vmt;
808 /* get methods we need in this file */
810 #if defined(WITH_CLASSPATH_GNU)
812 class_resolveclassmethod(class_java_lang_Thread,
814 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
815 class_java_lang_Thread,
819 class_resolveclassmethod(class_java_lang_Thread,
821 utf_new_char("(Ljava/lang/String;)V"),
822 class_java_lang_Thread,
826 if (method_thread_init == NULL)
829 /* Get the main-thread (NOTE: The main threads is always the first
830 thread in the list). */
832 mainthread = threads_list_first();
834 /* create a java.lang.Thread for the main thread */
836 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
841 /* set the object in the internal data structure */
843 mainthread->object = t;
845 #if defined(ENABLE_INTRP)
846 /* create interpreter stack */
849 MSET(intrp_main_stack, 0, u1, opt_stacksize);
850 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
854 threadname = javastring_new(utf_new_char("main"));
856 #if defined(ENABLE_JAVASE)
857 /* allocate and init ThreadGroup */
859 threadgroup = (java_lang_ThreadGroup *)
860 native_new_and_init(class_java_lang_ThreadGroup);
862 if (threadgroup == NULL)
866 #if defined(WITH_CLASSPATH_GNU)
867 /* create a java.lang.VMThread for the main thread */
869 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
876 LLNI_field_set_ref(vmt, thread, t);
877 LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) mainthread);
879 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
880 o = (java_handle_t *) t;
882 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
885 #elif defined(WITH_CLASSPATH_SUN)
887 /* We trick java.lang.Thread.init, which sets the priority of the
888 current thread to the parent's one. */
890 t->priority = NORM_PRIORITY;
892 #elif defined(WITH_CLASSPATH_CLDC1_1)
896 t->vm_thread = (java_lang_Object *) mainthread;
898 /* call public Thread(String name) */
900 o = (java_handle_t *) t;
902 (void) vm_call_method(method_thread_init, o, threadname);
904 # error unknown classpath configuration
907 if (exceptions_get_exception())
910 #if defined(ENABLE_JAVASE)
911 LLNI_field_set_ref(t, group, threadgroup);
913 # if defined(WITH_CLASSPATH_GNU)
914 /* add main thread to java.lang.ThreadGroup */
916 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
918 utf_java_lang_Thread__V,
919 class_java_lang_ThreadGroup,
922 o = (java_handle_t *) threadgroup;
924 (void) vm_call_method(m, o, t);
926 if (exceptions_get_exception())
929 # warning Do not know what to do here
933 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
935 /* initialize the thread attribute object */
937 if (pthread_attr_init(&attr) != 0)
938 vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
940 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
941 vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
945 if (opt_verbosethreads) {
946 printf("[Starting thread ");
947 threads_thread_print_info(mainthread);
952 /* everything's ok */
958 /* threads_startup_thread ******************************************************
960 Thread startup function called by pthread_create.
962 Thread which have a startup.function != NULL are marked as internal
963 threads. All other threads are threated as normal Java threads.
965 NOTE: This function is not called directly by pthread_create. The Boehm GC
966 inserts its own GC_start_routine in between, which then calls
970 arg..........the argument passed to pthread_create, ie. a pointer to
971 a startupinfo struct. CAUTION: When the `psem` semaphore
972 is posted, the startupinfo struct becomes invalid! (It
973 is allocated on the stack of threads_start_thread.)
975 ******************************************************************************/
977 static void *threads_startup_thread(void *arg)
979 startupinfo *startup;
980 threadobject *thread;
981 #if defined(WITH_CLASSPATH_GNU)
982 java_lang_VMThread *vmt;
988 functionptr function;
990 #if defined(ENABLE_INTRP)
991 u1 *intrp_thread_stack;
993 /* create interpreter stack */
996 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
997 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1000 intrp_thread_stack = NULL;
1003 /* get passed startupinfo structure and the values in there */
1007 thread = startup->thread;
1008 function = startup->function;
1009 psem = startup->psem;
1011 /* Seems like we've encountered a situation where thread->tid was
1012 not set by pthread_create. We alleviate this problem by waiting
1013 for pthread_create to return. */
1015 threads_sem_wait(startup->psem_first);
1017 #if defined(__DARWIN__)
1018 thread->mach_thread = mach_thread_self();
1021 /* store the internal thread data-structure in the TSD */
1023 threads_set_current_threadobject(thread);
1025 /* set our priority */
1027 threads_set_thread_priority(thread->tid, LLNI_field_direct(thread->object, priority));
1029 /* thread is completely initialized */
1031 threads_thread_state_runnable(thread);
1033 /* tell threads_startup_thread that we registered ourselves */
1034 /* CAUTION: *startup becomes invalid with this! */
1037 threads_sem_post(psem);
1039 #if defined(ENABLE_INTRP)
1040 /* set interpreter stack */
1043 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1046 #if defined(ENABLE_JVMTI)
1047 /* fire thread start event */
1050 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1053 #if !defined(NDEBUG)
1054 if (opt_verbosethreads) {
1055 printf("[Starting thread ");
1056 threads_thread_print_info(thread);
1061 /* find and run the Thread.run()V method if no other function was passed */
1063 if (function == NULL) {
1064 #if defined(WITH_CLASSPATH_GNU)
1065 /* We need to start the run method of
1066 java.lang.VMThread. Since this is a final class, we can use
1067 the class object directly. */
1069 c = class_java_lang_VMThread;
1070 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1071 c = thread->object->header.vftbl->class;
1073 # error unknown classpath configuration
1076 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1079 vm_abort("threads_startup_thread: run() method not found in class");
1081 /* set ThreadMXBean variables */
1083 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1084 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1086 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1087 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1088 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1089 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1091 #if defined(WITH_CLASSPATH_GNU)
1092 /* we need to start the run method of java.lang.VMThread */
1094 vmt = (java_lang_VMThread *) LLNI_field_direct(thread->object, vmThread);
1095 o = (java_handle_t *) vmt;
1097 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1098 o = (java_handle_t *) thread->object;
1100 # error unknown classpath configuration
1103 /* run the thread */
1105 (void) vm_call_method(m, o);
1108 /* set ThreadMXBean variables */
1110 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1111 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1113 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1114 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1115 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1116 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1118 /* call passed function, e.g. finalizer_thread */
1123 #if !defined(NDEBUG)
1124 if (opt_verbosethreads) {
1125 printf("[Stopping thread ");
1126 threads_thread_print_info(thread);
1131 #if defined(ENABLE_JVMTI)
1132 /* fire thread end event */
1135 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1138 if (!threads_detach_thread(thread))
1139 vm_abort("threads_startup_thread: threads_detach_thread failed");
1141 /* set ThreadMXBean variables */
1143 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1149 /* threads_impl_thread_start ***************************************************
1151 Start a thread in the JVM. Both (vm internal and java) thread
1155 thread....the thread object
1156 f.........function to run in the new thread. NULL means that the
1157 "run" method of the object `t` should be called
1159 ******************************************************************************/
1161 void threads_impl_thread_start(threadobject *thread, functionptr f)
1165 pthread_attr_t attr;
1166 startupinfo startup;
1169 /* fill startupinfo structure passed by pthread_create to
1170 * threads_startup_thread */
1172 startup.thread = thread;
1173 startup.function = f; /* maybe we don't call Thread.run()V */
1174 startup.psem = &sem;
1175 startup.psem_first = &sem_first;
1177 threads_sem_init(&sem, 0, 0);
1178 threads_sem_init(&sem_first, 0, 0);
1180 /* initialize thread attributes */
1182 if (pthread_attr_init(&attr) != 0)
1183 vm_abort("threads_impl_thread_start: pthread_attr_init failed: %s",
1186 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
1187 vm_abort("threads_impl_thread_start: pthread_attr_setdetachstate failed: %s",
1190 /* initialize thread stacksize */
1192 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1193 vm_abort("threads_impl_thread_start: pthread_attr_setstacksize failed: %s",
1196 /* create the thread */
1198 ret = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1200 /* destroy the thread attributes */
1202 if (pthread_attr_destroy(&attr) != 0)
1203 vm_abort("threads_impl_thread_start: pthread_attr_destroy failed: %s",
1206 /* check for pthread_create error */
1209 vm_abort("threads_impl_thread_start: pthread_create failed: %s",
1212 /* signal that pthread_create has returned, so thread->tid is valid */
1214 threads_sem_post(&sem_first);
1216 /* wait here until the thread has entered itself into the thread list */
1218 threads_sem_wait(&sem);
1223 sem_destroy(&sem_first);
1227 /* threads_set_thread_priority *************************************************
1229 Set the priority of the given thread.
1232 tid..........thread id
1233 priority.....priority to set
1235 ******************************************************************************/
1237 void threads_set_thread_priority(pthread_t tid, int priority)
1239 struct sched_param schedp;
1242 pthread_getschedparam(tid, &policy, &schedp);
1243 schedp.sched_priority = priority;
1244 pthread_setschedparam(tid, policy, &schedp);
1248 /* threads_attach_current_thread ***********************************************
1250 Attaches the current thread to the VM. Used in JNI.
1252 *******************************************************************************/
1254 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1256 threadobject *thread;
1260 java_lang_Thread *t;
1262 #if defined(ENABLE_JAVASE)
1263 java_lang_ThreadGroup *group;
1264 threadobject *mainthread;
1269 #if defined(WITH_CLASSPATH_GNU)
1270 java_lang_VMThread *vmt;
1273 /* Enter the join-mutex, so if the main-thread is currently
1274 waiting to join all threads, the number of non-daemon threads
1277 threads_mutex_join_lock();
1279 /* create internal thread data-structure */
1281 thread = threads_thread_new();
1283 /* thread is a Java thread and running */
1285 thread->flags = THREAD_FLAG_JAVA;
1288 thread->flags |= THREAD_FLAG_DAEMON;
1290 /* The thread is flagged and (non-)daemon thread, we can leave the
1293 threads_mutex_join_unlock();
1295 /* create a java.lang.Thread object */
1297 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1299 /* XXX memory leak!!! */
1305 /* thread is completely initialized */
1307 threads_thread_state_runnable(thread);
1309 #if !defined(NDEBUG)
1310 if (opt_verbosethreads) {
1311 printf("[Attaching thread ");
1312 threads_thread_print_info(thread);
1317 #if defined(ENABLE_INTRP)
1318 /* create interpreter stack */
1321 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1322 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1326 #if defined(WITH_CLASSPATH_GNU)
1328 /* create a java.lang.VMThread object */
1330 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1332 /* XXX memory leak!!! */
1336 /* set the thread */
1338 LLNI_field_set_ref(vmt, thread, t);
1339 LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
1341 #elif defined(WITH_CLASSPATH_SUN)
1343 vm_abort("threads_attach_current_thread: IMPLEMENT ME!");
1345 #elif defined(WITH_CLASSPATH_CLDC1_1)
1347 LLNI_field_set_val(t, vm_thread, (java_lang_Object *) thread);
1350 # error unknown classpath configuration
1353 if (vm_aargs != NULL) {
1354 u = utf_new_char(vm_aargs->name);
1355 #if defined(ENABLE_JAVASE)
1356 group = (java_lang_ThreadGroup *) vm_aargs->group;
1361 #if defined(ENABLE_JAVASE)
1362 /* get the main thread */
1364 mainthread = threads_list_first();
1365 group = LLNI_field_direct(mainthread->object, group);
1369 /* the the thread name */
1371 s = javastring_new(u);
1373 /* for convenience */
1375 o = (java_handle_t *) thread->object;
1377 #if defined(WITH_CLASSPATH_GNU)
1378 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1380 #elif defined(WITH_CLASSPATH_CLDC1_1)
1381 (void) vm_call_method(method_thread_init, o, s);
1384 if (exceptions_get_exception())
1387 #if defined(ENABLE_JAVASE)
1388 /* store the thread group in the object */
1390 LLNI_field_direct(thread->object, group) = group;
1392 /* add thread to given thread-group */
1394 LLNI_class_get(group, c);
1396 m = class_resolveclassmethod(c,
1398 utf_java_lang_Thread__V,
1399 class_java_lang_ThreadGroup,
1402 o = (java_handle_t *) group;
1404 (void) vm_call_method(m, o, t);
1406 if (exceptions_get_exception())
1414 /* threads_detach_thread *******************************************************
1416 Detaches the passed thread from the VM. Used in JNI.
1418 *******************************************************************************/
1420 bool threads_detach_thread(threadobject *thread)
1422 #if defined(ENABLE_JAVASE)
1423 java_lang_ThreadGroup *group;
1427 java_lang_Thread *t;
1430 /* XXX implement uncaught exception stuff (like JamVM does) */
1432 #if defined(ENABLE_JAVASE)
1433 /* remove thread from the thread group */
1435 group = LLNI_field_direct(thread->object, group);
1437 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1439 if (group != NULL) {
1440 LLNI_class_get(group, c);
1442 # if defined(WITH_CLASSPATH_GNU)
1443 m = class_resolveclassmethod(c,
1445 utf_java_lang_Thread__V,
1446 class_java_lang_ThreadGroup,
1448 # elif defined(WITH_CLASSPATH_SUN)
1449 m = class_resolveclassmethod(c,
1451 utf_java_lang_Thread__V,
1452 class_java_lang_ThreadGroup,
1455 # error unknown classpath configuration
1461 o = (java_handle_t *) group;
1464 (void) vm_call_method(m, o, t);
1466 if (exceptions_get_exception())
1471 /* thread is terminated */
1473 threads_thread_state_terminated(thread);
1475 #if !defined(NDEBUG)
1476 if (opt_verbosethreads) {
1477 printf("[Detaching thread ");
1478 threads_thread_print_info(thread);
1483 /* Enter the join-mutex before calling threads_thread_free, so
1484 threads_join_all_threads gets the correct number of non-daemon
1487 threads_mutex_join_lock();
1489 /* free the vm internal thread object */
1491 threads_thread_free(thread);
1493 /* Signal that this thread has finished and leave the mutex. */
1495 pthread_cond_signal(&cond_join);
1496 threads_mutex_join_unlock();
1502 /* threads_join_all_threads ****************************************************
1504 Join all non-daemon threads.
1506 *******************************************************************************/
1508 void threads_join_all_threads(void)
1512 /* get current thread */
1516 /* this thread is waiting for all non-daemon threads to exit */
1518 threads_thread_state_waiting(t);
1520 /* enter join mutex */
1522 threads_mutex_join_lock();
1524 /* Wait for condition as long as we have non-daemon threads. We
1525 compare against 1 because the current (main thread) is also a
1526 non-daemon thread. */
1528 while (threads_list_get_non_daemons() > 1)
1529 pthread_cond_wait(&cond_join, &mutex_join);
1531 /* leave join mutex */
1533 threads_mutex_join_unlock();
1537 /* threads_timespec_earlier ****************************************************
1539 Return true if timespec tv1 is earlier than timespec tv2.
1542 tv1..........first timespec
1543 tv2..........second timespec
1546 true, if the first timespec is earlier
1548 *******************************************************************************/
1550 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1551 const struct timespec *tv2)
1553 return (tv1->tv_sec < tv2->tv_sec)
1555 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1559 /* threads_current_time_is_earlier_than ****************************************
1561 Check if the current time is earlier than the given timespec.
1564 tv...........the timespec to compare against
1567 true, if the current time is earlier
1569 *******************************************************************************/
1571 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1573 struct timeval tvnow;
1574 struct timespec tsnow;
1576 /* get current time */
1578 if (gettimeofday(&tvnow, NULL) != 0)
1579 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1581 /* convert it to a timespec */
1583 tsnow.tv_sec = tvnow.tv_sec;
1584 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1586 /* compare current time with the given timespec */
1588 return threads_timespec_earlier(&tsnow, tv);
1592 /* threads_wait_with_timeout ***************************************************
1594 Wait until the given point in time on a monitor until either
1595 we are notified, we are interrupted, or the time is up.
1598 t............the current thread
1599 wakeupTime...absolute (latest) wakeup time
1600 If both tv_sec and tv_nsec are zero, this function
1601 waits for an unlimited amount of time.
1604 true.........if the wait has been interrupted,
1605 false........if the wait was ended by notification or timeout
1607 *******************************************************************************/
1609 static bool threads_wait_with_timeout(threadobject *thread,
1610 struct timespec *wakeupTime)
1612 bool wasinterrupted;
1614 /* acquire the waitmutex */
1616 pthread_mutex_lock(&thread->waitmutex);
1618 /* mark us as sleeping */
1620 thread->sleeping = true;
1622 /* wait on waitcond */
1624 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1626 while (!thread->interrupted && !thread->signaled
1627 && threads_current_time_is_earlier_than(wakeupTime))
1629 threads_thread_state_timed_waiting(thread);
1631 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1634 threads_thread_state_runnable(thread);
1639 while (!thread->interrupted && !thread->signaled) {
1640 threads_thread_state_waiting(thread);
1642 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1644 threads_thread_state_runnable(thread);
1648 /* check if we were interrupted */
1650 wasinterrupted = thread->interrupted;
1652 /* reset all flags */
1654 thread->interrupted = false;
1655 thread->signaled = false;
1656 thread->sleeping = false;
1658 /* release the waitmutex */
1660 pthread_mutex_unlock(&thread->waitmutex);
1662 return wasinterrupted;
1666 /* threads_wait_with_timeout_relative ******************************************
1668 Wait for the given maximum amount of time on a monitor until either
1669 we are notified, we are interrupted, or the time is up.
1672 t............the current thread
1673 millis.......milliseconds to wait
1674 nanos........nanoseconds to wait
1677 true.........if the wait has been interrupted,
1678 false........if the wait was ended by notification or timeout
1680 *******************************************************************************/
1682 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1685 struct timespec wakeupTime;
1687 /* calculate the the (latest) wakeup time */
1689 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1693 return threads_wait_with_timeout(thread, &wakeupTime);
1697 /* threads_calc_absolute_time **************************************************
1699 Calculate the absolute point in time a given number of ms and ns from now.
1702 millis............milliseconds from now
1703 nanos.............nanoseconds from now
1706 *tm...............receives the timespec of the absolute point in time
1708 *******************************************************************************/
1710 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1712 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1715 gettimeofday(&tv, NULL);
1716 tv.tv_sec += millis / 1000;
1718 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1719 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1720 tm->tv_nsec = nsec % 1000000000;
1729 /* threads_thread_interrupt ****************************************************
1731 Interrupt the given thread.
1733 The thread gets the "waitcond" signal and
1734 its interrupted flag is set to true.
1737 thread............the thread to interrupt
1739 *******************************************************************************/
1741 void threads_thread_interrupt(threadobject *thread)
1743 /* Signal the thread a "waitcond" and tell it that it has been
1746 pthread_mutex_lock(&thread->waitmutex);
1748 /* Interrupt blocking system call using a signal. */
1750 pthread_kill(thread->tid, SIGHUP);
1752 if (thread->sleeping)
1753 pthread_cond_signal(&thread->waitcond);
1755 thread->interrupted = true;
1757 pthread_mutex_unlock(&thread->waitmutex);
1761 /* threads_check_if_interrupted_and_reset **************************************
1763 Check if the current thread has been interrupted and reset the
1767 true, if the current thread had been interrupted
1769 *******************************************************************************/
1771 bool threads_check_if_interrupted_and_reset(void)
1773 threadobject *thread;
1776 thread = THREADOBJECT;
1778 /* get interrupted flag */
1780 intr = thread->interrupted;
1782 /* reset interrupted flag */
1784 thread->interrupted = false;
1790 /* threads_thread_has_been_interrupted *****************************************
1792 Check if the given thread has been interrupted
1795 t............the thread to check
1798 true, if the given thread had been interrupted
1800 *******************************************************************************/
1802 bool threads_thread_has_been_interrupted(threadobject *thread)
1804 return thread->interrupted;
1808 /* threads_sleep ***************************************************************
1810 Sleep the current thread for the specified amount of time.
1812 *******************************************************************************/
1814 void threads_sleep(s8 millis, s4 nanos)
1816 threadobject *thread;
1817 struct timespec wakeupTime;
1818 bool wasinterrupted;
1820 thread = THREADOBJECT;
1822 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1824 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1827 exceptions_throw_interruptedexception();
1831 /* threads_yield ***************************************************************
1833 Yield to the scheduler.
1835 *******************************************************************************/
1837 void threads_yield(void)
1844 * These are local overrides for various environment variables in Emacs.
1845 * Please do not remove this and leave it at the end of the file, where
1846 * Emacs will automagically detect them.
1847 * ---------------------------------------------------------------------
1850 * indent-tabs-mode: t
1854 * vim:noexpandtab:sw=4:ts=4: