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 7831 2007-04-26 12:48:16Z twisti $
32 /* XXX cleanup these includes */
37 #include <sys/types.h>
50 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
51 # include "machine-instr.h"
53 # include "threads/native/generic-primitives.h"
56 #include "mm/gc-common.h"
57 #include "mm/memory.h"
59 #include "native/jni.h"
60 #include "native/native.h"
61 #include "native/include/java_lang_Object.h"
62 #include "native/include/java_lang_String.h"
63 #include "native/include/java_lang_Throwable.h"
64 #include "native/include/java_lang_Thread.h"
66 #if defined(ENABLE_JAVASE)
67 # include "native/include/java_lang_ThreadGroup.h"
70 #if defined(WITH_CLASSPATH_GNU)
71 # include "native/include/java_lang_VMThread.h"
74 #include "threads/lock-common.h"
75 #include "threads/threads-common.h"
77 #include "threads/native/threads.h"
79 #include "toolbox/avl.h"
80 #include "toolbox/logging.h"
82 #include "vm/builtin.h"
83 #include "vm/exceptions.h"
84 #include "vm/global.h"
85 #include "vm/stringlocal.h"
88 #include "vm/jit/asmpart.h"
90 #include "vmcore/options.h"
92 #if defined(ENABLE_STATISTICS)
93 # include "vmcore/statistics.h"
96 #if !defined(__DARWIN__)
97 # if defined(__LINUX__)
98 # define GC_LINUX_THREADS
99 # elif defined(__MIPS__)
100 # define GC_IRIX_THREADS
102 # include <semaphore.h>
103 # if defined(ENABLE_GC_BOEHM)
104 # include "mm/boehm-gc/include/gc.h"
108 #if defined(ENABLE_JVMTI)
109 #include "native/jvmti/cacaodbg.h"
112 #if defined(__DARWIN__)
113 /* Darwin has no working semaphore implementation. This one is taken
117 This is a very simple semaphore implementation for darwin. It
118 is implemented in terms of pthreads calls so it isn't async signal
119 safe. This isn't a problem because signals aren't used to
120 suspend threads on darwin.
123 static int sem_init(sem_t *sem, int pshared, int value)
130 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
133 if (pthread_cond_init(&sem->cond, NULL) < 0)
139 static int sem_post(sem_t *sem)
141 if (pthread_mutex_lock(&sem->mutex) < 0)
146 if (pthread_cond_signal(&sem->cond) < 0) {
147 pthread_mutex_unlock(&sem->mutex);
151 if (pthread_mutex_unlock(&sem->mutex) < 0)
157 static int sem_wait(sem_t *sem)
159 if (pthread_mutex_lock(&sem->mutex) < 0)
162 while (sem->value == 0) {
163 pthread_cond_wait(&sem->cond, &sem->mutex);
168 if (pthread_mutex_unlock(&sem->mutex) < 0)
174 static int sem_destroy(sem_t *sem)
176 if (pthread_cond_destroy(&sem->cond) < 0)
179 if (pthread_mutex_destroy(&sem->mutex) < 0)
184 #endif /* defined(__DARWIN__) */
187 /* internally used constants **************************************************/
189 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
190 #define STOPWORLD_FROM_GC 1
191 #define STOPWORLD_FROM_CLASS_NUMBERING 2
194 /* startupinfo *****************************************************************
196 Struct used to pass info from threads_start_thread to
197 threads_startup_thread.
199 ******************************************************************************/
202 threadobject *thread; /* threadobject for this thread */
203 functionptr function; /* function to run in the new thread */
204 sem_t *psem; /* signals when thread has been entered */
205 /* in the thread list */
206 sem_t *psem_first; /* signals when pthread_create has returned */
210 /* prototypes *****************************************************************/
212 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
215 /******************************************************************************/
216 /* GLOBAL VARIABLES */
217 /******************************************************************************/
219 /* the main thread */
220 threadobject *mainthreadobj;
222 static methodinfo *method_thread_init;
224 /* the thread object of the current thread */
225 /* This is either a thread-local variable defined with __thread, or */
226 /* a thread-specific value stored with key threads_current_threadobject_key. */
227 #if defined(HAVE___THREAD)
228 __thread threadobject *threads_current_threadobject;
230 pthread_key_t threads_current_threadobject_key;
233 /* global mutex for changing the thread list */
234 static pthread_mutex_t threadlistlock;
236 /* global mutex for stop-the-world */
237 static pthread_mutex_t stopworldlock;
239 /* global mutex and condition for joining threads on exit */
240 static pthread_mutex_t mutex_join;
241 static pthread_cond_t cond_join;
243 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
245 static volatile int stopworldwhere;
247 /* semaphore used for acknowleding thread suspension */
248 static sem_t suspend_ack;
249 #if defined(__MIPS__)
250 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
251 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
254 static pthread_attr_t threadattr;
256 /* mutexes used by the fake atomic instructions */
257 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
258 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
259 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
260 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
264 /* threads_sem_init ************************************************************
266 Initialize a semaphore. Checks against errors and interruptions.
269 sem..............the semaphore to initialize
270 shared...........true if this semaphore will be shared between processes
271 value............the initial value for the semaphore
273 *******************************************************************************/
275 void threads_sem_init(sem_t *sem, bool shared, int value)
282 r = sem_init(sem, shared, value);
285 } while (errno == EINTR);
287 vm_abort("sem_init failed: %s", strerror(errno));
291 /* threads_sem_wait ************************************************************
293 Wait for a semaphore, non-interruptible.
295 IMPORTANT: Always use this function instead of `sem_wait` directly, as
296 `sem_wait` may be interrupted by signals!
299 sem..............the semaphore to wait on
301 *******************************************************************************/
303 void threads_sem_wait(sem_t *sem)
313 } while (errno == EINTR);
315 vm_abort("sem_wait failed: %s", strerror(errno));
319 /* threads_sem_post ************************************************************
321 Increase the count of a semaphore. Checks for errors.
324 sem..............the semaphore to increase the count of
326 *******************************************************************************/
328 void threads_sem_post(sem_t *sem)
334 /* unlike sem_wait, sem_post is not interruptible */
340 vm_abort("sem_post failed: %s", strerror(errno));
344 /* lock_stopworld **************************************************************
346 Enter the stopworld lock, specifying why the world shall be stopped.
349 where........ STOPWORLD_FROM_GC (1) from within GC
350 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
352 ******************************************************************************/
354 void lock_stopworld(int where)
356 pthread_mutex_lock(&stopworldlock);
357 stopworldwhere = where;
361 /* unlock_stopworld ************************************************************
363 Release the stopworld lock.
365 ******************************************************************************/
367 void unlock_stopworld(void)
370 pthread_mutex_unlock(&stopworldlock);
373 #if !defined(__DARWIN__)
374 /* Caller must hold threadlistlock */
375 static int threads_cast_sendsignals(int sig, int count)
378 threadobject *tobj = mainthreadobj;
379 threadobject *self = THREADOBJECT;
385 } while (tobj != mainthreadobj);
388 assert(tobj == mainthreadobj);
392 pthread_kill(tobj->tid, sig);
394 } while (tobj != mainthreadobj);
401 static void threads_cast_darwinstop(void)
403 threadobject *tobj = mainthreadobj;
404 threadobject *self = THREADOBJECT;
409 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
410 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
411 #if defined(__I386__)
412 i386_thread_state_t thread_state;
414 ppc_thread_state_t thread_state;
416 mach_port_t thread = tobj->mach_thread;
419 r = thread_suspend(thread);
421 if (r != KERN_SUCCESS)
422 vm_abort("thread_suspend failed");
424 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
425 &thread_state_count);
427 if (r != KERN_SUCCESS)
428 vm_abort("thread_get_state failed");
430 thread_restartcriticalsection((ucontext_t *) &thread_state);
432 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
435 if (r != KERN_SUCCESS)
436 vm_abort("thread_set_state failed");
440 } while (tobj != mainthreadobj);
443 static void threads_cast_darwinresume(void)
445 threadobject *tobj = mainthreadobj;
446 threadobject *self = THREADOBJECT;
451 mach_port_t thread = tobj->mach_thread;
454 r = thread_resume(thread);
456 if (r != KERN_SUCCESS)
457 vm_abort("thread_resume failed");
461 } while (tobj != mainthreadobj);
466 #if defined(__MIPS__)
467 static void threads_cast_irixresume(void)
469 pthread_mutex_lock(&suspend_ack_lock);
470 pthread_cond_broadcast(&suspend_cond);
471 pthread_mutex_unlock(&suspend_ack_lock);
475 #if !defined(DISABLE_GC)
477 void threads_cast_stopworld(void)
479 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
483 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
484 pthread_mutex_lock(&threadlistlock);
486 #if defined(__DARWIN__)
487 threads_cast_darwinstop();
488 #elif defined(__CYGWIN__)
492 count = threads_cast_sendsignals(GC_signum1(), 0);
493 for (i = 0; i < count; i++)
494 threads_sem_wait(&suspend_ack);
497 pthread_mutex_unlock(&threadlistlock);
500 void threads_cast_startworld(void)
502 pthread_mutex_lock(&threadlistlock);
503 #if defined(__DARWIN__)
504 threads_cast_darwinresume();
505 #elif defined(__MIPS__)
506 threads_cast_irixresume();
507 #elif defined(__CYGWIN__)
511 threads_cast_sendsignals(GC_signum2(), -1);
513 pthread_mutex_unlock(&threadlistlock);
518 #if !defined(__DARWIN__)
519 static void threads_sigsuspend_handler(ucontext_t *ctx)
524 /* XXX TWISTI: this is just a quick hack */
525 #if defined(ENABLE_JIT)
526 thread_restartcriticalsection(ctx);
529 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
530 (not POSIX async-safe). */
531 #if defined(__IRIX__)
532 pthread_mutex_lock(&suspend_ack_lock);
533 threads_sem_post(&suspend_ack);
534 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
535 pthread_mutex_unlock(&suspend_ack_lock);
536 #elif defined(__CYGWIN__)
540 threads_sem_post(&suspend_ack);
544 sigdelset(&sigs, sig);
549 /* This function is called from Boehm GC code. */
551 int cacao_suspendhandler(ucontext_t *ctx)
553 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
556 threads_sigsuspend_handler(ctx);
561 #endif /* DISABLE_GC */
564 /* threads_set_current_threadobject ********************************************
566 Set the current thread object.
569 thread.......the thread object to set
571 *******************************************************************************/
573 void threads_set_current_threadobject(threadobject *thread)
575 #if !defined(HAVE___THREAD)
576 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
577 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
579 threads_current_threadobject = thread;
584 /* threads_init_threadobject **************************************************
586 Initialize implementation fields of a threadobject.
589 thread............the threadobject
591 ******************************************************************************/
593 void threads_init_threadobject(threadobject *thread)
595 /* get the pthread id */
597 thread->tid = pthread_self();
601 /* TODO destroy all those things */
603 pthread_mutex_init(&(thread->waitmutex), NULL);
604 pthread_cond_init(&(thread->waitcond), NULL);
606 thread->interrupted = false;
607 thread->signaled = false;
608 thread->sleeping = false;
612 /* threads_get_current_threadobject ********************************************
614 Return the threadobject of the current thread.
617 the current threadobject * (an instance of java.lang.Thread)
619 *******************************************************************************/
621 threadobject *threads_get_current_threadobject(void)
627 /* threads_impl_preinit ********************************************************
629 Do some early initialization of stuff required.
631 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
632 is called AFTER this function!
634 *******************************************************************************/
636 void threads_impl_preinit(void)
638 pthread_mutex_init(&threadlistlock, NULL);
639 pthread_mutex_init(&stopworldlock, NULL);
641 /* initialize exit mutex and condition (on exit we join all
644 pthread_mutex_init(&mutex_join, NULL);
645 pthread_cond_init(&cond_join, NULL);
647 #if !defined(HAVE___THREAD)
648 pthread_key_create(&threads_current_threadobject_key, NULL);
651 /* create internal thread data-structure */
653 mainthreadobj = threads_create_thread();
655 mainthreadobj->object = NULL;
656 mainthreadobj->index = 1;
657 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
659 /* store the internal thread data-structure in the TSD */
661 threads_set_current_threadobject(mainthreadobj);
663 threads_sem_init(&suspend_ack, 0, 0);
667 /* threads_init ****************************************************************
669 Initializes the threads required by the JVM: main, finalizer.
671 *******************************************************************************/
673 bool threads_init(void)
675 java_objectheader *threadname;
677 java_objectheader *o;
679 #if defined(ENABLE_JAVASE)
680 java_lang_ThreadGroup *threadgroup;
684 #if defined(WITH_CLASSPATH_GNU)
685 java_lang_VMThread *vmt;
688 /* get methods we need in this file */
690 #if defined(WITH_CLASSPATH_GNU)
692 class_resolveclassmethod(class_java_lang_Thread,
694 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
695 class_java_lang_Thread,
699 class_resolveclassmethod(class_java_lang_Thread,
701 utf_new_char("(Ljava/lang/String;)V"),
702 class_java_lang_Thread,
706 if (method_thread_init == NULL)
709 /* create a java.lang.Thread for the main thread */
711 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
716 /* set the object in the internal data structure */
718 mainthreadobj->object = t;
720 /* thread is running */
722 mainthreadobj->state = THREAD_STATE_RUNNABLE;
724 mainthreadobj->next = mainthreadobj;
725 mainthreadobj->prev = mainthreadobj;
727 threads_table_add(mainthreadobj);
729 /* mark main thread as Java thread */
731 mainthreadobj->flags = THREAD_FLAG_JAVA;
733 #if defined(ENABLE_INTRP)
734 /* create interpreter stack */
737 MSET(intrp_main_stack, 0, u1, opt_stacksize);
738 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
742 threadname = javastring_new(utf_new_char("main"));
744 #if defined(ENABLE_JAVASE)
745 /* allocate and init ThreadGroup */
747 threadgroup = (java_lang_ThreadGroup *)
748 native_new_and_init(class_java_lang_ThreadGroup);
750 if (threadgroup == NULL)
754 #if defined(WITH_CLASSPATH_GNU)
755 /* create a java.lang.VMThread for the main thread */
757 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
765 vmt->vmdata = (java_lang_Object *) mainthreadobj;
767 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
768 o = (java_objectheader *) t;
770 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
772 #elif defined(WITH_CLASSPATH_CLDC1_1)
775 t->vm_thread = (java_lang_Object *) mainthreadobj;
777 /* call public Thread(String name) */
779 o = (java_objectheader *) t;
781 (void) vm_call_method(method_thread_init, o, threadname);
787 #if defined(ENABLE_JAVASE)
788 t->group = threadgroup;
790 /* add main thread to java.lang.ThreadGroup */
792 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
794 utf_java_lang_Thread__V,
795 class_java_lang_ThreadGroup,
798 o = (java_objectheader *) threadgroup;
800 (void) vm_call_method(m, o, t);
806 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
808 /* initialize the thread attribute object */
810 if (pthread_attr_init(&threadattr)) {
811 log_println("pthread_attr_init failed: %s", strerror(errno));
815 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
817 /* everything's ok */
823 /* threads_startup_thread ******************************************************
825 Thread startup function called by pthread_create.
827 Thread which have a startup.function != NULL are marked as internal
828 threads. All other threads are threated as normal Java threads.
830 NOTE: This function is not called directly by pthread_create. The Boehm GC
831 inserts its own GC_start_routine in between, which then calls
835 t............the argument passed to pthread_create, ie. a pointer to
836 a startupinfo struct. CAUTION: When the `psem` semaphore
837 is posted, the startupinfo struct becomes invalid! (It
838 is allocated on the stack of threads_start_thread.)
840 ******************************************************************************/
842 static void *threads_startup_thread(void *t)
844 startupinfo *startup;
845 threadobject *thread;
846 #if defined(WITH_CLASSPATH_GNU)
847 java_lang_VMThread *vmt;
853 java_objectheader *o;
854 functionptr function;
856 #if defined(ENABLE_INTRP)
857 u1 *intrp_thread_stack;
859 /* create interpreter stack */
862 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
863 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
866 intrp_thread_stack = NULL;
869 /* get passed startupinfo structure and the values in there */
872 t = NULL; /* make sure it's not used wrongly */
874 thread = startup->thread;
875 function = startup->function;
876 psem = startup->psem;
878 /* Seems like we've encountered a situation where thread->tid was not set by
879 * pthread_create. We alleviate this problem by waiting for pthread_create
881 threads_sem_wait(startup->psem_first);
883 #if defined(__DARWIN__)
884 thread->mach_thread = mach_thread_self();
887 /* store the internal thread data-structure in the TSD */
889 threads_set_current_threadobject(thread);
891 /* thread is running */
893 thread->state = THREAD_STATE_RUNNABLE;
895 /* insert the thread into the threadlist and the threads table */
897 pthread_mutex_lock(&threadlistlock);
899 thread->prev = mainthreadobj;
900 thread->next = tnext = mainthreadobj->next;
901 mainthreadobj->next = thread;
902 tnext->prev = thread;
904 threads_table_add(thread);
906 pthread_mutex_unlock(&threadlistlock);
908 /* tell threads_startup_thread that we registered ourselves */
909 /* CAUTION: *startup becomes invalid with this! */
912 threads_sem_post(psem);
914 /* set our priority */
916 threads_set_thread_priority(thread->tid, thread->object->priority);
918 #if defined(ENABLE_INTRP)
919 /* set interpreter stack */
922 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
925 #if defined(ENABLE_JVMTI)
926 /* fire thread start event */
929 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
932 /* find and run the Thread.run()V method if no other function was passed */
934 if (function == NULL) {
935 /* this is a normal Java thread */
937 thread->flags |= THREAD_FLAG_JAVA;
939 #if defined(WITH_CLASSPATH_GNU)
940 /* We need to start the run method of
941 java.lang.VMThread. Since this is a final class, we can use
942 the class object directly. */
944 c = class_java_lang_VMThread;
945 #elif defined(WITH_CLASSPATH_CLDC1_1)
946 c = thread->object->header.vftbl->class;
949 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
952 vm_abort("threads_startup_thread: run() method not found in class");
954 /* set ThreadMXBean variables */
956 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
957 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
959 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
960 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
961 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
962 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
964 #if defined(WITH_CLASSPATH_GNU)
965 /* we need to start the run method of java.lang.VMThread */
967 vmt = (java_lang_VMThread *) thread->object->vmThread;
968 o = (java_objectheader *) vmt;
970 #elif defined(WITH_CLASSPATH_CLDC1_1)
971 o = (java_objectheader *) thread->object;
976 (void) vm_call_method(m, o);
979 /* this is an internal thread */
981 thread->flags |= THREAD_FLAG_INTERNAL;
983 /* set ThreadMXBean variables */
985 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
986 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
988 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
989 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
990 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
991 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
993 /* call passed function, e.g. finalizer_thread */
998 #if defined(ENABLE_JVMTI)
999 /* fire thread end event */
1002 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1005 if (!threads_detach_thread(thread))
1006 vm_abort("threads_startup_thread: threads_detach_thread failed");
1008 /* set ThreadMXBean variables */
1010 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1016 /* threads_impl_thread_start ***************************************************
1018 Start a thread in the JVM. Both (vm internal and java) thread
1022 thread....the thread object
1023 f.........function to run in the new thread. NULL means that the
1024 "run" method of the object `t` should be called
1026 ******************************************************************************/
1028 void threads_impl_thread_start(threadobject *thread, functionptr f)
1032 pthread_attr_t attr;
1033 startupinfo startup;
1035 /* fill startupinfo structure passed by pthread_create to
1036 * threads_startup_thread */
1038 startup.thread = thread;
1039 startup.function = f; /* maybe we don't call Thread.run()V */
1040 startup.psem = &sem;
1041 startup.psem_first = &sem_first;
1043 threads_sem_init(&sem, 0, 0);
1044 threads_sem_init(&sem_first, 0, 0);
1046 /* initialize thread attribute object */
1048 if (pthread_attr_init(&attr))
1049 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1051 /* initialize thread stacksize */
1053 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1054 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1056 /* create the thread */
1058 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1059 vm_abort("pthread_create failed: %s", strerror(errno));
1061 /* signal that pthread_create has returned, so thread->tid is valid */
1063 threads_sem_post(&sem_first);
1065 /* wait here until the thread has entered itself into the thread list */
1067 threads_sem_wait(&sem);
1072 sem_destroy(&sem_first);
1076 /* threads_set_thread_priority *************************************************
1078 Set the priority of the given thread.
1081 tid..........thread id
1082 priority.....priority to set
1084 ******************************************************************************/
1086 void threads_set_thread_priority(pthread_t tid, int priority)
1088 struct sched_param schedp;
1091 pthread_getschedparam(tid, &policy, &schedp);
1092 schedp.sched_priority = priority;
1093 pthread_setschedparam(tid, policy, &schedp);
1097 /* threads_attach_current_thread ***********************************************
1099 Attaches the current thread to the VM. Used in JNI.
1101 *******************************************************************************/
1103 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1105 threadobject *thread;
1107 java_objectheader *s;
1108 java_objectheader *o;
1109 java_lang_Thread *t;
1111 #if defined(ENABLE_JAVASE)
1112 java_lang_ThreadGroup *group;
1116 #if defined(WITH_CLASSPATH_GNU)
1117 java_lang_VMThread *vmt;
1120 /* create internal thread data-structure */
1122 thread = threads_create_thread();
1124 /* create a java.lang.Thread object */
1126 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1133 /* thread is running */
1135 thread->state = THREAD_STATE_RUNNABLE;
1137 /* insert the thread into the threadlist and the threads table */
1139 pthread_mutex_lock(&threadlistlock);
1141 thread->prev = mainthreadobj;
1142 thread->next = mainthreadobj->next;
1143 mainthreadobj->next = thread;
1144 thread->next->prev = thread;
1146 threads_table_add(thread);
1148 pthread_mutex_unlock(&threadlistlock);
1150 /* mark thread as Java thread */
1152 thread->flags = THREAD_FLAG_JAVA;
1155 thread->flags |= THREAD_FLAG_DAEMON;
1157 #if defined(ENABLE_INTRP)
1158 /* create interpreter stack */
1161 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1162 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1166 #if defined(WITH_CLASSPATH_GNU)
1167 /* create a java.lang.VMThread object */
1169 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1174 /* set the thread */
1177 vmt->vmdata = (java_lang_Object *) thread;
1178 #elif defined(WITH_CLASSPATH_CLDC1_1)
1179 t->vm_thread = (java_lang_Object *) thread;
1182 if (vm_aargs != NULL) {
1183 u = utf_new_char(vm_aargs->name);
1184 #if defined(ENABLE_JAVASE)
1185 group = (java_lang_ThreadGroup *) vm_aargs->group;
1190 #if defined(ENABLE_JAVASE)
1191 group = mainthreadobj->object->group;
1195 /* the the thread name */
1197 s = javastring_new(u);
1199 /* for convenience */
1201 o = (java_objectheader *) thread->object;
1203 #if defined(WITH_CLASSPATH_GNU)
1204 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1206 #elif defined(WITH_CLASSPATH_CLDC1_1)
1207 (void) vm_call_method(method_thread_init, o, s);
1213 #if defined(ENABLE_JAVASE)
1214 /* store the thread group in the object */
1216 thread->object->group = group;
1218 /* add thread to given thread-group */
1220 m = class_resolveclassmethod(group->header.vftbl->class,
1222 utf_java_lang_Thread__V,
1223 class_java_lang_ThreadGroup,
1226 o = (java_objectheader *) group;
1228 (void) vm_call_method(m, o, t);
1238 /* threads_detach_thread *******************************************************
1240 Detaches the passed thread from the VM. Used in JNI.
1242 *******************************************************************************/
1244 bool threads_detach_thread(threadobject *thread)
1246 #if defined(ENABLE_JAVASE)
1247 java_lang_ThreadGroup *group;
1249 java_objectheader *o;
1250 java_lang_Thread *t;
1253 /* Allow lock record pools to be used by other threads. They
1254 cannot be deleted so we'd better not waste them. */
1256 /* XXX We have to find a new way to free lock records */
1257 /* with the new locking algorithm. */
1258 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1260 /* XXX implement uncaught exception stuff (like JamVM does) */
1262 #if defined(ENABLE_JAVASE)
1263 /* remove thread from the thread group */
1265 group = thread->object->group;
1267 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1269 if (group != NULL) {
1270 m = class_resolveclassmethod(group->header.vftbl->class,
1272 utf_java_lang_Thread__V,
1273 class_java_lang_ThreadGroup,
1279 o = (java_objectheader *) group;
1282 (void) vm_call_method(m, o, t);
1289 /* thread is terminated */
1291 thread->state = THREAD_STATE_TERMINATED;
1293 /* lock thread list */
1295 pthread_mutex_lock(&threadlistlock);
1297 /* remove thread from thread list and threads table */
1299 thread->next->prev = thread->prev;
1300 thread->prev->next = thread->next;
1302 threads_table_remove(thread);
1304 /* unlock thread list */
1306 pthread_mutex_unlock(&threadlistlock);
1308 /* signal that this thread has finished */
1310 pthread_mutex_lock(&mutex_join);
1311 pthread_cond_signal(&cond_join);
1312 pthread_mutex_unlock(&mutex_join);
1314 /* free the vm internal thread object */
1316 #if defined(ENABLE_GC_BOEHM)
1319 FREE(thread, threadobject);
1322 #if defined(ENABLE_STATISTICS)
1324 size_threadobject -= sizeof(threadobject);
1331 /* threads_find_non_daemon_thread **********************************************
1333 Helper function used by threads_join_all_threads for finding
1334 non-daemon threads that are still running.
1336 *******************************************************************************/
1338 static threadobject *threads_find_non_daemon_thread(void)
1340 threadobject *thread;
1342 /* lock the thread list */
1344 pthread_mutex_lock(&threadlistlock);
1346 /* iterate over all threads */
1348 thread = mainthreadobj->next;
1350 while (thread != mainthreadobj) {
1351 if (!(thread->flags & THREAD_FLAG_DAEMON)) {
1352 /* unlock thread list */
1354 pthread_mutex_unlock(&threadlistlock);
1359 thread = thread->next;
1362 /* unlock thread list */
1364 pthread_mutex_unlock(&threadlistlock);
1370 /* threads_join_all_threads ****************************************************
1372 Join all non-daemon threads.
1374 *******************************************************************************/
1376 void threads_join_all_threads(void)
1378 threadobject *thread;
1380 /* get current thread */
1382 thread = THREADOBJECT;
1384 /* this thread is waiting for all non-daemon threads to exit */
1386 thread->state = THREAD_STATE_WAITING;
1388 /* enter join mutex */
1390 pthread_mutex_lock(&mutex_join);
1392 /* wait for condition as long as we have non-daemon threads */
1394 while (threads_find_non_daemon_thread() != NULL)
1395 pthread_cond_wait(&cond_join, &mutex_join);
1397 /* leave join mutex */
1399 pthread_mutex_unlock(&mutex_join);
1403 /* threads_timespec_earlier ****************************************************
1405 Return true if timespec tv1 is earlier than timespec tv2.
1408 tv1..........first timespec
1409 tv2..........second timespec
1412 true, if the first timespec is earlier
1414 *******************************************************************************/
1416 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1417 const struct timespec *tv2)
1419 return (tv1->tv_sec < tv2->tv_sec)
1421 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1425 /* threads_current_time_is_earlier_than ****************************************
1427 Check if the current time is earlier than the given timespec.
1430 tv...........the timespec to compare against
1433 true, if the current time is earlier
1435 *******************************************************************************/
1437 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1439 struct timeval tvnow;
1440 struct timespec tsnow;
1442 /* get current time */
1444 if (gettimeofday(&tvnow, NULL) != 0)
1445 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1447 /* convert it to a timespec */
1449 tsnow.tv_sec = tvnow.tv_sec;
1450 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1452 /* compare current time with the given timespec */
1454 return threads_timespec_earlier(&tsnow, tv);
1458 /* threads_wait_with_timeout ***************************************************
1460 Wait until the given point in time on a monitor until either
1461 we are notified, we are interrupted, or the time is up.
1464 t............the current thread
1465 wakeupTime...absolute (latest) wakeup time
1466 If both tv_sec and tv_nsec are zero, this function
1467 waits for an unlimited amount of time.
1470 true.........if the wait has been interrupted,
1471 false........if the wait was ended by notification or timeout
1473 *******************************************************************************/
1475 static bool threads_wait_with_timeout(threadobject *thread,
1476 struct timespec *wakeupTime)
1478 bool wasinterrupted;
1480 /* acquire the waitmutex */
1482 pthread_mutex_lock(&thread->waitmutex);
1484 /* mark us as sleeping */
1486 thread->sleeping = true;
1488 /* wait on waitcond */
1490 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1492 while (!thread->interrupted && !thread->signaled
1493 && threads_current_time_is_earlier_than(wakeupTime))
1495 thread->state = THREAD_STATE_TIMED_WAITING;
1497 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1500 thread->state = THREAD_STATE_RUNNABLE;
1505 while (!thread->interrupted && !thread->signaled) {
1506 thread->state = THREAD_STATE_WAITING;
1508 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1510 thread->state = THREAD_STATE_RUNNABLE;
1514 /* check if we were interrupted */
1516 wasinterrupted = thread->interrupted;
1518 /* reset all flags */
1520 thread->interrupted = false;
1521 thread->signaled = false;
1522 thread->sleeping = false;
1524 /* release the waitmutex */
1526 pthread_mutex_unlock(&thread->waitmutex);
1528 return wasinterrupted;
1532 /* threads_wait_with_timeout_relative ******************************************
1534 Wait for the given maximum amount of time on a monitor until either
1535 we are notified, we are interrupted, or the time is up.
1538 t............the current thread
1539 millis.......milliseconds to wait
1540 nanos........nanoseconds to wait
1543 true.........if the wait has been interrupted,
1544 false........if the wait was ended by notification or timeout
1546 *******************************************************************************/
1548 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1551 struct timespec wakeupTime;
1553 /* calculate the the (latest) wakeup time */
1555 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1559 return threads_wait_with_timeout(thread, &wakeupTime);
1563 /* threads_calc_absolute_time **************************************************
1565 Calculate the absolute point in time a given number of ms and ns from now.
1568 millis............milliseconds from now
1569 nanos.............nanoseconds from now
1572 *tm...............receives the timespec of the absolute point in time
1574 *******************************************************************************/
1576 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1578 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1581 gettimeofday(&tv, NULL);
1582 tv.tv_sec += millis / 1000;
1584 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1585 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1586 tm->tv_nsec = nsec % 1000000000;
1595 /* threads_thread_interrupt ****************************************************
1597 Interrupt the given thread.
1599 The thread gets the "waitcond" signal and
1600 its interrupted flag is set to true.
1603 thread............the thread to interrupt
1605 *******************************************************************************/
1607 void threads_thread_interrupt(threadobject *thread)
1609 /* Signal the thread a "waitcond" and tell it that it has been
1612 pthread_mutex_lock(&thread->waitmutex);
1614 /* Interrupt blocking system call using a signal. */
1616 pthread_kill(thread->tid, SIGHUP);
1618 if (thread->sleeping)
1619 pthread_cond_signal(&thread->waitcond);
1621 thread->interrupted = true;
1623 pthread_mutex_unlock(&thread->waitmutex);
1627 /* threads_check_if_interrupted_and_reset **************************************
1629 Check if the current thread has been interrupted and reset the
1633 true, if the current thread had been interrupted
1635 *******************************************************************************/
1637 bool threads_check_if_interrupted_and_reset(void)
1639 threadobject *thread;
1642 thread = THREADOBJECT;
1644 /* get interrupted flag */
1646 intr = thread->interrupted;
1648 /* reset interrupted flag */
1650 thread->interrupted = false;
1656 /* threads_thread_has_been_interrupted *****************************************
1658 Check if the given thread has been interrupted
1661 t............the thread to check
1664 true, if the given thread had been interrupted
1666 *******************************************************************************/
1668 bool threads_thread_has_been_interrupted(threadobject *thread)
1670 return thread->interrupted;
1674 /* threads_sleep ***************************************************************
1676 Sleep the current thread for the specified amount of time.
1678 *******************************************************************************/
1680 void threads_sleep(s8 millis, s4 nanos)
1682 threadobject *thread;
1683 struct timespec wakeupTime;
1684 bool wasinterrupted;
1686 thread = THREADOBJECT;
1688 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1690 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1693 exceptions_throw_interruptedexception();
1697 /* threads_yield ***************************************************************
1699 Yield to the scheduler.
1701 *******************************************************************************/
1703 void threads_yield(void)
1710 * These are local overrides for various environment variables in Emacs.
1711 * Please do not remove this and leave it at the end of the file, where
1712 * Emacs will automagically detect them.
1713 * ---------------------------------------------------------------------
1716 * indent-tabs-mode: t
1720 * vim:noexpandtab:sw=4:ts=4: