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 7478 2007-03-08 02:59:31Z michi $
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(__DARWIN__)
92 # if defined(__LINUX__)
93 # define GC_LINUX_THREADS
94 # elif defined(__MIPS__)
95 # define GC_IRIX_THREADS
97 # include <semaphore.h>
98 # if defined(ENABLE_GC_BOEHM)
99 # include "mm/boehm-gc/include/gc.h"
103 #if defined(ENABLE_JVMTI)
104 #include "native/jvmti/cacaodbg.h"
107 #if defined(__DARWIN__)
108 /* Darwin has no working semaphore implementation. This one is taken
112 This is a very simple semaphore implementation for darwin. It
113 is implemented in terms of pthreads calls so it isn't async signal
114 safe. This isn't a problem because signals aren't used to
115 suspend threads on darwin.
118 static int sem_init(sem_t *sem, int pshared, int value)
125 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
128 if (pthread_cond_init(&sem->cond, NULL) < 0)
134 static int sem_post(sem_t *sem)
136 if (pthread_mutex_lock(&sem->mutex) < 0)
141 if (pthread_cond_signal(&sem->cond) < 0) {
142 pthread_mutex_unlock(&sem->mutex);
146 if (pthread_mutex_unlock(&sem->mutex) < 0)
152 static int sem_wait(sem_t *sem)
154 if (pthread_mutex_lock(&sem->mutex) < 0)
157 while (sem->value == 0) {
158 pthread_cond_wait(&sem->cond, &sem->mutex);
163 if (pthread_mutex_unlock(&sem->mutex) < 0)
169 static int sem_destroy(sem_t *sem)
171 if (pthread_cond_destroy(&sem->cond) < 0)
174 if (pthread_mutex_destroy(&sem->mutex) < 0)
179 #endif /* defined(__DARWIN__) */
182 /* internally used constants **************************************************/
184 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
185 #define STOPWORLD_FROM_GC 1
186 #define STOPWORLD_FROM_CLASS_NUMBERING 2
188 #define THREADS_INITIAL_TABLE_SIZE 8
191 /* startupinfo *****************************************************************
193 Struct used to pass info from threads_start_thread to
194 threads_startup_thread.
196 ******************************************************************************/
199 threadobject *thread; /* threadobject for this thread */
200 functionptr function; /* function to run in the new thread */
201 sem_t *psem; /* signals when thread has been entered */
202 /* in the thread list */
203 sem_t *psem_first; /* signals when pthread_create has returned */
207 /* prototypes *****************************************************************/
209 static void threads_table_init(void);
210 static s4 threads_table_add(threadobject *thread);
211 static void threads_table_remove(threadobject *thread);
212 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
214 #if !defined(NDEBUG) && 0
215 static void threads_table_dump(FILE *file);
218 /******************************************************************************/
219 /* GLOBAL VARIABLES */
220 /******************************************************************************/
222 /* the main thread */
223 threadobject *mainthreadobj;
225 static methodinfo *method_thread_init;
227 /* the thread object of the current thread */
228 /* This is either a thread-local variable defined with __thread, or */
229 /* a thread-specific value stored with key threads_current_threadobject_key. */
230 #if defined(HAVE___THREAD)
231 __thread threadobject *threads_current_threadobject;
233 pthread_key_t threads_current_threadobject_key;
236 /* global threads table */
237 static threads_table_t threads_table;
239 /* global compiler mutex */
240 static pthread_mutex_t compiler_mutex;
242 /* global mutex for changing the thread list */
243 static pthread_mutex_t threadlistlock;
245 /* global mutex for stop-the-world */
246 static pthread_mutex_t stopworldlock;
248 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
250 static volatile int stopworldwhere;
252 /* semaphore used for acknowleding thread suspension */
253 static sem_t suspend_ack;
254 #if defined(__MIPS__)
255 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
256 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
259 static pthread_attr_t threadattr;
261 /* mutexes used by the fake atomic instructions */
262 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
263 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
264 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
265 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
269 /* threads_sem_init ************************************************************
271 Initialize a semaphore. Checks against errors and interruptions.
274 sem..............the semaphore to initialize
275 shared...........true if this semaphore will be shared between processes
276 value............the initial value for the semaphore
278 *******************************************************************************/
280 void threads_sem_init(sem_t *sem, bool shared, int value)
287 r = sem_init(sem, shared, value);
290 } while (errno == EINTR);
292 vm_abort("sem_init failed: %s", strerror(errno));
296 /* threads_sem_wait ************************************************************
298 Wait for a semaphore, non-interruptible.
300 IMPORTANT: Always use this function instead of `sem_wait` directly, as
301 `sem_wait` may be interrupted by signals!
304 sem..............the semaphore to wait on
306 *******************************************************************************/
308 void threads_sem_wait(sem_t *sem)
318 } while (errno == EINTR);
320 vm_abort("sem_wait failed: %s", strerror(errno));
324 /* threads_sem_post ************************************************************
326 Increase the count of a semaphore. Checks for errors.
329 sem..............the semaphore to increase the count of
331 *******************************************************************************/
333 void threads_sem_post(sem_t *sem)
339 /* unlike sem_wait, sem_post is not interruptible */
345 vm_abort("sem_post failed: %s", strerror(errno));
349 /* compiler_lock ***************************************************************
351 Enter the compiler lock.
353 ******************************************************************************/
355 void compiler_lock(void)
357 pthread_mutex_lock(&compiler_mutex);
361 /* compiler_unlock *************************************************************
363 Release the compiler lock.
365 ******************************************************************************/
367 void compiler_unlock(void)
369 pthread_mutex_unlock(&compiler_mutex);
373 /* lock_stopworld **************************************************************
375 Enter the stopworld lock, specifying why the world shall be stopped.
378 where........ STOPWORLD_FROM_GC (1) from within GC
379 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
381 ******************************************************************************/
383 void lock_stopworld(int where)
385 pthread_mutex_lock(&stopworldlock);
386 stopworldwhere = where;
390 /* unlock_stopworld ************************************************************
392 Release the stopworld lock.
394 ******************************************************************************/
396 void unlock_stopworld(void)
399 pthread_mutex_unlock(&stopworldlock);
402 #if !defined(__DARWIN__)
403 /* Caller must hold threadlistlock */
404 static int threads_cast_sendsignals(int sig, int count)
407 threadobject *tobj = mainthreadobj;
408 threadobject *self = THREADOBJECT;
414 } while (tobj != mainthreadobj);
417 assert(tobj == mainthreadobj);
421 pthread_kill(tobj->tid, sig);
423 } while (tobj != mainthreadobj);
430 static void threads_cast_darwinstop(void)
432 threadobject *tobj = mainthreadobj;
433 threadobject *self = THREADOBJECT;
438 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
439 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
440 #if defined(__I386__)
441 i386_thread_state_t thread_state;
443 ppc_thread_state_t thread_state;
445 mach_port_t thread = tobj->mach_thread;
448 r = thread_suspend(thread);
450 if (r != KERN_SUCCESS)
451 vm_abort("thread_suspend failed");
453 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
454 &thread_state_count);
456 if (r != KERN_SUCCESS)
457 vm_abort("thread_get_state failed");
459 thread_restartcriticalsection((ucontext_t *) &thread_state);
461 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
464 if (r != KERN_SUCCESS)
465 vm_abort("thread_set_state failed");
469 } while (tobj != mainthreadobj);
472 static void threads_cast_darwinresume(void)
474 threadobject *tobj = mainthreadobj;
475 threadobject *self = THREADOBJECT;
480 mach_port_t thread = tobj->mach_thread;
483 r = thread_resume(thread);
485 if (r != KERN_SUCCESS)
486 vm_abort("thread_resume failed");
490 } while (tobj != mainthreadobj);
495 #if defined(__MIPS__)
496 static void threads_cast_irixresume(void)
498 pthread_mutex_lock(&suspend_ack_lock);
499 pthread_cond_broadcast(&suspend_cond);
500 pthread_mutex_unlock(&suspend_ack_lock);
504 #if !defined(DISABLE_GC)
506 void threads_cast_stopworld(void)
508 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
512 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
513 pthread_mutex_lock(&threadlistlock);
515 #if defined(__DARWIN__)
516 threads_cast_darwinstop();
517 #elif defined(__CYGWIN__)
521 count = threads_cast_sendsignals(GC_signum1(), 0);
522 for (i = 0; i < count; i++)
523 threads_sem_wait(&suspend_ack);
526 pthread_mutex_unlock(&threadlistlock);
529 void threads_cast_startworld(void)
531 pthread_mutex_lock(&threadlistlock);
532 #if defined(__DARWIN__)
533 threads_cast_darwinresume();
534 #elif defined(__MIPS__)
535 threads_cast_irixresume();
536 #elif defined(__CYGWIN__)
540 threads_cast_sendsignals(GC_signum2(), -1);
542 pthread_mutex_unlock(&threadlistlock);
547 #if !defined(__DARWIN__)
548 static void threads_sigsuspend_handler(ucontext_t *ctx)
553 /* XXX TWISTI: this is just a quick hack */
554 #if defined(ENABLE_JIT)
555 thread_restartcriticalsection(ctx);
558 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
559 (not POSIX async-safe). */
560 #if defined(__IRIX__)
561 pthread_mutex_lock(&suspend_ack_lock);
562 threads_sem_post(&suspend_ack);
563 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
564 pthread_mutex_unlock(&suspend_ack_lock);
565 #elif defined(__CYGWIN__)
569 threads_sem_post(&suspend_ack);
573 sigdelset(&sigs, sig);
578 /* This function is called from Boehm GC code. */
580 int cacao_suspendhandler(ucontext_t *ctx)
582 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
585 threads_sigsuspend_handler(ctx);
590 #endif /* DISABLE_GC */
592 /* threads_set_current_threadobject ********************************************
594 Set the current thread object.
597 thread.......the thread object to set
599 *******************************************************************************/
601 static void threads_set_current_threadobject(threadobject *thread)
603 #if !defined(HAVE___THREAD)
604 pthread_setspecific(threads_current_threadobject_key, thread);
606 threads_current_threadobject = thread;
611 /* threads_init_threadobject **************************************************
613 Initialize implementation fields of a threadobject.
616 thread............the threadobject
618 ******************************************************************************/
620 static void threads_init_threadobject(threadobject *thread)
622 thread->tid = pthread_self();
626 /* TODO destroy all those things */
627 pthread_mutex_init(&(thread->joinmutex), NULL);
628 pthread_cond_init(&(thread->joincond), NULL);
630 pthread_mutex_init(&(thread->waitmutex), NULL);
631 pthread_cond_init(&(thread->waitcond), NULL);
633 thread->interrupted = false;
634 thread->signaled = false;
635 thread->sleeping = false;
639 /* threads_get_current_threadobject ********************************************
641 Return the threadobject of the current thread.
644 the current threadobject * (an instance of java.lang.Thread)
646 *******************************************************************************/
648 threadobject *threads_get_current_threadobject(void)
654 /* threads_preinit *************************************************************
656 Do some early initialization of stuff required.
658 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
659 is called AFTER this function!
661 *******************************************************************************/
663 void threads_preinit(void)
665 pthread_mutexattr_t mutexattr;
666 pthread_mutexattr_init(&mutexattr);
667 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
668 pthread_mutex_init(&compiler_mutex, &mutexattr);
669 pthread_mutexattr_destroy(&mutexattr);
671 pthread_mutex_init(&threadlistlock, NULL);
672 pthread_mutex_init(&stopworldlock, NULL);
674 mainthreadobj = NEW(threadobject);
675 mainthreadobj->object = NULL;
676 mainthreadobj->tid = pthread_self();
677 mainthreadobj->index = 1;
678 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
680 #if !defined(HAVE___THREAD)
681 pthread_key_create(&threads_current_threadobject_key, NULL);
683 threads_set_current_threadobject(mainthreadobj);
685 threads_sem_init(&suspend_ack, 0, 0);
687 /* initialize the threads table */
689 threads_table_init();
691 /* initialize subsystems */
699 /* threads_init ****************************************************************
701 Initializes the threads required by the JVM: main, finalizer.
703 *******************************************************************************/
705 bool threads_init(void)
707 java_lang_String *threadname;
708 threadobject *tempthread;
709 java_objectheader *o;
711 #if defined(ENABLE_JAVASE)
712 java_lang_ThreadGroup *threadgroup;
717 #if defined(WITH_CLASSPATH_GNU)
718 java_lang_VMThread *vmt;
721 tempthread = mainthreadobj;
723 /* XXX We have to find a new way to free lock records */
724 /* with the new locking algorithm. */
725 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
728 /* This is kinda tricky, we grow the java.lang.Thread object so we
729 can keep the execution environment there. No Thread object must
730 have been created at an earlier time. */
732 class_java_lang_Thread->instancesize = sizeof(threadobject);
735 /* get methods we need in this file */
737 #if defined(WITH_CLASSPATH_GNU)
739 class_resolveclassmethod(class_java_lang_Thread,
741 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
742 class_java_lang_Thread,
746 class_resolveclassmethod(class_java_lang_Thread,
748 utf_new_char("(Ljava/lang/String;)V"),
749 class_java_lang_Thread,
753 if (method_thread_init == NULL)
756 /* create a vm internal thread object for the main thread */
757 /* XXX Michi: we do not need to do this here, we could use the one
758 created by threads_preinit() */
760 #if defined(ENABLE_GC_CACAO)
761 mainthreadobj = NEW(threadobject);
763 mainthreadobj = GCNEW(threadobject);
766 if (mainthreadobj == NULL)
769 /* create a java.lang.Thread for the main thread */
771 mainthreadobj->object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
773 if (mainthreadobj->object == NULL)
776 FREE(tempthread, threadobject);
778 threads_init_threadobject(mainthreadobj);
780 threads_set_current_threadobject(mainthreadobj);
782 lock_init_execution_env(mainthreadobj);
784 mainthreadobj->next = mainthreadobj;
785 mainthreadobj->prev = mainthreadobj;
787 threads_table_add(mainthreadobj);
789 /* mark main thread as Java thread */
791 mainthreadobj->flags = THREAD_FLAG_JAVA;
793 #if defined(ENABLE_INTRP)
794 /* create interpreter stack */
797 MSET(intrp_main_stack, 0, u1, opt_stacksize);
798 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
802 threadname = javastring_new(utf_new_char("main"));
804 #if defined(ENABLE_JAVASE)
805 /* allocate and init ThreadGroup */
807 threadgroup = (java_lang_ThreadGroup *)
808 native_new_and_init(class_java_lang_ThreadGroup);
810 if (threadgroup == NULL)
811 throw_exception_exit();
814 #if defined(WITH_CLASSPATH_GNU)
815 /* create a java.lang.VMThread for the main thread */
817 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
820 throw_exception_exit();
824 vmt->thread = mainthreadobj->object;
825 vmt->vmdata = (java_lang_Object *) mainthreadobj;
827 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
828 o = (java_objectheader *) mainthreadobj->object;
830 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
832 #elif defined(WITH_CLASSPATH_CLDC1_1)
835 mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
837 /* call public Thread(String name) */
839 o = (java_objectheader *) mainthreadobj->object;
841 (void) vm_call_method(method_thread_init, o, threadname);
847 #if defined(ENABLE_JAVASE)
848 mainthreadobj->object->group = threadgroup;
850 /* add main thread to java.lang.ThreadGroup */
852 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
854 utf_java_lang_Thread__V,
855 class_java_lang_ThreadGroup,
858 o = (java_objectheader *) threadgroup;
859 t = mainthreadobj->object;
861 (void) vm_call_method(m, o, t);
868 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
870 /* initialize the thread attribute object */
872 if (pthread_attr_init(&threadattr)) {
873 log_println("pthread_attr_init failed: %s", strerror(errno));
877 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
879 /* everything's ok */
885 /* threads_table_init *********************************************************
887 Initialize the global threads table.
889 ******************************************************************************/
891 static void threads_table_init(void)
896 size = THREADS_INITIAL_TABLE_SIZE;
898 threads_table.size = size;
899 threads_table.table = MNEW(threads_table_entry_t, size);
901 /* link the entries in a freelist */
903 for (i=0; i<size; ++i) {
904 threads_table.table[i].nextfree = i+1;
907 /* terminate the freelist */
909 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
913 /* threads_table_add **********************************************************
915 Add a thread to the global threads table. The index is entered in the
916 threadobject. The thinlock value for the thread is pre-computed.
919 thread............the thread to add
922 The table index for the newly added thread. This value has also been
923 entered in the threadobject.
926 The caller must hold the threadlistlock!
928 ******************************************************************************/
930 static s4 threads_table_add(threadobject *thread)
937 /* table[0] serves as the head of the freelist */
939 index = threads_table.table[0].nextfree;
941 /* if we got a free index, use it */
945 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
946 threads_table.table[index].thread = thread;
947 thread->index = index;
948 thread->thinlock = lock_pre_compute_thinlock(index);
952 /* we must grow the table */
954 oldsize = threads_table.size;
955 newsize = oldsize * 2;
957 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
959 threads_table.size = newsize;
961 /* link the new entries to a free list */
963 for (i=oldsize; i<newsize; ++i) {
964 threads_table.table[i].nextfree = i+1;
967 /* terminate the freelist */
969 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
971 /* use the first of the new entries */
978 /* threads_table_remove *******************************************************
980 Remove a thread from the global threads table.
983 thread............the thread to remove
986 The caller must hold the threadlistlock!
988 ******************************************************************************/
990 static void threads_table_remove(threadobject *thread)
994 index = thread->index;
996 /* put the index into the freelist */
998 threads_table.table[index] = threads_table.table[0];
999 threads_table.table[0].nextfree = index;
1001 /* delete the index in the threadobject to discover bugs */
1002 #if !defined(NDEBUG)
1008 /* threads_startup_thread ******************************************************
1010 Thread startup function called by pthread_create.
1012 Thread which have a startup.function != NULL are marked as internal
1013 threads. All other threads are threated as normal Java threads.
1015 NOTE: This function is not called directly by pthread_create. The Boehm GC
1016 inserts its own GC_start_routine in between, which then calls
1020 t............the argument passed to pthread_create, ie. a pointer to
1021 a startupinfo struct. CAUTION: When the `psem` semaphore
1022 is posted, the startupinfo struct becomes invalid! (It
1023 is allocated on the stack of threads_start_thread.)
1025 ******************************************************************************/
1027 static void *threads_startup_thread(void *t)
1029 startupinfo *startup;
1030 threadobject *thread;
1031 #if defined(WITH_CLASSPATH_GNU)
1032 java_lang_VMThread *vmt;
1035 threadobject *tnext;
1038 java_objectheader *o;
1039 functionptr function;
1041 #if defined(ENABLE_INTRP)
1042 u1 *intrp_thread_stack;
1044 /* create interpreter stack */
1047 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1048 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1051 intrp_thread_stack = NULL;
1054 /* get passed startupinfo structure and the values in there */
1057 t = NULL; /* make sure it's not used wrongly */
1059 thread = startup->thread;
1060 function = startup->function;
1061 psem = startup->psem;
1063 /* Seems like we've encountered a situation where thread->tid was not set by
1064 * pthread_create. We alleviate this problem by waiting for pthread_create
1066 threads_sem_wait(startup->psem_first);
1068 /* set the thread object */
1070 #if defined(__DARWIN__)
1071 thread->mach_thread = mach_thread_self();
1073 threads_set_current_threadobject(thread);
1075 /* insert the thread into the threadlist and the threads table */
1077 pthread_mutex_lock(&threadlistlock);
1079 thread->prev = mainthreadobj;
1080 thread->next = tnext = mainthreadobj->next;
1081 mainthreadobj->next = thread;
1082 tnext->prev = thread;
1084 threads_table_add(thread);
1086 pthread_mutex_unlock(&threadlistlock);
1088 /* init data structures of this thread */
1090 lock_init_execution_env(thread);
1092 /* tell threads_startup_thread that we registered ourselves */
1093 /* CAUTION: *startup becomes invalid with this! */
1096 threads_sem_post(psem);
1098 /* set our priority */
1100 threads_set_thread_priority(thread->tid, thread->object->priority);
1102 #if defined(ENABLE_INTRP)
1103 /* set interpreter stack */
1106 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1109 #if defined(ENABLE_JVMTI)
1110 /* fire thread start event */
1113 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1116 /* find and run the Thread.run()V method if no other function was passed */
1118 if (function == NULL) {
1119 /* this is a normal Java thread */
1121 thread->flags |= THREAD_FLAG_JAVA;
1123 #if defined(WITH_CLASSPATH_GNU)
1124 /* We need to start the run method of
1125 java.lang.VMThread. Since this is a final class, we can use
1126 the class object directly. */
1128 c = class_java_lang_VMThread;
1129 #elif defined(WITH_CLASSPATH_CLDC1_1)
1130 c = thread->object->header.vftbl->class;
1133 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1138 /* set ThreadMXBean variables */
1140 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1141 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1143 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1144 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1145 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1146 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1148 #if defined(WITH_CLASSPATH_GNU)
1149 /* we need to start the run method of java.lang.VMThread */
1151 vmt = (java_lang_VMThread *) thread->object->vmThread;
1152 o = (java_objectheader *) vmt;
1154 #elif defined(WITH_CLASSPATH_CLDC1_1)
1155 o = (java_objectheader *) thread->object;
1158 (void) vm_call_method(m, o);
1161 /* this is an internal thread */
1163 thread->flags |= THREAD_FLAG_INTERNAL;
1165 /* set ThreadMXBean variables */
1167 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1168 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1170 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1171 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1172 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1173 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1175 /* call passed function, e.g. finalizer_thread */
1180 #if defined(ENABLE_JVMTI)
1181 /* fire thread end event */
1184 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1187 threads_detach_thread(thread);
1189 /* set ThreadMXBean variables */
1191 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1197 /* threads_start_javathread ***************************************************
1199 Start a thread in the JVM. Only the java thread object exists so far.
1202 object.....the java thread object java.lang.Thread
1204 ******************************************************************************/
1206 void threads_start_javathread(java_lang_Thread *object)
1208 threadobject *thread;
1210 /* create the vm internal threadobject */
1212 thread = NEW(threadobject);
1215 /* link the two objects together */
1217 thread->object = object;
1219 #if defined(WITH_CLASSPATH_GNU)
1220 assert(object->vmThread);
1221 assert(object->vmThread->vmdata == NULL);
1222 object->vmThread->vmdata = (java_lang_Object *) thread;
1223 #elif defined(WITH_CLASSPATH_CLDC1_1)
1224 object->vm_thread = (java_lang_Object *) thread;
1227 /* actually start the thread */
1228 /* don't pass a function pointer (NULL) since we want Thread.run()V here */
1230 threads_start_thread(thread, NULL);
1234 /* threads_start_thread ********************************************************
1236 Start a thread in the JVM. Both (vm internal and java) thread objects exist.
1239 thread.......the thread object
1240 function.....function to run in the new thread. NULL means that the
1241 "run" method of the object `t` should be called
1243 ******************************************************************************/
1245 void threads_start_thread(threadobject *thread, functionptr function)
1249 pthread_attr_t attr;
1250 startupinfo startup;
1252 /* fill startupinfo structure passed by pthread_create to
1253 * threads_startup_thread */
1255 startup.thread = thread;
1256 startup.function = function; /* maybe we don't call Thread.run()V */
1257 startup.psem = &sem;
1258 startup.psem_first = &sem_first;
1260 threads_sem_init(&sem, 0, 0);
1261 threads_sem_init(&sem_first, 0, 0);
1263 /* initialize thread attribute object */
1265 if (pthread_attr_init(&attr))
1266 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1268 /* initialize thread stacksize */
1270 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1271 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1273 /* create the thread */
1275 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1276 vm_abort("pthread_create failed: %s", strerror(errno));
1278 /* signal that pthread_create has returned, so thread->tid is valid */
1280 threads_sem_post(&sem_first);
1282 /* wait here until the thread has entered itself into the thread list */
1284 threads_sem_wait(&sem);
1289 sem_destroy(&sem_first);
1293 /* threads_set_thread_priority *************************************************
1295 Set the priority of the given thread.
1298 tid..........thread id
1299 priority.....priority to set
1301 ******************************************************************************/
1303 void threads_set_thread_priority(pthread_t tid, int priority)
1305 struct sched_param schedp;
1308 pthread_getschedparam(tid, &policy, &schedp);
1309 schedp.sched_priority = priority;
1310 pthread_setschedparam(tid, policy, &schedp);
1314 /* threads_attach_current_thread ***********************************************
1316 Attaches the current thread to the VM. Used in JNI.
1318 *******************************************************************************/
1320 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1322 threadobject *thread;
1324 java_lang_String *s;
1325 java_objectheader *o;
1326 java_lang_Thread *t;
1328 #if defined(ENABLE_JAVASE)
1329 java_lang_ThreadGroup *group;
1333 #if defined(WITH_CLASSPATH_GNU)
1334 java_lang_VMThread *vmt;
1337 /* create a vm internal thread object */
1339 thread = NEW(threadobject);
1344 /* create a java.lang.Thread object */
1346 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1353 threads_init_threadobject(thread);
1354 threads_set_current_threadobject(thread);
1355 lock_init_execution_env(thread);
1357 /* insert the thread into the threadlist and the threads table */
1359 pthread_mutex_lock(&threadlistlock);
1361 thread->prev = mainthreadobj;
1362 thread->next = mainthreadobj->next;
1363 mainthreadobj->next = thread;
1364 thread->next->prev = thread;
1366 threads_table_add(thread);
1368 pthread_mutex_unlock(&threadlistlock);
1370 /* mark thread as Java thread */
1372 thread->flags = THREAD_FLAG_JAVA;
1375 thread->flags |= THREAD_FLAG_DAEMON;
1377 #if defined(ENABLE_INTRP)
1378 /* create interpreter stack */
1381 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1382 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1386 #if defined(WITH_CLASSPATH_GNU)
1387 /* create a java.lang.VMThread object */
1389 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1394 /* set the thread */
1397 vmt->vmdata = (java_lang_Object *) thread;
1398 #elif defined(WITH_CLASSPATH_CLDC1_1)
1399 t->vm_thread = (java_lang_Object *) thread;
1402 if (vm_aargs != NULL) {
1403 u = utf_new_char(vm_aargs->name);
1404 #if defined(ENABLE_JAVASE)
1405 group = (java_lang_ThreadGroup *) vm_aargs->group;
1410 #if defined(ENABLE_JAVASE)
1411 group = mainthreadobj->object->group;
1415 s = javastring_new(u);
1417 o = (java_objectheader *) thread->object;
1419 #if defined(WITH_CLASSPATH_GNU)
1420 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1422 #elif defined(WITH_CLASSPATH_CLDC1_1)
1423 (void) vm_call_method(method_thread_init, o, s);
1429 #if defined(ENABLE_JAVASE)
1430 /* store the thread group in the object */
1432 thread->object->group = group;
1434 /* add thread to given thread-group */
1436 m = class_resolveclassmethod(group->header.vftbl->class,
1438 utf_java_lang_Thread__V,
1439 class_java_lang_ThreadGroup,
1442 o = (java_objectheader *) group;
1444 (void) vm_call_method(m, o, t);
1454 /* threads_detach_thread *******************************************************
1456 Detaches the passed thread from the VM. Used in JNI.
1458 *******************************************************************************/
1460 bool threads_detach_thread(threadobject *thread)
1462 #if defined(ENABLE_JAVASE)
1463 java_lang_ThreadGroup *group;
1465 java_objectheader *o;
1466 java_lang_Thread *t;
1469 /* Allow lock record pools to be used by other threads. They
1470 cannot be deleted so we'd better not waste them. */
1472 /* XXX We have to find a new way to free lock records */
1473 /* with the new locking algorithm. */
1474 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1476 /* XXX implement uncaught exception stuff (like JamVM does) */
1478 #if defined(ENABLE_JAVASE)
1479 /* remove thread from the thread group */
1481 group = thread->object->group;
1483 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1485 if (group != NULL) {
1486 m = class_resolveclassmethod(group->header.vftbl->class,
1488 utf_java_lang_Thread__V,
1489 class_java_lang_ThreadGroup,
1495 o = (java_objectheader *) group;
1498 (void) vm_call_method(m, o, t);
1505 /* remove thread from thread list and threads table, do this
1508 pthread_mutex_lock(&threadlistlock);
1510 thread->next->prev = thread->prev;
1511 thread->prev->next = thread->next;
1513 threads_table_remove(thread);
1515 pthread_mutex_unlock(&threadlistlock);
1517 /* reset thread id (lock on joinmutex? TWISTI) */
1519 pthread_mutex_lock(&(thread->joinmutex));
1521 pthread_mutex_unlock(&(thread->joinmutex));
1523 /* tell everyone that a thread has finished */
1525 pthread_cond_broadcast(&(thread->joincond));
1527 /* free the vm internal thread object */
1529 FREE(thread, threadobject);
1535 /* threads_find_non_daemon_thread **********************************************
1537 Helper function used by threads_join_all_threads for finding
1538 non-daemon threads that are still running.
1540 *******************************************************************************/
1542 /* At the end of the program, we wait for all running non-daemon
1545 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1547 while (thread != mainthreadobj) {
1548 if (!(thread->flags & THREAD_FLAG_DAEMON))
1551 thread = thread->prev;
1558 /* threads_join_all_threads ****************************************************
1560 Join all non-daemon threads.
1562 *******************************************************************************/
1564 void threads_join_all_threads(void)
1566 threadobject *thread;
1568 pthread_mutex_lock(&threadlistlock);
1570 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1571 pthread_mutex_lock(&(thread->joinmutex));
1573 pthread_mutex_unlock(&threadlistlock);
1576 pthread_cond_wait(&(thread->joincond), &(thread->joinmutex));
1578 pthread_mutex_unlock(&(thread->joinmutex));
1580 pthread_mutex_lock(&threadlistlock);
1583 pthread_mutex_unlock(&threadlistlock);
1587 /* threads_timespec_earlier ****************************************************
1589 Return true if timespec tv1 is earlier than timespec tv2.
1592 tv1..........first timespec
1593 tv2..........second timespec
1596 true, if the first timespec is earlier
1598 *******************************************************************************/
1600 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1601 const struct timespec *tv2)
1603 return (tv1->tv_sec < tv2->tv_sec)
1605 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1609 /* threads_current_time_is_earlier_than ****************************************
1611 Check if the current time is earlier than the given timespec.
1614 tv...........the timespec to compare against
1617 true, if the current time is earlier
1619 *******************************************************************************/
1621 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1623 struct timeval tvnow;
1624 struct timespec tsnow;
1626 /* get current time */
1628 if (gettimeofday(&tvnow, NULL) != 0)
1629 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1631 /* convert it to a timespec */
1633 tsnow.tv_sec = tvnow.tv_sec;
1634 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1636 /* compare current time with the given timespec */
1638 return threads_timespec_earlier(&tsnow, tv);
1642 /* threads_wait_with_timeout ***************************************************
1644 Wait until the given point in time on a monitor until either
1645 we are notified, we are interrupted, or the time is up.
1648 t............the current thread
1649 wakeupTime...absolute (latest) wakeup time
1650 If both tv_sec and tv_nsec are zero, this function
1651 waits for an unlimited amount of time.
1654 true.........if the wait has been interrupted,
1655 false........if the wait was ended by notification or timeout
1657 *******************************************************************************/
1659 static bool threads_wait_with_timeout(threadobject *thread,
1660 struct timespec *wakeupTime)
1662 bool wasinterrupted;
1664 /* acquire the waitmutex */
1666 pthread_mutex_lock(&thread->waitmutex);
1668 /* mark us as sleeping */
1670 thread->sleeping = true;
1672 /* wait on waitcond */
1674 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1676 while (!thread->interrupted && !thread->signaled
1677 && threads_current_time_is_earlier_than(wakeupTime))
1679 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1685 while (!thread->interrupted && !thread->signaled)
1686 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1689 /* check if we were interrupted */
1691 wasinterrupted = thread->interrupted;
1693 /* reset all flags */
1695 thread->interrupted = false;
1696 thread->signaled = false;
1697 thread->sleeping = false;
1699 /* release the waitmutex */
1701 pthread_mutex_unlock(&thread->waitmutex);
1703 return wasinterrupted;
1707 /* threads_wait_with_timeout_relative ******************************************
1709 Wait for the given maximum amount of time on a monitor until either
1710 we are notified, we are interrupted, or the time is up.
1713 t............the current thread
1714 millis.......milliseconds to wait
1715 nanos........nanoseconds to wait
1718 true.........if the wait has been interrupted,
1719 false........if the wait was ended by notification or timeout
1721 *******************************************************************************/
1723 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1726 struct timespec wakeupTime;
1728 /* calculate the the (latest) wakeup time */
1730 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1734 return threads_wait_with_timeout(thread, &wakeupTime);
1738 /* threads_calc_absolute_time **************************************************
1740 Calculate the absolute point in time a given number of ms and ns from now.
1743 millis............milliseconds from now
1744 nanos.............nanoseconds from now
1747 *tm...............receives the timespec of the absolute point in time
1749 *******************************************************************************/
1751 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1753 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1756 gettimeofday(&tv, NULL);
1757 tv.tv_sec += millis / 1000;
1759 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1760 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1761 tm->tv_nsec = nsec % 1000000000;
1770 /* threads_thread_interrupt ****************************************************
1772 Interrupt the given thread.
1774 The thread gets the "waitcond" signal and
1775 its interrupted flag is set to true.
1778 thread............the thread to interrupt
1780 *******************************************************************************/
1782 void threads_thread_interrupt(threadobject *thread)
1784 /* Signal the thread a "waitcond" and tell it that it has been
1787 pthread_mutex_lock(&thread->waitmutex);
1789 /* Interrupt blocking system call using a signal. */
1791 pthread_kill(thread->tid, SIGHUP);
1793 if (thread->sleeping)
1794 pthread_cond_signal(&thread->waitcond);
1796 thread->interrupted = true;
1798 pthread_mutex_unlock(&thread->waitmutex);
1802 /* threads_check_if_interrupted_and_reset **************************************
1804 Check if the current thread has been interrupted and reset the
1808 true, if the current thread had been interrupted
1810 *******************************************************************************/
1812 bool threads_check_if_interrupted_and_reset(void)
1814 threadobject *thread;
1817 thread = THREADOBJECT;
1819 /* get interrupted flag */
1821 intr = thread->interrupted;
1823 /* reset interrupted flag */
1825 thread->interrupted = false;
1831 /* threads_thread_has_been_interrupted *****************************************
1833 Check if the given thread has been interrupted
1836 t............the thread to check
1839 true, if the given thread had been interrupted
1841 *******************************************************************************/
1843 bool threads_thread_has_been_interrupted(threadobject *thread)
1845 return thread->interrupted;
1849 /* threads_sleep ***************************************************************
1851 Sleep the current thread for the specified amount of time.
1853 *******************************************************************************/
1855 void threads_sleep(s8 millis, s4 nanos)
1857 threadobject *thread;
1858 struct timespec wakeupTime;
1859 bool wasinterrupted;
1861 thread = THREADOBJECT;
1863 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1865 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1868 exceptions_throw_interruptedexception();
1872 /* threads_yield ***************************************************************
1874 Yield to the scheduler.
1876 *******************************************************************************/
1878 void threads_yield(void)
1884 /* threads_dump ****************************************************************
1886 Dumps info for all threads running in the JVM. This function is
1887 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1889 *******************************************************************************/
1891 void threads_dump(void)
1893 threadobject *thread;
1894 java_lang_Thread *t;
1897 thread = mainthreadobj;
1899 /* XXX we should stop the world here */
1901 printf("Full thread dump CACAO "VERSION":\n");
1903 /* iterate over all started threads */
1906 /* get thread object */
1910 /* the thread may be currently in initalization, don't print it */
1913 /* get thread name */
1915 #if defined(ENABLE_JAVASE)
1916 name = javastring_toutf(t->name, false);
1917 #elif defined(ENABLE_JAVAME_CLDC1_1)
1922 utf_display_printable_ascii(name);
1925 if (thread->flags & THREAD_FLAG_DAEMON)
1928 #if SIZEOF_VOID_P == 8
1929 printf("prio=%d tid=0x%016lx\n", t->priority, (ptrint) thread->tid);
1931 printf("prio=%d tid=0x%08lx\n", t->priority, (ptrint) thread->tid);
1934 /* dump trace of thread */
1936 stacktrace_dump_trace(thread);
1939 thread = thread->next;
1940 } while ((thread != NULL) && (thread != mainthreadobj));
1944 /* threads_table_dump *********************************************************
1946 Dump the threads table for debugging purposes.
1949 file..............stream to write to
1951 ******************************************************************************/
1953 #if !defined(NDEBUG) && 0
1954 static void threads_table_dump(FILE *file)
1960 pthread_mutex_lock(&threadlistlock);
1962 size = threads_table.size;
1964 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1966 for (i=0; i<size; ++i) {
1967 index = threads_table.table[i].nextfree;
1969 fprintf(file, "%4d: ", i);
1972 fprintf(file, "free, nextfree = %d\n", (int) index);
1975 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1979 fprintf(file, "======== END OF THREADS TABLE ========\n");
1981 pthread_mutex_unlock(&threadlistlock);
1986 * These are local overrides for various environment variables in Emacs.
1987 * Please do not remove this and leave it at the end of the file, where
1988 * Emacs will automagically detect them.
1989 * ---------------------------------------------------------------------
1992 * indent-tabs-mode: t
1996 * vim:noexpandtab:sw=4:ts=4: