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 7805 2007-04-25 11:47:15Z 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/threads-common.h"
76 #include "threads/native/threads.h"
78 #include "toolbox/avl.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
192 #define THREADS_INITIAL_TABLE_SIZE 8
195 /* startupinfo *****************************************************************
197 Struct used to pass info from threads_start_thread to
198 threads_startup_thread.
200 ******************************************************************************/
203 threadobject *thread; /* threadobject for this thread */
204 functionptr function; /* function to run in the new thread */
205 sem_t *psem; /* signals when thread has been entered */
206 /* in the thread list */
207 sem_t *psem_first; /* signals when pthread_create has returned */
211 /* prototypes *****************************************************************/
213 static void threads_table_init(void);
214 static s4 threads_table_add(threadobject *thread);
215 static void threads_table_remove(threadobject *thread);
216 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
218 #if !defined(NDEBUG) && 0
219 static void threads_table_dump(FILE *file);
222 /******************************************************************************/
223 /* GLOBAL VARIABLES */
224 /******************************************************************************/
226 /* the main thread */
227 threadobject *mainthreadobj;
229 static methodinfo *method_thread_init;
231 /* the thread object of the current thread */
232 /* This is either a thread-local variable defined with __thread, or */
233 /* a thread-specific value stored with key threads_current_threadobject_key. */
234 #if defined(HAVE___THREAD)
235 __thread threadobject *threads_current_threadobject;
237 pthread_key_t threads_current_threadobject_key;
240 /* global threads table */
241 static threads_table_t threads_table;
243 /* global mutex for changing the thread list */
244 static pthread_mutex_t threadlistlock;
246 /* global mutex for stop-the-world */
247 static pthread_mutex_t stopworldlock;
249 /* global mutex and condition for joining threads on exit */
250 static pthread_mutex_t mutex_join;
251 static pthread_cond_t cond_join;
253 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
255 static volatile int stopworldwhere;
257 /* semaphore used for acknowleding thread suspension */
258 static sem_t suspend_ack;
259 #if defined(__MIPS__)
260 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
261 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
264 static pthread_attr_t threadattr;
266 /* mutexes used by the fake atomic instructions */
267 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
268 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
269 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
270 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
274 /* threads_sem_init ************************************************************
276 Initialize a semaphore. Checks against errors and interruptions.
279 sem..............the semaphore to initialize
280 shared...........true if this semaphore will be shared between processes
281 value............the initial value for the semaphore
283 *******************************************************************************/
285 void threads_sem_init(sem_t *sem, bool shared, int value)
292 r = sem_init(sem, shared, value);
295 } while (errno == EINTR);
297 vm_abort("sem_init failed: %s", strerror(errno));
301 /* threads_sem_wait ************************************************************
303 Wait for a semaphore, non-interruptible.
305 IMPORTANT: Always use this function instead of `sem_wait` directly, as
306 `sem_wait` may be interrupted by signals!
309 sem..............the semaphore to wait on
311 *******************************************************************************/
313 void threads_sem_wait(sem_t *sem)
323 } while (errno == EINTR);
325 vm_abort("sem_wait failed: %s", strerror(errno));
329 /* threads_sem_post ************************************************************
331 Increase the count of a semaphore. Checks for errors.
334 sem..............the semaphore to increase the count of
336 *******************************************************************************/
338 void threads_sem_post(sem_t *sem)
344 /* unlike sem_wait, sem_post is not interruptible */
350 vm_abort("sem_post failed: %s", strerror(errno));
354 /* lock_stopworld **************************************************************
356 Enter the stopworld lock, specifying why the world shall be stopped.
359 where........ STOPWORLD_FROM_GC (1) from within GC
360 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
362 ******************************************************************************/
364 void lock_stopworld(int where)
366 pthread_mutex_lock(&stopworldlock);
367 stopworldwhere = where;
371 /* unlock_stopworld ************************************************************
373 Release the stopworld lock.
375 ******************************************************************************/
377 void unlock_stopworld(void)
380 pthread_mutex_unlock(&stopworldlock);
383 #if !defined(__DARWIN__)
384 /* Caller must hold threadlistlock */
385 static int threads_cast_sendsignals(int sig, int count)
388 threadobject *tobj = mainthreadobj;
389 threadobject *self = THREADOBJECT;
395 } while (tobj != mainthreadobj);
398 assert(tobj == mainthreadobj);
402 pthread_kill(tobj->tid, sig);
404 } while (tobj != mainthreadobj);
411 static void threads_cast_darwinstop(void)
413 threadobject *tobj = mainthreadobj;
414 threadobject *self = THREADOBJECT;
419 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
420 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
421 #if defined(__I386__)
422 i386_thread_state_t thread_state;
424 ppc_thread_state_t thread_state;
426 mach_port_t thread = tobj->mach_thread;
429 r = thread_suspend(thread);
431 if (r != KERN_SUCCESS)
432 vm_abort("thread_suspend failed");
434 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
435 &thread_state_count);
437 if (r != KERN_SUCCESS)
438 vm_abort("thread_get_state failed");
440 thread_restartcriticalsection((ucontext_t *) &thread_state);
442 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
445 if (r != KERN_SUCCESS)
446 vm_abort("thread_set_state failed");
450 } while (tobj != mainthreadobj);
453 static void threads_cast_darwinresume(void)
455 threadobject *tobj = mainthreadobj;
456 threadobject *self = THREADOBJECT;
461 mach_port_t thread = tobj->mach_thread;
464 r = thread_resume(thread);
466 if (r != KERN_SUCCESS)
467 vm_abort("thread_resume failed");
471 } while (tobj != mainthreadobj);
476 #if defined(__MIPS__)
477 static void threads_cast_irixresume(void)
479 pthread_mutex_lock(&suspend_ack_lock);
480 pthread_cond_broadcast(&suspend_cond);
481 pthread_mutex_unlock(&suspend_ack_lock);
485 #if !defined(DISABLE_GC)
487 void threads_cast_stopworld(void)
489 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
493 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
494 pthread_mutex_lock(&threadlistlock);
496 #if defined(__DARWIN__)
497 threads_cast_darwinstop();
498 #elif defined(__CYGWIN__)
502 count = threads_cast_sendsignals(GC_signum1(), 0);
503 for (i = 0; i < count; i++)
504 threads_sem_wait(&suspend_ack);
507 pthread_mutex_unlock(&threadlistlock);
510 void threads_cast_startworld(void)
512 pthread_mutex_lock(&threadlistlock);
513 #if defined(__DARWIN__)
514 threads_cast_darwinresume();
515 #elif defined(__MIPS__)
516 threads_cast_irixresume();
517 #elif defined(__CYGWIN__)
521 threads_cast_sendsignals(GC_signum2(), -1);
523 pthread_mutex_unlock(&threadlistlock);
528 #if !defined(__DARWIN__)
529 static void threads_sigsuspend_handler(ucontext_t *ctx)
534 /* XXX TWISTI: this is just a quick hack */
535 #if defined(ENABLE_JIT)
536 thread_restartcriticalsection(ctx);
539 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
540 (not POSIX async-safe). */
541 #if defined(__IRIX__)
542 pthread_mutex_lock(&suspend_ack_lock);
543 threads_sem_post(&suspend_ack);
544 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
545 pthread_mutex_unlock(&suspend_ack_lock);
546 #elif defined(__CYGWIN__)
550 threads_sem_post(&suspend_ack);
554 sigdelset(&sigs, sig);
559 /* This function is called from Boehm GC code. */
561 int cacao_suspendhandler(ucontext_t *ctx)
563 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
566 threads_sigsuspend_handler(ctx);
571 #endif /* DISABLE_GC */
573 /* threads_set_current_threadobject ********************************************
575 Set the current thread object.
578 thread.......the thread object to set
580 *******************************************************************************/
582 static void threads_set_current_threadobject(threadobject *thread)
584 #if !defined(HAVE___THREAD)
585 pthread_setspecific(threads_current_threadobject_key, thread);
587 threads_current_threadobject = thread;
592 /* threads_init_threadobject **************************************************
594 Initialize implementation fields of a threadobject.
597 thread............the threadobject
599 ******************************************************************************/
601 static void threads_init_threadobject(threadobject *thread)
603 /* get the pthread id */
605 thread->tid = pthread_self();
609 /* TODO destroy all those things */
611 pthread_mutex_init(&(thread->waitmutex), NULL);
612 pthread_cond_init(&(thread->waitcond), NULL);
614 thread->interrupted = false;
615 thread->signaled = false;
616 thread->sleeping = false;
620 /* threads_get_current_threadobject ********************************************
622 Return the threadobject of the current thread.
625 the current threadobject * (an instance of java.lang.Thread)
627 *******************************************************************************/
629 threadobject *threads_get_current_threadobject(void)
635 /* threads_preinit *************************************************************
637 Do some early initialization of stuff required.
639 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
640 is called AFTER this function!
642 *******************************************************************************/
644 void threads_preinit(void)
646 pthread_mutex_init(&threadlistlock, NULL);
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(ENABLE_GC_BOEHM)
656 mainthreadobj = GCNEW_UNCOLLECTABLE(threadobject, 1);
658 mainthreadobj = NEW(threadobject);
661 #if defined(ENABLE_STATISTICS)
663 size_threadobject += sizeof(threadobject);
666 mainthreadobj->object = NULL;
667 mainthreadobj->tid = pthread_self();
668 mainthreadobj->index = 1;
669 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
671 #if !defined(HAVE___THREAD)
672 pthread_key_create(&threads_current_threadobject_key, NULL);
674 threads_set_current_threadobject(mainthreadobj);
676 threads_sem_init(&suspend_ack, 0, 0);
678 /* initialize the threads table */
680 threads_table_init();
682 /* initialize subsystems */
690 /* threads_init ****************************************************************
692 Initializes the threads required by the JVM: main, finalizer.
694 *******************************************************************************/
696 bool threads_init(void)
698 java_objectheader *threadname;
699 java_objectheader *o;
701 #if defined(ENABLE_JAVASE)
702 java_lang_ThreadGroup *threadgroup;
707 #if defined(WITH_CLASSPATH_GNU)
708 java_lang_VMThread *vmt;
711 /* get methods we need in this file */
713 #if defined(WITH_CLASSPATH_GNU)
715 class_resolveclassmethod(class_java_lang_Thread,
717 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
718 class_java_lang_Thread,
722 class_resolveclassmethod(class_java_lang_Thread,
724 utf_new_char("(Ljava/lang/String;)V"),
725 class_java_lang_Thread,
729 if (method_thread_init == NULL)
732 /* create a java.lang.Thread for the main thread */
734 mainthreadobj->object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
736 if (mainthreadobj->object == NULL)
739 threads_init_threadobject(mainthreadobj);
740 threads_set_current_threadobject(mainthreadobj);
741 lock_init_execution_env(mainthreadobj);
743 /* thread is running */
745 mainthreadobj->state = THREAD_STATE_RUNNABLE;
747 mainthreadobj->next = mainthreadobj;
748 mainthreadobj->prev = mainthreadobj;
750 threads_table_add(mainthreadobj);
752 /* mark main thread as Java thread */
754 mainthreadobj->flags = THREAD_FLAG_JAVA;
756 #if defined(ENABLE_INTRP)
757 /* create interpreter stack */
760 MSET(intrp_main_stack, 0, u1, opt_stacksize);
761 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
765 threadname = javastring_new(utf_new_char("main"));
767 #if defined(ENABLE_JAVASE)
768 /* allocate and init ThreadGroup */
770 threadgroup = (java_lang_ThreadGroup *)
771 native_new_and_init(class_java_lang_ThreadGroup);
773 if (threadgroup == NULL)
777 #if defined(WITH_CLASSPATH_GNU)
778 /* create a java.lang.VMThread for the main thread */
780 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
787 vmt->thread = mainthreadobj->object;
788 vmt->vmdata = (java_lang_Object *) mainthreadobj;
790 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
791 o = (java_objectheader *) mainthreadobj->object;
793 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
795 #elif defined(WITH_CLASSPATH_CLDC1_1)
798 mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
800 /* call public Thread(String name) */
802 o = (java_objectheader *) mainthreadobj->object;
804 (void) vm_call_method(method_thread_init, o, threadname);
810 #if defined(ENABLE_JAVASE)
811 mainthreadobj->object->group = threadgroup;
813 /* add main thread to java.lang.ThreadGroup */
815 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
817 utf_java_lang_Thread__V,
818 class_java_lang_ThreadGroup,
821 o = (java_objectheader *) threadgroup;
822 t = mainthreadobj->object;
824 (void) vm_call_method(m, o, t);
831 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
833 /* initialize the thread attribute object */
835 if (pthread_attr_init(&threadattr)) {
836 log_println("pthread_attr_init failed: %s", strerror(errno));
840 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
842 /* everything's ok */
848 /* threads_table_init *********************************************************
850 Initialize the global threads table.
852 ******************************************************************************/
854 static void threads_table_init(void)
859 size = THREADS_INITIAL_TABLE_SIZE;
861 threads_table.size = size;
862 threads_table.table = MNEW(threads_table_entry_t, size);
864 /* link the entries in a freelist */
866 for (i=0; i<size; ++i) {
867 threads_table.table[i].nextfree = i+1;
870 /* terminate the freelist */
872 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
876 /* threads_table_add **********************************************************
878 Add a thread to the global threads table. The index is entered in the
879 threadobject. The thinlock value for the thread is pre-computed.
882 thread............the thread to add
885 The table index for the newly added thread. This value has also been
886 entered in the threadobject.
889 The caller must hold the threadlistlock!
891 ******************************************************************************/
893 static s4 threads_table_add(threadobject *thread)
900 /* table[0] serves as the head of the freelist */
902 index = threads_table.table[0].nextfree;
904 /* if we got a free index, use it */
908 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
909 threads_table.table[index].thread = thread;
910 thread->index = index;
911 thread->thinlock = lock_pre_compute_thinlock(index);
915 /* we must grow the table */
917 oldsize = threads_table.size;
918 newsize = oldsize * 2;
920 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
922 threads_table.size = newsize;
924 /* link the new entries to a free list */
926 for (i=oldsize; i<newsize; ++i) {
927 threads_table.table[i].nextfree = i+1;
930 /* terminate the freelist */
932 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
934 /* use the first of the new entries */
941 /* threads_table_remove *******************************************************
943 Remove a thread from the global threads table.
946 thread............the thread to remove
949 The caller must hold the threadlistlock!
951 ******************************************************************************/
953 static void threads_table_remove(threadobject *thread)
957 index = thread->index;
959 /* put the index into the freelist */
961 threads_table.table[index] = threads_table.table[0];
962 threads_table.table[0].nextfree = index;
964 /* delete the index in the threadobject to discover bugs */
971 /* threads_startup_thread ******************************************************
973 Thread startup function called by pthread_create.
975 Thread which have a startup.function != NULL are marked as internal
976 threads. All other threads are threated as normal Java threads.
978 NOTE: This function is not called directly by pthread_create. The Boehm GC
979 inserts its own GC_start_routine in between, which then calls
983 t............the argument passed to pthread_create, ie. a pointer to
984 a startupinfo struct. CAUTION: When the `psem` semaphore
985 is posted, the startupinfo struct becomes invalid! (It
986 is allocated on the stack of threads_start_thread.)
988 ******************************************************************************/
990 static void *threads_startup_thread(void *t)
992 startupinfo *startup;
993 threadobject *thread;
994 #if defined(WITH_CLASSPATH_GNU)
995 java_lang_VMThread *vmt;
1001 java_objectheader *o;
1002 functionptr function;
1004 #if defined(ENABLE_INTRP)
1005 u1 *intrp_thread_stack;
1007 /* create interpreter stack */
1010 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1011 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1014 intrp_thread_stack = NULL;
1017 /* get passed startupinfo structure and the values in there */
1020 t = NULL; /* make sure it's not used wrongly */
1022 thread = startup->thread;
1023 function = startup->function;
1024 psem = startup->psem;
1026 /* Seems like we've encountered a situation where thread->tid was not set by
1027 * pthread_create. We alleviate this problem by waiting for pthread_create
1029 threads_sem_wait(startup->psem_first);
1031 /* set the thread object */
1033 #if defined(__DARWIN__)
1034 thread->mach_thread = mach_thread_self();
1036 threads_set_current_threadobject(thread);
1038 /* thread is running */
1040 thread->state = THREAD_STATE_RUNNABLE;
1042 /* insert the thread into the threadlist and the threads table */
1044 pthread_mutex_lock(&threadlistlock);
1046 thread->prev = mainthreadobj;
1047 thread->next = tnext = mainthreadobj->next;
1048 mainthreadobj->next = thread;
1049 tnext->prev = thread;
1051 threads_table_add(thread);
1053 pthread_mutex_unlock(&threadlistlock);
1055 /* init data structures of this thread */
1057 lock_init_execution_env(thread);
1059 /* tell threads_startup_thread that we registered ourselves */
1060 /* CAUTION: *startup becomes invalid with this! */
1063 threads_sem_post(psem);
1065 /* set our priority */
1067 threads_set_thread_priority(thread->tid, thread->object->priority);
1069 #if defined(ENABLE_INTRP)
1070 /* set interpreter stack */
1073 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1076 #if defined(ENABLE_JVMTI)
1077 /* fire thread start event */
1080 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1083 /* find and run the Thread.run()V method if no other function was passed */
1085 if (function == NULL) {
1086 /* this is a normal Java thread */
1088 thread->flags |= THREAD_FLAG_JAVA;
1090 #if defined(WITH_CLASSPATH_GNU)
1091 /* We need to start the run method of
1092 java.lang.VMThread. Since this is a final class, we can use
1093 the class object directly. */
1095 c = class_java_lang_VMThread;
1096 #elif defined(WITH_CLASSPATH_CLDC1_1)
1097 c = thread->object->header.vftbl->class;
1100 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1103 vm_abort("threads_startup_thread: run() method not found in class");
1105 /* set ThreadMXBean variables */
1107 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1108 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1110 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1111 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1112 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1113 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1115 #if defined(WITH_CLASSPATH_GNU)
1116 /* we need to start the run method of java.lang.VMThread */
1118 vmt = (java_lang_VMThread *) thread->object->vmThread;
1119 o = (java_objectheader *) vmt;
1121 #elif defined(WITH_CLASSPATH_CLDC1_1)
1122 o = (java_objectheader *) thread->object;
1125 /* run the thread */
1127 (void) vm_call_method(m, o);
1130 /* this is an internal thread */
1132 thread->flags |= THREAD_FLAG_INTERNAL;
1134 /* set ThreadMXBean variables */
1136 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1137 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1139 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1140 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1141 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1142 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1144 /* call passed function, e.g. finalizer_thread */
1149 #if defined(ENABLE_JVMTI)
1150 /* fire thread end event */
1153 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1156 if (!threads_detach_thread(thread))
1157 vm_abort("threads_startup_thread: threads_detach_thread failed");
1159 /* set ThreadMXBean variables */
1161 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1167 /* threads_start_thread ********************************************************
1169 Start a thread in the JVM. Both (vm internal and java) thread objects exist.
1172 thread.......the thread object
1173 function.....function to run in the new thread. NULL means that the
1174 "run" method of the object `t` should be called
1176 ******************************************************************************/
1178 void threads_start_thread(threadobject *thread, functionptr function)
1182 pthread_attr_t attr;
1183 startupinfo startup;
1185 /* fill startupinfo structure passed by pthread_create to
1186 * threads_startup_thread */
1188 startup.thread = thread;
1189 startup.function = function; /* maybe we don't call Thread.run()V */
1190 startup.psem = &sem;
1191 startup.psem_first = &sem_first;
1193 threads_sem_init(&sem, 0, 0);
1194 threads_sem_init(&sem_first, 0, 0);
1196 /* initialize thread attribute object */
1198 if (pthread_attr_init(&attr))
1199 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1201 /* initialize thread stacksize */
1203 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1204 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1206 /* create the thread */
1208 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1209 vm_abort("pthread_create failed: %s", strerror(errno));
1211 /* signal that pthread_create has returned, so thread->tid is valid */
1213 threads_sem_post(&sem_first);
1215 /* wait here until the thread has entered itself into the thread list */
1217 threads_sem_wait(&sem);
1222 sem_destroy(&sem_first);
1226 /* threads_set_thread_priority *************************************************
1228 Set the priority of the given thread.
1231 tid..........thread id
1232 priority.....priority to set
1234 ******************************************************************************/
1236 void threads_set_thread_priority(pthread_t tid, int priority)
1238 struct sched_param schedp;
1241 pthread_getschedparam(tid, &policy, &schedp);
1242 schedp.sched_priority = priority;
1243 pthread_setschedparam(tid, policy, &schedp);
1247 /* threads_attach_current_thread ***********************************************
1249 Attaches the current thread to the VM. Used in JNI.
1251 *******************************************************************************/
1253 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1255 threadobject *thread;
1257 java_objectheader *s;
1258 java_objectheader *o;
1259 java_lang_Thread *t;
1261 #if defined(ENABLE_JAVASE)
1262 java_lang_ThreadGroup *group;
1266 #if defined(WITH_CLASSPATH_GNU)
1267 java_lang_VMThread *vmt;
1270 /* create a vm internal thread object */
1272 #if defined(ENABLE_GC_BOEHM)
1273 thread = GCNEW_UNCOLLECTABLE(threadobject, 1);
1275 thread = NEW(threadobject);
1278 #if defined(ENABLE_STATISTICS)
1280 size_threadobject += sizeof(threadobject);
1286 /* create a java.lang.Thread object */
1288 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1295 threads_init_threadobject(thread);
1296 threads_set_current_threadobject(thread);
1297 lock_init_execution_env(thread);
1299 /* thread is running */
1301 thread->state = THREAD_STATE_RUNNABLE;
1303 /* insert the thread into the threadlist and the threads table */
1305 pthread_mutex_lock(&threadlistlock);
1307 thread->prev = mainthreadobj;
1308 thread->next = mainthreadobj->next;
1309 mainthreadobj->next = thread;
1310 thread->next->prev = thread;
1312 threads_table_add(thread);
1314 pthread_mutex_unlock(&threadlistlock);
1316 /* mark thread as Java thread */
1318 thread->flags = THREAD_FLAG_JAVA;
1321 thread->flags |= THREAD_FLAG_DAEMON;
1323 #if defined(ENABLE_INTRP)
1324 /* create interpreter stack */
1327 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1328 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1332 #if defined(WITH_CLASSPATH_GNU)
1333 /* create a java.lang.VMThread object */
1335 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1340 /* set the thread */
1343 vmt->vmdata = (java_lang_Object *) thread;
1344 #elif defined(WITH_CLASSPATH_CLDC1_1)
1345 t->vm_thread = (java_lang_Object *) thread;
1348 if (vm_aargs != NULL) {
1349 u = utf_new_char(vm_aargs->name);
1350 #if defined(ENABLE_JAVASE)
1351 group = (java_lang_ThreadGroup *) vm_aargs->group;
1356 #if defined(ENABLE_JAVASE)
1357 group = mainthreadobj->object->group;
1361 /* the the thread name */
1363 s = javastring_new(u);
1365 /* for convenience */
1367 o = (java_objectheader *) thread->object;
1369 #if defined(WITH_CLASSPATH_GNU)
1370 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1372 #elif defined(WITH_CLASSPATH_CLDC1_1)
1373 (void) vm_call_method(method_thread_init, o, s);
1379 #if defined(ENABLE_JAVASE)
1380 /* store the thread group in the object */
1382 thread->object->group = group;
1384 /* add thread to given thread-group */
1386 m = class_resolveclassmethod(group->header.vftbl->class,
1388 utf_java_lang_Thread__V,
1389 class_java_lang_ThreadGroup,
1392 o = (java_objectheader *) group;
1394 (void) vm_call_method(m, o, t);
1404 /* threads_detach_thread *******************************************************
1406 Detaches the passed thread from the VM. Used in JNI.
1408 *******************************************************************************/
1410 bool threads_detach_thread(threadobject *thread)
1412 #if defined(ENABLE_JAVASE)
1413 java_lang_ThreadGroup *group;
1415 java_objectheader *o;
1416 java_lang_Thread *t;
1419 /* Allow lock record pools to be used by other threads. They
1420 cannot be deleted so we'd better not waste them. */
1422 /* XXX We have to find a new way to free lock records */
1423 /* with the new locking algorithm. */
1424 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1426 /* XXX implement uncaught exception stuff (like JamVM does) */
1428 #if defined(ENABLE_JAVASE)
1429 /* remove thread from the thread group */
1431 group = thread->object->group;
1433 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1435 if (group != NULL) {
1436 m = class_resolveclassmethod(group->header.vftbl->class,
1438 utf_java_lang_Thread__V,
1439 class_java_lang_ThreadGroup,
1445 o = (java_objectheader *) group;
1448 (void) vm_call_method(m, o, t);
1455 /* thread is terminated */
1457 thread->state = THREAD_STATE_TERMINATED;
1459 /* lock thread list */
1461 pthread_mutex_lock(&threadlistlock);
1463 /* remove thread from thread list and threads table */
1465 thread->next->prev = thread->prev;
1466 thread->prev->next = thread->next;
1468 threads_table_remove(thread);
1470 /* unlock thread list */
1472 pthread_mutex_unlock(&threadlistlock);
1474 /* signal that this thread has finished */
1476 pthread_mutex_lock(&mutex_join);
1477 pthread_cond_signal(&cond_join);
1478 pthread_mutex_unlock(&mutex_join);
1480 /* free the vm internal thread object */
1482 #if defined(ENABLE_GC_BOEHM)
1485 FREE(thread, threadobject);
1488 #if defined(ENABLE_STATISTICS)
1490 size_threadobject -= sizeof(threadobject);
1497 /* threads_find_non_daemon_thread **********************************************
1499 Helper function used by threads_join_all_threads for finding
1500 non-daemon threads that are still running.
1502 *******************************************************************************/
1504 static threadobject *threads_find_non_daemon_thread(void)
1506 threadobject *thread;
1508 /* lock the thread list */
1510 pthread_mutex_lock(&threadlistlock);
1512 /* iterate over all threads */
1514 thread = mainthreadobj->next;
1516 while (thread != mainthreadobj) {
1517 if (!(thread->flags & THREAD_FLAG_DAEMON)) {
1518 /* unlock thread list */
1520 pthread_mutex_unlock(&threadlistlock);
1525 thread = thread->next;
1528 /* unlock thread list */
1530 pthread_mutex_unlock(&threadlistlock);
1536 /* threads_join_all_threads ****************************************************
1538 Join all non-daemon threads.
1540 *******************************************************************************/
1542 void threads_join_all_threads(void)
1544 threadobject *thread;
1546 /* get current thread */
1548 thread = THREADOBJECT;
1550 /* this thread is waiting for all non-daemon threads to exit */
1552 thread->state = THREAD_STATE_WAITING;
1554 /* enter join mutex */
1556 pthread_mutex_lock(&mutex_join);
1558 /* wait for condition as long as we have non-daemon threads */
1560 while (threads_find_non_daemon_thread() != NULL)
1561 pthread_cond_wait(&cond_join, &mutex_join);
1563 /* leave join mutex */
1565 pthread_mutex_unlock(&mutex_join);
1569 /* threads_timespec_earlier ****************************************************
1571 Return true if timespec tv1 is earlier than timespec tv2.
1574 tv1..........first timespec
1575 tv2..........second timespec
1578 true, if the first timespec is earlier
1580 *******************************************************************************/
1582 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1583 const struct timespec *tv2)
1585 return (tv1->tv_sec < tv2->tv_sec)
1587 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1591 /* threads_current_time_is_earlier_than ****************************************
1593 Check if the current time is earlier than the given timespec.
1596 tv...........the timespec to compare against
1599 true, if the current time is earlier
1601 *******************************************************************************/
1603 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1605 struct timeval tvnow;
1606 struct timespec tsnow;
1608 /* get current time */
1610 if (gettimeofday(&tvnow, NULL) != 0)
1611 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1613 /* convert it to a timespec */
1615 tsnow.tv_sec = tvnow.tv_sec;
1616 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1618 /* compare current time with the given timespec */
1620 return threads_timespec_earlier(&tsnow, tv);
1624 /* threads_wait_with_timeout ***************************************************
1626 Wait until the given point in time on a monitor until either
1627 we are notified, we are interrupted, or the time is up.
1630 t............the current thread
1631 wakeupTime...absolute (latest) wakeup time
1632 If both tv_sec and tv_nsec are zero, this function
1633 waits for an unlimited amount of time.
1636 true.........if the wait has been interrupted,
1637 false........if the wait was ended by notification or timeout
1639 *******************************************************************************/
1641 static bool threads_wait_with_timeout(threadobject *thread,
1642 struct timespec *wakeupTime)
1644 bool wasinterrupted;
1646 /* acquire the waitmutex */
1648 pthread_mutex_lock(&thread->waitmutex);
1650 /* mark us as sleeping */
1652 thread->sleeping = true;
1654 /* wait on waitcond */
1656 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1658 while (!thread->interrupted && !thread->signaled
1659 && threads_current_time_is_earlier_than(wakeupTime))
1661 thread->state = THREAD_STATE_TIMED_WAITING;
1663 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1666 thread->state = THREAD_STATE_RUNNABLE;
1671 while (!thread->interrupted && !thread->signaled) {
1672 thread->state = THREAD_STATE_WAITING;
1674 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1676 thread->state = THREAD_STATE_RUNNABLE;
1680 /* check if we were interrupted */
1682 wasinterrupted = thread->interrupted;
1684 /* reset all flags */
1686 thread->interrupted = false;
1687 thread->signaled = false;
1688 thread->sleeping = false;
1690 /* release the waitmutex */
1692 pthread_mutex_unlock(&thread->waitmutex);
1694 return wasinterrupted;
1698 /* threads_wait_with_timeout_relative ******************************************
1700 Wait for the given maximum amount of time on a monitor until either
1701 we are notified, we are interrupted, or the time is up.
1704 t............the current thread
1705 millis.......milliseconds to wait
1706 nanos........nanoseconds to wait
1709 true.........if the wait has been interrupted,
1710 false........if the wait was ended by notification or timeout
1712 *******************************************************************************/
1714 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1717 struct timespec wakeupTime;
1719 /* calculate the the (latest) wakeup time */
1721 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1725 return threads_wait_with_timeout(thread, &wakeupTime);
1729 /* threads_calc_absolute_time **************************************************
1731 Calculate the absolute point in time a given number of ms and ns from now.
1734 millis............milliseconds from now
1735 nanos.............nanoseconds from now
1738 *tm...............receives the timespec of the absolute point in time
1740 *******************************************************************************/
1742 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1744 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1747 gettimeofday(&tv, NULL);
1748 tv.tv_sec += millis / 1000;
1750 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1751 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1752 tm->tv_nsec = nsec % 1000000000;
1761 /* threads_thread_interrupt ****************************************************
1763 Interrupt the given thread.
1765 The thread gets the "waitcond" signal and
1766 its interrupted flag is set to true.
1769 thread............the thread to interrupt
1771 *******************************************************************************/
1773 void threads_thread_interrupt(threadobject *thread)
1775 /* Signal the thread a "waitcond" and tell it that it has been
1778 pthread_mutex_lock(&thread->waitmutex);
1780 /* Interrupt blocking system call using a signal. */
1782 pthread_kill(thread->tid, SIGHUP);
1784 if (thread->sleeping)
1785 pthread_cond_signal(&thread->waitcond);
1787 thread->interrupted = true;
1789 pthread_mutex_unlock(&thread->waitmutex);
1793 /* threads_check_if_interrupted_and_reset **************************************
1795 Check if the current thread has been interrupted and reset the
1799 true, if the current thread had been interrupted
1801 *******************************************************************************/
1803 bool threads_check_if_interrupted_and_reset(void)
1805 threadobject *thread;
1808 thread = THREADOBJECT;
1810 /* get interrupted flag */
1812 intr = thread->interrupted;
1814 /* reset interrupted flag */
1816 thread->interrupted = false;
1822 /* threads_thread_has_been_interrupted *****************************************
1824 Check if the given thread has been interrupted
1827 t............the thread to check
1830 true, if the given thread had been interrupted
1832 *******************************************************************************/
1834 bool threads_thread_has_been_interrupted(threadobject *thread)
1836 return thread->interrupted;
1840 /* threads_sleep ***************************************************************
1842 Sleep the current thread for the specified amount of time.
1844 *******************************************************************************/
1846 void threads_sleep(s8 millis, s4 nanos)
1848 threadobject *thread;
1849 struct timespec wakeupTime;
1850 bool wasinterrupted;
1852 thread = THREADOBJECT;
1854 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1856 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1859 exceptions_throw_interruptedexception();
1863 /* threads_yield ***************************************************************
1865 Yield to the scheduler.
1867 *******************************************************************************/
1869 void threads_yield(void)
1875 /* threads_table_dump *********************************************************
1877 Dump the threads table for debugging purposes.
1880 file..............stream to write to
1882 ******************************************************************************/
1884 #if !defined(NDEBUG) && 0
1885 static void threads_table_dump(FILE *file)
1891 pthread_mutex_lock(&threadlistlock);
1893 size = threads_table.size;
1895 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1897 for (i=0; i<size; ++i) {
1898 index = threads_table.table[i].nextfree;
1900 fprintf(file, "%4d: ", i);
1903 fprintf(file, "free, nextfree = %d\n", (int) index);
1906 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1910 fprintf(file, "======== END OF THREADS TABLE ========\n");
1912 pthread_mutex_unlock(&threadlistlock);
1917 * These are local overrides for various environment variables in Emacs.
1918 * Please do not remove this and leave it at the end of the file, where
1919 * Emacs will automagically detect them.
1920 * ---------------------------------------------------------------------
1923 * indent-tabs-mode: t
1927 * vim:noexpandtab:sw=4:ts=4: