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 7830 2007-04-26 11:14:39Z 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_start_thread ********************************************************
1018 Start a thread in the JVM. Both (vm internal and java) thread objects exist.
1021 thread.......the thread object
1022 function.....function to run in the new thread. NULL means that the
1023 "run" method of the object `t` should be called
1025 ******************************************************************************/
1027 void threads_start_thread(threadobject *thread, functionptr function)
1031 pthread_attr_t attr;
1032 startupinfo startup;
1034 /* fill startupinfo structure passed by pthread_create to
1035 * threads_startup_thread */
1037 startup.thread = thread;
1038 startup.function = function; /* maybe we don't call Thread.run()V */
1039 startup.psem = &sem;
1040 startup.psem_first = &sem_first;
1042 threads_sem_init(&sem, 0, 0);
1043 threads_sem_init(&sem_first, 0, 0);
1045 /* initialize thread attribute object */
1047 if (pthread_attr_init(&attr))
1048 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1050 /* initialize thread stacksize */
1052 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1053 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1055 /* create the thread */
1057 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1058 vm_abort("pthread_create failed: %s", strerror(errno));
1060 /* signal that pthread_create has returned, so thread->tid is valid */
1062 threads_sem_post(&sem_first);
1064 /* wait here until the thread has entered itself into the thread list */
1066 threads_sem_wait(&sem);
1071 sem_destroy(&sem_first);
1075 /* threads_set_thread_priority *************************************************
1077 Set the priority of the given thread.
1080 tid..........thread id
1081 priority.....priority to set
1083 ******************************************************************************/
1085 void threads_set_thread_priority(pthread_t tid, int priority)
1087 struct sched_param schedp;
1090 pthread_getschedparam(tid, &policy, &schedp);
1091 schedp.sched_priority = priority;
1092 pthread_setschedparam(tid, policy, &schedp);
1096 /* threads_attach_current_thread ***********************************************
1098 Attaches the current thread to the VM. Used in JNI.
1100 *******************************************************************************/
1102 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1104 threadobject *thread;
1106 java_objectheader *s;
1107 java_objectheader *o;
1108 java_lang_Thread *t;
1110 #if defined(ENABLE_JAVASE)
1111 java_lang_ThreadGroup *group;
1115 #if defined(WITH_CLASSPATH_GNU)
1116 java_lang_VMThread *vmt;
1119 /* create internal thread data-structure */
1121 thread = threads_create_thread();
1123 /* create a java.lang.Thread object */
1125 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1132 /* thread is running */
1134 thread->state = THREAD_STATE_RUNNABLE;
1136 /* insert the thread into the threadlist and the threads table */
1138 pthread_mutex_lock(&threadlistlock);
1140 thread->prev = mainthreadobj;
1141 thread->next = mainthreadobj->next;
1142 mainthreadobj->next = thread;
1143 thread->next->prev = thread;
1145 threads_table_add(thread);
1147 pthread_mutex_unlock(&threadlistlock);
1149 /* mark thread as Java thread */
1151 thread->flags = THREAD_FLAG_JAVA;
1154 thread->flags |= THREAD_FLAG_DAEMON;
1156 #if defined(ENABLE_INTRP)
1157 /* create interpreter stack */
1160 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1161 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1165 #if defined(WITH_CLASSPATH_GNU)
1166 /* create a java.lang.VMThread object */
1168 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1173 /* set the thread */
1176 vmt->vmdata = (java_lang_Object *) thread;
1177 #elif defined(WITH_CLASSPATH_CLDC1_1)
1178 t->vm_thread = (java_lang_Object *) thread;
1181 if (vm_aargs != NULL) {
1182 u = utf_new_char(vm_aargs->name);
1183 #if defined(ENABLE_JAVASE)
1184 group = (java_lang_ThreadGroup *) vm_aargs->group;
1189 #if defined(ENABLE_JAVASE)
1190 group = mainthreadobj->object->group;
1194 /* the the thread name */
1196 s = javastring_new(u);
1198 /* for convenience */
1200 o = (java_objectheader *) thread->object;
1202 #if defined(WITH_CLASSPATH_GNU)
1203 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1205 #elif defined(WITH_CLASSPATH_CLDC1_1)
1206 (void) vm_call_method(method_thread_init, o, s);
1212 #if defined(ENABLE_JAVASE)
1213 /* store the thread group in the object */
1215 thread->object->group = group;
1217 /* add thread to given thread-group */
1219 m = class_resolveclassmethod(group->header.vftbl->class,
1221 utf_java_lang_Thread__V,
1222 class_java_lang_ThreadGroup,
1225 o = (java_objectheader *) group;
1227 (void) vm_call_method(m, o, t);
1237 /* threads_detach_thread *******************************************************
1239 Detaches the passed thread from the VM. Used in JNI.
1241 *******************************************************************************/
1243 bool threads_detach_thread(threadobject *thread)
1245 #if defined(ENABLE_JAVASE)
1246 java_lang_ThreadGroup *group;
1248 java_objectheader *o;
1249 java_lang_Thread *t;
1252 /* Allow lock record pools to be used by other threads. They
1253 cannot be deleted so we'd better not waste them. */
1255 /* XXX We have to find a new way to free lock records */
1256 /* with the new locking algorithm. */
1257 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1259 /* XXX implement uncaught exception stuff (like JamVM does) */
1261 #if defined(ENABLE_JAVASE)
1262 /* remove thread from the thread group */
1264 group = thread->object->group;
1266 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1268 if (group != NULL) {
1269 m = class_resolveclassmethod(group->header.vftbl->class,
1271 utf_java_lang_Thread__V,
1272 class_java_lang_ThreadGroup,
1278 o = (java_objectheader *) group;
1281 (void) vm_call_method(m, o, t);
1288 /* thread is terminated */
1290 thread->state = THREAD_STATE_TERMINATED;
1292 /* lock thread list */
1294 pthread_mutex_lock(&threadlistlock);
1296 /* remove thread from thread list and threads table */
1298 thread->next->prev = thread->prev;
1299 thread->prev->next = thread->next;
1301 threads_table_remove(thread);
1303 /* unlock thread list */
1305 pthread_mutex_unlock(&threadlistlock);
1307 /* signal that this thread has finished */
1309 pthread_mutex_lock(&mutex_join);
1310 pthread_cond_signal(&cond_join);
1311 pthread_mutex_unlock(&mutex_join);
1313 /* free the vm internal thread object */
1315 #if defined(ENABLE_GC_BOEHM)
1318 FREE(thread, threadobject);
1321 #if defined(ENABLE_STATISTICS)
1323 size_threadobject -= sizeof(threadobject);
1330 /* threads_find_non_daemon_thread **********************************************
1332 Helper function used by threads_join_all_threads for finding
1333 non-daemon threads that are still running.
1335 *******************************************************************************/
1337 static threadobject *threads_find_non_daemon_thread(void)
1339 threadobject *thread;
1341 /* lock the thread list */
1343 pthread_mutex_lock(&threadlistlock);
1345 /* iterate over all threads */
1347 thread = mainthreadobj->next;
1349 while (thread != mainthreadobj) {
1350 if (!(thread->flags & THREAD_FLAG_DAEMON)) {
1351 /* unlock thread list */
1353 pthread_mutex_unlock(&threadlistlock);
1358 thread = thread->next;
1361 /* unlock thread list */
1363 pthread_mutex_unlock(&threadlistlock);
1369 /* threads_join_all_threads ****************************************************
1371 Join all non-daemon threads.
1373 *******************************************************************************/
1375 void threads_join_all_threads(void)
1377 threadobject *thread;
1379 /* get current thread */
1381 thread = THREADOBJECT;
1383 /* this thread is waiting for all non-daemon threads to exit */
1385 thread->state = THREAD_STATE_WAITING;
1387 /* enter join mutex */
1389 pthread_mutex_lock(&mutex_join);
1391 /* wait for condition as long as we have non-daemon threads */
1393 while (threads_find_non_daemon_thread() != NULL)
1394 pthread_cond_wait(&cond_join, &mutex_join);
1396 /* leave join mutex */
1398 pthread_mutex_unlock(&mutex_join);
1402 /* threads_timespec_earlier ****************************************************
1404 Return true if timespec tv1 is earlier than timespec tv2.
1407 tv1..........first timespec
1408 tv2..........second timespec
1411 true, if the first timespec is earlier
1413 *******************************************************************************/
1415 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1416 const struct timespec *tv2)
1418 return (tv1->tv_sec < tv2->tv_sec)
1420 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1424 /* threads_current_time_is_earlier_than ****************************************
1426 Check if the current time is earlier than the given timespec.
1429 tv...........the timespec to compare against
1432 true, if the current time is earlier
1434 *******************************************************************************/
1436 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1438 struct timeval tvnow;
1439 struct timespec tsnow;
1441 /* get current time */
1443 if (gettimeofday(&tvnow, NULL) != 0)
1444 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1446 /* convert it to a timespec */
1448 tsnow.tv_sec = tvnow.tv_sec;
1449 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1451 /* compare current time with the given timespec */
1453 return threads_timespec_earlier(&tsnow, tv);
1457 /* threads_wait_with_timeout ***************************************************
1459 Wait until the given point in time on a monitor until either
1460 we are notified, we are interrupted, or the time is up.
1463 t............the current thread
1464 wakeupTime...absolute (latest) wakeup time
1465 If both tv_sec and tv_nsec are zero, this function
1466 waits for an unlimited amount of time.
1469 true.........if the wait has been interrupted,
1470 false........if the wait was ended by notification or timeout
1472 *******************************************************************************/
1474 static bool threads_wait_with_timeout(threadobject *thread,
1475 struct timespec *wakeupTime)
1477 bool wasinterrupted;
1479 /* acquire the waitmutex */
1481 pthread_mutex_lock(&thread->waitmutex);
1483 /* mark us as sleeping */
1485 thread->sleeping = true;
1487 /* wait on waitcond */
1489 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1491 while (!thread->interrupted && !thread->signaled
1492 && threads_current_time_is_earlier_than(wakeupTime))
1494 thread->state = THREAD_STATE_TIMED_WAITING;
1496 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1499 thread->state = THREAD_STATE_RUNNABLE;
1504 while (!thread->interrupted && !thread->signaled) {
1505 thread->state = THREAD_STATE_WAITING;
1507 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1509 thread->state = THREAD_STATE_RUNNABLE;
1513 /* check if we were interrupted */
1515 wasinterrupted = thread->interrupted;
1517 /* reset all flags */
1519 thread->interrupted = false;
1520 thread->signaled = false;
1521 thread->sleeping = false;
1523 /* release the waitmutex */
1525 pthread_mutex_unlock(&thread->waitmutex);
1527 return wasinterrupted;
1531 /* threads_wait_with_timeout_relative ******************************************
1533 Wait for the given maximum amount of time on a monitor until either
1534 we are notified, we are interrupted, or the time is up.
1537 t............the current thread
1538 millis.......milliseconds to wait
1539 nanos........nanoseconds to wait
1542 true.........if the wait has been interrupted,
1543 false........if the wait was ended by notification or timeout
1545 *******************************************************************************/
1547 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1550 struct timespec wakeupTime;
1552 /* calculate the the (latest) wakeup time */
1554 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1558 return threads_wait_with_timeout(thread, &wakeupTime);
1562 /* threads_calc_absolute_time **************************************************
1564 Calculate the absolute point in time a given number of ms and ns from now.
1567 millis............milliseconds from now
1568 nanos.............nanoseconds from now
1571 *tm...............receives the timespec of the absolute point in time
1573 *******************************************************************************/
1575 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1577 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1580 gettimeofday(&tv, NULL);
1581 tv.tv_sec += millis / 1000;
1583 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1584 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1585 tm->tv_nsec = nsec % 1000000000;
1594 /* threads_thread_interrupt ****************************************************
1596 Interrupt the given thread.
1598 The thread gets the "waitcond" signal and
1599 its interrupted flag is set to true.
1602 thread............the thread to interrupt
1604 *******************************************************************************/
1606 void threads_thread_interrupt(threadobject *thread)
1608 /* Signal the thread a "waitcond" and tell it that it has been
1611 pthread_mutex_lock(&thread->waitmutex);
1613 /* Interrupt blocking system call using a signal. */
1615 pthread_kill(thread->tid, SIGHUP);
1617 if (thread->sleeping)
1618 pthread_cond_signal(&thread->waitcond);
1620 thread->interrupted = true;
1622 pthread_mutex_unlock(&thread->waitmutex);
1626 /* threads_check_if_interrupted_and_reset **************************************
1628 Check if the current thread has been interrupted and reset the
1632 true, if the current thread had been interrupted
1634 *******************************************************************************/
1636 bool threads_check_if_interrupted_and_reset(void)
1638 threadobject *thread;
1641 thread = THREADOBJECT;
1643 /* get interrupted flag */
1645 intr = thread->interrupted;
1647 /* reset interrupted flag */
1649 thread->interrupted = false;
1655 /* threads_thread_has_been_interrupted *****************************************
1657 Check if the given thread has been interrupted
1660 t............the thread to check
1663 true, if the given thread had been interrupted
1665 *******************************************************************************/
1667 bool threads_thread_has_been_interrupted(threadobject *thread)
1669 return thread->interrupted;
1673 /* threads_sleep ***************************************************************
1675 Sleep the current thread for the specified amount of time.
1677 *******************************************************************************/
1679 void threads_sleep(s8 millis, s4 nanos)
1681 threadobject *thread;
1682 struct timespec wakeupTime;
1683 bool wasinterrupted;
1685 thread = THREADOBJECT;
1687 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1689 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1692 exceptions_throw_interruptedexception();
1696 /* threads_yield ***************************************************************
1698 Yield to the scheduler.
1700 *******************************************************************************/
1702 void threads_yield(void)
1709 * These are local overrides for various environment variables in Emacs.
1710 * Please do not remove this and leave it at the end of the file, where
1711 * Emacs will automagically detect them.
1712 * ---------------------------------------------------------------------
1715 * indent-tabs-mode: t
1719 * vim:noexpandtab:sw=4:ts=4: