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 7246 2007-01-29 18:49:05Z 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/native/threads.h"
76 #include "toolbox/avl.h"
77 #include "toolbox/logging.h"
79 #include "vm/builtin.h"
80 #include "vm/exceptions.h"
81 #include "vm/global.h"
82 #include "vm/stringlocal.h"
85 #include "vm/jit/asmpart.h"
87 #include "vmcore/options.h"
89 #if !defined(__DARWIN__)
90 # if defined(__LINUX__)
91 # define GC_LINUX_THREADS
92 # elif defined(__MIPS__)
93 # define GC_IRIX_THREADS
95 # include <semaphore.h>
96 # if defined(ENABLE_GC_BOEHM)
97 # include "mm/boehm-gc/include/gc.h"
101 #if defined(ENABLE_JVMTI)
102 #include "native/jvmti/cacaodbg.h"
105 #if defined(__DARWIN__)
106 /* Darwin has no working semaphore implementation. This one is taken
110 This is a very simple semaphore implementation for darwin. It
111 is implemented in terms of pthreads calls so it isn't async signal
112 safe. This isn't a problem because signals aren't used to
113 suspend threads on darwin.
116 static int sem_init(sem_t *sem, int pshared, int value)
123 if (pthread_mutex_init(&sem->mutex, NULL) < 0)
126 if (pthread_cond_init(&sem->cond, NULL) < 0)
132 static int sem_post(sem_t *sem)
134 if (pthread_mutex_lock(&sem->mutex) < 0)
139 if (pthread_cond_signal(&sem->cond) < 0) {
140 pthread_mutex_unlock(&sem->mutex);
144 if (pthread_mutex_unlock(&sem->mutex) < 0)
150 static int sem_wait(sem_t *sem)
152 if (pthread_mutex_lock(&sem->mutex) < 0)
155 while (sem->value == 0) {
156 pthread_cond_wait(&sem->cond, &sem->mutex);
161 if (pthread_mutex_unlock(&sem->mutex) < 0)
167 static int sem_destroy(sem_t *sem)
169 if (pthread_cond_destroy(&sem->cond) < 0)
172 if (pthread_mutex_destroy(&sem->mutex) < 0)
177 #endif /* defined(__DARWIN__) */
180 /* internally used constants **************************************************/
182 /* CAUTION: Do not change these values. Boehm GC code depends on them. */
183 #define STOPWORLD_FROM_GC 1
184 #define STOPWORLD_FROM_CLASS_NUMBERING 2
186 #define THREADS_INITIAL_TABLE_SIZE 8
189 /* startupinfo *****************************************************************
191 Struct used to pass info from threads_start_thread to
192 threads_startup_thread.
194 ******************************************************************************/
197 threadobject *thread; /* threadobject for this thread */
198 functionptr function; /* function to run in the new thread */
199 sem_t *psem; /* signals when thread has been entered */
200 /* in the thread list */
201 sem_t *psem_first; /* signals when pthread_create has returned */
205 /* prototypes *****************************************************************/
207 static void threads_table_init(void);
208 static s4 threads_table_add(threadobject *thread);
209 static void threads_table_remove(threadobject *thread);
210 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
212 #if !defined(NDEBUG) && 0
213 static void threads_table_dump(FILE *file);
216 /******************************************************************************/
217 /* GLOBAL VARIABLES */
218 /******************************************************************************/
220 /* the main thread */
221 threadobject *mainthreadobj;
223 static methodinfo *method_thread_init;
225 /* the thread object of the current thread */
226 /* This is either a thread-local variable defined with __thread, or */
227 /* a thread-specific value stored with key threads_current_threadobject_key. */
228 #if defined(HAVE___THREAD)
229 __thread threadobject *threads_current_threadobject;
231 pthread_key_t threads_current_threadobject_key;
234 /* global threads table */
235 static threads_table_t threads_table;
237 /* global compiler mutex */
238 static pthread_mutex_t compiler_mutex;
240 /* global mutex for changing the thread list */
241 static pthread_mutex_t threadlistlock;
243 /* global mutex for stop-the-world */
244 static pthread_mutex_t stopworldlock;
246 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
248 static volatile int stopworldwhere;
250 /* semaphore used for acknowleding thread suspension */
251 static sem_t suspend_ack;
252 #if defined(__MIPS__)
253 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
254 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
257 static pthread_attr_t threadattr;
259 /* mutexes used by the fake atomic instructions */
260 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
261 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
262 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
263 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
267 /* threads_sem_init ************************************************************
269 Initialize a semaphore. Checks against errors and interruptions.
272 sem..............the semaphore to initialize
273 shared...........true if this semaphore will be shared between processes
274 value............the initial value for the semaphore
276 *******************************************************************************/
278 void threads_sem_init(sem_t *sem, bool shared, int value)
285 r = sem_init(sem, shared, value);
288 } while (errno == EINTR);
290 vm_abort("sem_init failed: %s", strerror(errno));
294 /* threads_sem_wait ************************************************************
296 Wait for a semaphore, non-interruptible.
298 IMPORTANT: Always use this function instead of `sem_wait` directly, as
299 `sem_wait` may be interrupted by signals!
302 sem..............the semaphore to wait on
304 *******************************************************************************/
306 void threads_sem_wait(sem_t *sem)
316 } while (errno == EINTR);
318 vm_abort("sem_wait failed: %s", strerror(errno));
322 /* threads_sem_post ************************************************************
324 Increase the count of a semaphore. Checks for errors.
327 sem..............the semaphore to increase the count of
329 *******************************************************************************/
331 void threads_sem_post(sem_t *sem)
337 /* unlike sem_wait, sem_post is not interruptible */
343 vm_abort("sem_post failed: %s", strerror(errno));
347 /* compiler_lock ***************************************************************
349 Enter the compiler lock.
351 ******************************************************************************/
353 void compiler_lock(void)
355 pthread_mutex_lock(&compiler_mutex);
359 /* compiler_unlock *************************************************************
361 Release the compiler lock.
363 ******************************************************************************/
365 void compiler_unlock(void)
367 pthread_mutex_unlock(&compiler_mutex);
371 /* lock_stopworld **************************************************************
373 Enter the stopworld lock, specifying why the world shall be stopped.
376 where........ STOPWORLD_FROM_GC (1) from within GC
377 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
379 ******************************************************************************/
381 void lock_stopworld(int where)
383 pthread_mutex_lock(&stopworldlock);
384 stopworldwhere = where;
388 /* unlock_stopworld ************************************************************
390 Release the stopworld lock.
392 ******************************************************************************/
394 void unlock_stopworld(void)
397 pthread_mutex_unlock(&stopworldlock);
400 #if !defined(__DARWIN__)
401 /* Caller must hold threadlistlock */
402 static int threads_cast_sendsignals(int sig, int count)
405 threadobject *tobj = mainthreadobj;
406 threadobject *self = THREADOBJECT;
412 } while (tobj != mainthreadobj);
415 assert(tobj == mainthreadobj);
419 pthread_kill(tobj->tid, sig);
421 } while (tobj != mainthreadobj);
428 static void threads_cast_darwinstop(void)
430 threadobject *tobj = mainthreadobj;
431 threadobject *self = THREADOBJECT;
436 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
437 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
438 #if defined(__I386__)
439 i386_thread_state_t thread_state;
441 ppc_thread_state_t thread_state;
443 mach_port_t thread = tobj->mach_thread;
446 r = thread_suspend(thread);
448 if (r != KERN_SUCCESS)
449 vm_abort("thread_suspend failed");
451 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
452 &thread_state_count);
454 if (r != KERN_SUCCESS)
455 vm_abort("thread_get_state failed");
457 thread_restartcriticalsection((ucontext_t *) &thread_state);
459 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
462 if (r != KERN_SUCCESS)
463 vm_abort("thread_set_state failed");
467 } while (tobj != mainthreadobj);
470 static void threads_cast_darwinresume(void)
472 threadobject *tobj = mainthreadobj;
473 threadobject *self = THREADOBJECT;
478 mach_port_t thread = tobj->mach_thread;
481 r = thread_resume(thread);
483 if (r != KERN_SUCCESS)
484 vm_abort("thread_resume failed");
488 } while (tobj != mainthreadobj);
493 #if defined(__MIPS__)
494 static void threads_cast_irixresume(void)
496 pthread_mutex_lock(&suspend_ack_lock);
497 pthread_cond_broadcast(&suspend_cond);
498 pthread_mutex_unlock(&suspend_ack_lock);
502 #if !defined(DISABLE_GC)
504 void threads_cast_stopworld(void)
506 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
510 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
511 pthread_mutex_lock(&threadlistlock);
513 #if defined(__DARWIN__)
514 threads_cast_darwinstop();
515 #elif defined(__CYGWIN__)
519 count = threads_cast_sendsignals(GC_signum1(), 0);
520 for (i = 0; i < count; i++)
521 threads_sem_wait(&suspend_ack);
524 pthread_mutex_unlock(&threadlistlock);
527 void threads_cast_startworld(void)
529 pthread_mutex_lock(&threadlistlock);
530 #if defined(__DARWIN__)
531 threads_cast_darwinresume();
532 #elif defined(__MIPS__)
533 threads_cast_irixresume();
534 #elif defined(__CYGWIN__)
538 threads_cast_sendsignals(GC_signum2(), -1);
540 pthread_mutex_unlock(&threadlistlock);
545 #if !defined(__DARWIN__)
546 static void threads_sigsuspend_handler(ucontext_t *ctx)
551 /* XXX TWISTI: this is just a quick hack */
552 #if defined(ENABLE_JIT)
553 thread_restartcriticalsection(ctx);
556 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
557 (not POSIX async-safe). */
558 #if defined(__IRIX__)
559 pthread_mutex_lock(&suspend_ack_lock);
560 threads_sem_post(&suspend_ack);
561 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
562 pthread_mutex_unlock(&suspend_ack_lock);
563 #elif defined(__CYGWIN__)
567 threads_sem_post(&suspend_ack);
571 sigdelset(&sigs, sig);
576 /* This function is called from Boehm GC code. */
578 int cacao_suspendhandler(ucontext_t *ctx)
580 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
583 threads_sigsuspend_handler(ctx);
588 #endif /* DISABLE_GC */
590 /* threads_set_current_threadobject ********************************************
592 Set the current thread object.
595 thread.......the thread object to set
597 *******************************************************************************/
599 static void threads_set_current_threadobject(threadobject *thread)
601 #if !defined(HAVE___THREAD)
602 pthread_setspecific(threads_current_threadobject_key, thread);
604 threads_current_threadobject = thread;
609 /* threads_init_threadobject **************************************************
611 Initialize implementation fields of a threadobject.
614 thread............the threadobject
616 ******************************************************************************/
618 static void threads_init_threadobject(threadobject *thread)
620 thread->tid = pthread_self();
624 /* TODO destroy all those things */
625 pthread_mutex_init(&(thread->joinmutex), NULL);
626 pthread_cond_init(&(thread->joincond), NULL);
628 pthread_mutex_init(&(thread->waitmutex), NULL);
629 pthread_cond_init(&(thread->waitcond), NULL);
631 thread->interrupted = false;
632 thread->signaled = false;
633 thread->sleeping = false;
637 /* threads_get_current_threadobject ********************************************
639 Return the threadobject of the current thread.
642 the current threadobject * (an instance of java.lang.Thread)
644 *******************************************************************************/
646 threadobject *threads_get_current_threadobject(void)
652 /* threads_preinit *************************************************************
654 Do some early initialization of stuff required.
656 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
657 is called AFTER this function!
659 *******************************************************************************/
661 void threads_preinit(void)
663 pthread_mutexattr_t mutexattr;
664 pthread_mutexattr_init(&mutexattr);
665 pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
666 pthread_mutex_init(&compiler_mutex, &mutexattr);
667 pthread_mutexattr_destroy(&mutexattr);
669 pthread_mutex_init(&threadlistlock, NULL);
670 pthread_mutex_init(&stopworldlock, NULL);
672 mainthreadobj = NEW(threadobject);
673 mainthreadobj->tid = pthread_self();
674 mainthreadobj->index = 1;
675 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
677 #if !defined(HAVE___THREAD)
678 pthread_key_create(&threads_current_threadobject_key, NULL);
680 threads_set_current_threadobject(mainthreadobj);
682 threads_sem_init(&suspend_ack, 0, 0);
684 /* initialize the threads table */
686 threads_table_init();
688 /* initialize subsystems */
696 /* threads_init ****************************************************************
698 Initializes the threads required by the JVM: main, finalizer.
700 *******************************************************************************/
702 bool threads_init(void)
704 java_lang_String *threadname;
705 threadobject *tempthread;
706 java_objectheader *o;
708 #if defined(ENABLE_JAVASE)
709 java_lang_ThreadGroup *threadgroup;
714 #if defined(WITH_CLASSPATH_GNU)
715 java_lang_VMThread *vmt;
718 tempthread = mainthreadobj;
720 /* XXX We have to find a new way to free lock records */
721 /* with the new locking algorithm. */
722 /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
724 /* This is kinda tricky, we grow the java.lang.Thread object so we
725 can keep the execution environment there. No Thread object must
726 have been created at an earlier time. */
728 class_java_lang_Thread->instancesize = sizeof(threadobject);
730 /* get methods we need in this file */
732 #if defined(WITH_CLASSPATH_GNU)
734 class_resolveclassmethod(class_java_lang_Thread,
736 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
737 class_java_lang_Thread,
741 class_resolveclassmethod(class_java_lang_Thread,
743 utf_new_char("(Ljava/lang/String;)V"),
744 class_java_lang_Thread,
748 if (method_thread_init == NULL)
751 /* create a java.lang.Thread for the main thread */
753 mainthreadobj = (threadobject *) builtin_new(class_java_lang_Thread);
755 if (mainthreadobj == NULL)
758 FREE(tempthread, threadobject);
760 threads_init_threadobject(mainthreadobj);
762 threads_set_current_threadobject(mainthreadobj);
764 lock_init_execution_env(mainthreadobj);
766 mainthreadobj->next = mainthreadobj;
767 mainthreadobj->prev = mainthreadobj;
769 threads_table_add(mainthreadobj);
771 /* mark main thread as Java thread */
773 mainthreadobj->flags = THREAD_FLAG_JAVA;
775 #if defined(ENABLE_INTRP)
776 /* create interpreter stack */
779 MSET(intrp_main_stack, 0, u1, opt_stacksize);
780 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
784 threadname = javastring_new(utf_new_char("main"));
786 #if defined(ENABLE_JAVASE)
787 /* allocate and init ThreadGroup */
789 threadgroup = (java_lang_ThreadGroup *)
790 native_new_and_init(class_java_lang_ThreadGroup);
792 if (threadgroup == NULL)
793 throw_exception_exit();
796 #if defined(WITH_CLASSPATH_GNU)
797 /* create a java.lang.VMThread for the main thread */
799 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
802 throw_exception_exit();
806 t = (java_lang_Thread *) mainthreadobj;
809 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
810 o = (java_objectheader *) mainthreadobj;
812 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
814 #elif defined(WITH_CLASSPATH_CLDC1_1)
815 /* call public Thread(String name) */
817 o = (java_objectheader *) mainthreadobj;
819 (void) vm_call_method(method_thread_init, o, threadname);
825 #if defined(ENABLE_JAVASE)
826 mainthreadobj->o.group = threadgroup;
828 /* add main thread to java.lang.ThreadGroup */
830 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
832 utf_java_lang_Thread__V,
833 class_java_lang_ThreadGroup,
836 o = (java_objectheader *) threadgroup;
837 t = (java_lang_Thread *) mainthreadobj;
839 (void) vm_call_method(m, o, t);
846 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
848 /* initialize the thread attribute object */
850 if (pthread_attr_init(&threadattr)) {
851 log_println("pthread_attr_init failed: %s", strerror(errno));
855 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
857 /* everything's ok */
863 /* threads_table_init *********************************************************
865 Initialize the global threads table.
867 ******************************************************************************/
869 static void threads_table_init(void)
874 size = THREADS_INITIAL_TABLE_SIZE;
876 threads_table.size = size;
877 threads_table.table = MNEW(threads_table_entry_t, size);
879 /* link the entries in a freelist */
881 for (i=0; i<size; ++i) {
882 threads_table.table[i].nextfree = i+1;
885 /* terminate the freelist */
887 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
891 /* threads_table_add **********************************************************
893 Add a thread to the global threads table. The index is entered in the
894 threadobject. The thinlock value for the thread is pre-computed.
897 thread............the thread to add
900 The table index for the newly added thread. This value has also been
901 entered in the threadobject.
904 The caller must hold the threadlistlock!
906 ******************************************************************************/
908 static s4 threads_table_add(threadobject *thread)
915 /* table[0] serves as the head of the freelist */
917 index = threads_table.table[0].nextfree;
919 /* if we got a free index, use it */
923 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
924 threads_table.table[index].thread = thread;
925 thread->index = index;
926 thread->thinlock = lock_pre_compute_thinlock(index);
930 /* we must grow the table */
932 oldsize = threads_table.size;
933 newsize = oldsize * 2;
935 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
937 threads_table.size = newsize;
939 /* link the new entries to a free list */
941 for (i=oldsize; i<newsize; ++i) {
942 threads_table.table[i].nextfree = i+1;
945 /* terminate the freelist */
947 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
949 /* use the first of the new entries */
956 /* threads_table_remove *******************************************************
958 Remove a thread from the global threads table.
961 thread............the thread to remove
964 The caller must hold the threadlistlock!
966 ******************************************************************************/
968 static void threads_table_remove(threadobject *thread)
972 index = thread->index;
974 /* put the index into the freelist */
976 threads_table.table[index] = threads_table.table[0];
977 threads_table.table[0].nextfree = index;
979 /* delete the index in the threadobject to discover bugs */
986 /* threads_startup_thread ******************************************************
988 Thread startup function called by pthread_create.
990 Thread which have a startup.function != NULL are marked as internal
991 threads. All other threads are threated as normal Java threads.
993 NOTE: This function is not called directly by pthread_create. The Boehm GC
994 inserts its own GC_start_routine in between, which then calls
998 t............the argument passed to pthread_create, ie. a pointer to
999 a startupinfo struct. CAUTION: When the `psem` semaphore
1000 is posted, the startupinfo struct becomes invalid! (It
1001 is allocated on the stack of threads_start_thread.)
1003 ******************************************************************************/
1005 static void *threads_startup_thread(void *t)
1007 startupinfo *startup;
1008 threadobject *thread;
1009 #if defined(WITH_CLASSPATH_GNU)
1010 java_lang_VMThread *vmt;
1013 threadobject *tnext;
1016 java_objectheader *o;
1017 functionptr function;
1019 #if defined(ENABLE_INTRP)
1020 u1 *intrp_thread_stack;
1022 /* create interpreter stack */
1025 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1026 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1029 intrp_thread_stack = NULL;
1032 /* get passed startupinfo structure and the values in there */
1035 t = NULL; /* make sure it's not used wrongly */
1037 thread = startup->thread;
1038 function = startup->function;
1039 psem = startup->psem;
1041 /* Seems like we've encountered a situation where thread->tid was not set by
1042 * pthread_create. We alleviate this problem by waiting for pthread_create
1044 threads_sem_wait(startup->psem_first);
1046 /* set the thread object */
1048 #if defined(__DARWIN__)
1049 thread->mach_thread = mach_thread_self();
1051 threads_set_current_threadobject(thread);
1053 /* insert the thread into the threadlist and the threads table */
1055 pthread_mutex_lock(&threadlistlock);
1057 thread->prev = mainthreadobj;
1058 thread->next = tnext = mainthreadobj->next;
1059 mainthreadobj->next = thread;
1060 tnext->prev = thread;
1062 threads_table_add(thread);
1064 pthread_mutex_unlock(&threadlistlock);
1066 /* init data structures of this thread */
1068 lock_init_execution_env(thread);
1070 /* tell threads_startup_thread that we registered ourselves */
1071 /* CAUTION: *startup becomes invalid with this! */
1074 threads_sem_post(psem);
1076 /* set our priority */
1078 threads_set_thread_priority(thread->tid, thread->o.priority);
1080 #if defined(ENABLE_INTRP)
1081 /* set interpreter stack */
1084 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1087 #if defined(ENABLE_JVMTI)
1088 /* fire thread start event */
1091 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1094 /* find and run the Thread.run()V method if no other function was passed */
1096 if (function == NULL) {
1097 /* this is a normal Java thread */
1099 thread->flags |= THREAD_FLAG_JAVA;
1101 #if defined(WITH_CLASSPATH_GNU)
1102 /* We need to start the run method of
1103 java.lang.VMThread. Since this is a final class, we can use
1104 the class object directly. */
1106 c = class_java_lang_VMThread;
1107 #elif defined(WITH_CLASSPATH_CLDC1_1)
1108 c = thread->o.header.vftbl->class;
1111 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1116 /* set ThreadMXBean variables */
1118 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1119 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1121 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1122 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1123 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1124 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1126 #if defined(WITH_CLASSPATH_GNU)
1127 /* we need to start the run method of java.lang.VMThread */
1129 vmt = (java_lang_VMThread *) thread->o.vmThread;
1130 o = (java_objectheader *) vmt;
1132 #elif defined(WITH_CLASSPATH_CLDC1_1)
1133 o = (java_objectheader *) thread;
1136 (void) vm_call_method(m, o);
1139 /* this is an internal thread */
1141 thread->flags |= THREAD_FLAG_INTERNAL;
1143 /* set ThreadMXBean variables */
1145 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1146 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1148 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1149 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1150 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1151 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1153 /* call passed function, e.g. finalizer_thread */
1158 #if defined(ENABLE_JVMTI)
1159 /* fire thread end event */
1162 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1165 threads_detach_thread(thread);
1167 /* set ThreadMXBean variables */
1169 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1175 /* threads_start_thread ********************************************************
1177 Start a thread in the JVM.
1180 thread.......the thread object
1181 function.....function to run in the new thread. NULL means that the
1182 "run" method of the object `t` should be called
1184 ******************************************************************************/
1186 void threads_start_thread(threadobject *thread, functionptr function)
1190 pthread_attr_t attr;
1191 startupinfo startup;
1193 /* fill startupinfo structure passed by pthread_create to
1194 * threads_startup_thread */
1196 startup.thread = thread;
1197 startup.function = function; /* maybe we don't call Thread.run()V */
1198 startup.psem = &sem;
1199 startup.psem_first = &sem_first;
1201 threads_sem_init(&sem, 0, 0);
1202 threads_sem_init(&sem_first, 0, 0);
1204 /* initialize thread attribute object */
1206 if (pthread_attr_init(&attr))
1207 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1209 /* initialize thread stacksize */
1211 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1212 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1214 /* create the thread */
1216 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1217 vm_abort("pthread_create failed: %s", strerror(errno));
1219 /* signal that pthread_create has returned, so thread->tid is valid */
1221 threads_sem_post(&sem_first);
1223 /* wait here until the thread has entered itself into the thread list */
1225 threads_sem_wait(&sem);
1230 sem_destroy(&sem_first);
1234 /* threads_set_thread_priority *************************************************
1236 Set the priority of the given thread.
1239 tid..........thread id
1240 priority.....priority to set
1242 ******************************************************************************/
1244 void threads_set_thread_priority(pthread_t tid, int priority)
1246 struct sched_param schedp;
1249 #if defined(ENABLE_JAVAME_CLDC1_1)
1250 /* The thread id is zero when a thread is created in Java. The
1251 priority is set later during startup. */
1257 pthread_getschedparam(tid, &policy, &schedp);
1258 schedp.sched_priority = priority;
1259 pthread_setschedparam(tid, policy, &schedp);
1263 /* threads_attach_current_thread ***********************************************
1265 Attaches the current thread to the VM. Used in JNI.
1267 *******************************************************************************/
1269 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1271 threadobject *thread;
1273 java_lang_String *s;
1274 java_objectheader *o;
1275 java_lang_Thread *t;
1277 #if defined(ENABLE_JAVASE)
1278 java_lang_ThreadGroup *group;
1282 #if defined(WITH_CLASSPATH_GNU)
1283 java_lang_VMThread *vmt;
1286 /* create a java.lang.Thread object */
1288 thread = (threadobject *) builtin_new(class_java_lang_Thread);
1293 /* cast for convenience */
1295 t = (java_lang_Thread *) thread;
1297 threads_init_threadobject(thread);
1298 threads_set_current_threadobject(thread);
1299 lock_init_execution_env(thread);
1301 /* insert the thread into the threadlist and the threads table */
1303 pthread_mutex_lock(&threadlistlock);
1305 thread->prev = mainthreadobj;
1306 thread->next = mainthreadobj->next;
1307 mainthreadobj->next = thread;
1308 thread->next->prev = thread;
1310 threads_table_add(thread);
1312 pthread_mutex_unlock(&threadlistlock);
1314 /* mark thread as Java thread */
1316 thread->flags = THREAD_FLAG_JAVA;
1319 thread->flags |= THREAD_FLAG_DAEMON;
1321 #if defined(ENABLE_INTRP)
1322 /* create interpreter stack */
1325 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1326 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1330 #if defined(WITH_CLASSPATH_GNU)
1331 /* create a java.lang.VMThread object */
1333 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1338 /* set the thread */
1343 if (vm_aargs != NULL) {
1344 u = utf_new_char(vm_aargs->name);
1345 #if defined(ENABLE_JAVASE)
1346 group = (java_lang_ThreadGroup *) vm_aargs->group;
1351 #if defined(ENABLE_JAVASE)
1352 group = mainthreadobj->o.group;
1356 s = javastring_new(u);
1358 o = (java_objectheader *) thread;
1360 #if defined(WITH_CLASSPATH_GNU)
1361 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1363 #elif defined(WITH_CLASSPATH_CLDC1_1)
1364 (void) vm_call_method(method_thread_init, o, s);
1370 #if defined(ENABLE_JAVASE)
1371 /* store the thread group in the object */
1373 thread->o.group = group;
1375 /* add thread to given thread-group */
1377 m = class_resolveclassmethod(group->header.vftbl->class,
1379 utf_java_lang_Thread__V,
1380 class_java_lang_ThreadGroup,
1383 o = (java_objectheader *) group;
1385 (void) vm_call_method(m, o, t);
1395 /* threads_detach_thread *******************************************************
1397 Detaches the passed thread from the VM. Used in JNI.
1399 *******************************************************************************/
1401 bool threads_detach_thread(threadobject *thread)
1403 #if defined(ENABLE_JAVASE)
1404 java_lang_ThreadGroup *group;
1406 java_objectheader *o;
1407 java_lang_Thread *t;
1410 /* Allow lock record pools to be used by other threads. They
1411 cannot be deleted so we'd better not waste them. */
1413 /* XXX We have to find a new way to free lock records */
1414 /* with the new locking algorithm. */
1415 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1417 /* XXX implement uncaught exception stuff (like JamVM does) */
1419 #if defined(ENABLE_JAVASE)
1420 /* remove thread from the thread group */
1422 group = thread->o.group;
1424 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1426 if (group != NULL) {
1427 m = class_resolveclassmethod(group->header.vftbl->class,
1429 utf_java_lang_Thread__V,
1430 class_java_lang_ThreadGroup,
1436 o = (java_objectheader *) group;
1437 t = (java_lang_Thread *) thread;
1439 (void) vm_call_method(m, o, t);
1446 /* remove thread from thread list and threads table, do this
1449 pthread_mutex_lock(&threadlistlock);
1451 thread->next->prev = thread->prev;
1452 thread->prev->next = thread->next;
1454 threads_table_remove(thread);
1456 pthread_mutex_unlock(&threadlistlock);
1458 /* reset thread id (lock on joinmutex? TWISTI) */
1460 pthread_mutex_lock(&(thread->joinmutex));
1462 pthread_mutex_unlock(&(thread->joinmutex));
1464 /* tell everyone that a thread has finished */
1466 pthread_cond_broadcast(&(thread->joincond));
1472 /* threads_find_non_daemon_thread **********************************************
1474 Helper function used by threads_join_all_threads for finding
1475 non-daemon threads that are still running.
1477 *******************************************************************************/
1479 /* At the end of the program, we wait for all running non-daemon
1482 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1484 while (thread != mainthreadobj) {
1485 if (!(thread->flags & THREAD_FLAG_DAEMON))
1488 thread = thread->prev;
1495 /* threads_join_all_threads ****************************************************
1497 Join all non-daemon threads.
1499 *******************************************************************************/
1501 void threads_join_all_threads(void)
1503 threadobject *thread;
1505 pthread_mutex_lock(&threadlistlock);
1507 while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1508 pthread_mutex_lock(&(thread->joinmutex));
1510 pthread_mutex_unlock(&threadlistlock);
1513 pthread_cond_wait(&(thread->joincond), &(thread->joinmutex));
1515 pthread_mutex_unlock(&(thread->joinmutex));
1517 pthread_mutex_lock(&threadlistlock);
1520 pthread_mutex_unlock(&threadlistlock);
1524 /* threads_timespec_earlier ****************************************************
1526 Return true if timespec tv1 is earlier than timespec tv2.
1529 tv1..........first timespec
1530 tv2..........second timespec
1533 true, if the first timespec is earlier
1535 *******************************************************************************/
1537 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1538 const struct timespec *tv2)
1540 return (tv1->tv_sec < tv2->tv_sec)
1542 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1546 /* threads_current_time_is_earlier_than ****************************************
1548 Check if the current time is earlier than the given timespec.
1551 tv...........the timespec to compare against
1554 true, if the current time is earlier
1556 *******************************************************************************/
1558 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1560 struct timeval tvnow;
1561 struct timespec tsnow;
1563 /* get current time */
1565 if (gettimeofday(&tvnow, NULL) != 0)
1566 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1568 /* convert it to a timespec */
1570 tsnow.tv_sec = tvnow.tv_sec;
1571 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1573 /* compare current time with the given timespec */
1575 return threads_timespec_earlier(&tsnow, tv);
1579 /* threads_wait_with_timeout ***************************************************
1581 Wait until the given point in time on a monitor until either
1582 we are notified, we are interrupted, or the time is up.
1585 t............the current thread
1586 wakeupTime...absolute (latest) wakeup time
1587 If both tv_sec and tv_nsec are zero, this function
1588 waits for an unlimited amount of time.
1591 true.........if the wait has been interrupted,
1592 false........if the wait was ended by notification or timeout
1594 *******************************************************************************/
1596 static bool threads_wait_with_timeout(threadobject *thread,
1597 struct timespec *wakeupTime)
1599 bool wasinterrupted;
1601 /* acquire the waitmutex */
1603 pthread_mutex_lock(&thread->waitmutex);
1605 /* mark us as sleeping */
1607 thread->sleeping = true;
1609 /* wait on waitcond */
1611 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1613 while (!thread->interrupted && !thread->signaled
1614 && threads_current_time_is_earlier_than(wakeupTime))
1616 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1622 while (!thread->interrupted && !thread->signaled)
1623 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1626 /* check if we were interrupted */
1628 wasinterrupted = thread->interrupted;
1630 /* reset all flags */
1632 thread->interrupted = false;
1633 thread->signaled = false;
1634 thread->sleeping = false;
1636 /* release the waitmutex */
1638 pthread_mutex_unlock(&thread->waitmutex);
1640 return wasinterrupted;
1644 /* threads_wait_with_timeout_relative ******************************************
1646 Wait for the given maximum amount of time on a monitor until either
1647 we are notified, we are interrupted, or the time is up.
1650 t............the current thread
1651 millis.......milliseconds to wait
1652 nanos........nanoseconds to wait
1655 true.........if the wait has been interrupted,
1656 false........if the wait was ended by notification or timeout
1658 *******************************************************************************/
1660 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1663 struct timespec wakeupTime;
1665 /* calculate the the (latest) wakeup time */
1667 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1671 return threads_wait_with_timeout(thread, &wakeupTime);
1675 /* threads_calc_absolute_time **************************************************
1677 Calculate the absolute point in time a given number of ms and ns from now.
1680 millis............milliseconds from now
1681 nanos.............nanoseconds from now
1684 *tm...............receives the timespec of the absolute point in time
1686 *******************************************************************************/
1688 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1690 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1693 gettimeofday(&tv, NULL);
1694 tv.tv_sec += millis / 1000;
1696 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1697 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1698 tm->tv_nsec = nsec % 1000000000;
1707 /* threads_thread_interrupt ****************************************************
1709 Interrupt the given thread.
1711 The thread gets the "waitcond" signal and
1712 its interrupted flag is set to true.
1715 thread............the thread to interrupt
1717 *******************************************************************************/
1719 void threads_thread_interrupt(threadobject *thread)
1721 /* Signal the thread a "waitcond" and tell it that it has been
1724 pthread_mutex_lock(&thread->waitmutex);
1726 /* Interrupt blocking system call using a signal. */
1728 pthread_kill(thread->tid, SIGHUP);
1730 if (thread->sleeping)
1731 pthread_cond_signal(&thread->waitcond);
1733 thread->interrupted = true;
1735 pthread_mutex_unlock(&thread->waitmutex);
1739 /* threads_check_if_interrupted_and_reset **************************************
1741 Check if the current thread has been interrupted and reset the
1745 true, if the current thread had been interrupted
1747 *******************************************************************************/
1749 bool threads_check_if_interrupted_and_reset(void)
1751 threadobject *thread;
1754 thread = THREADOBJECT;
1756 /* get interrupted flag */
1758 intr = thread->interrupted;
1760 /* reset interrupted flag */
1762 thread->interrupted = false;
1768 /* threads_thread_has_been_interrupted *****************************************
1770 Check if the given thread has been interrupted
1773 t............the thread to check
1776 true, if the given thread had been interrupted
1778 *******************************************************************************/
1780 bool threads_thread_has_been_interrupted(threadobject *thread)
1782 return thread->interrupted;
1786 /* threads_sleep ***************************************************************
1788 Sleep the current thread for the specified amount of time.
1790 *******************************************************************************/
1792 void threads_sleep(s8 millis, s4 nanos)
1794 threadobject *thread;
1795 struct timespec wakeupTime;
1796 bool wasinterrupted;
1798 thread = THREADOBJECT;
1800 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1802 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1805 exceptions_throw_interruptedexception();
1809 /* threads_yield ***************************************************************
1811 Yield to the scheduler.
1813 *******************************************************************************/
1815 void threads_yield(void)
1821 /* threads_dump ****************************************************************
1823 Dumps info for all threads running in the JVM. This function is
1824 called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1826 *******************************************************************************/
1828 void threads_dump(void)
1830 threadobject *thread;
1831 java_lang_Thread *t;
1834 thread = mainthreadobj;
1836 /* XXX we should stop the world here */
1838 printf("Full thread dump CACAO "VERSION":\n");
1840 /* iterate over all started threads */
1843 /* get thread object */
1845 t = (java_lang_Thread *) thread;
1847 /* the thread may be currently in initalization, don't print it */
1850 /* get thread name */
1852 #if defined(ENABLE_JAVASE)
1853 name = javastring_toutf(t->name, false);
1854 #elif defined(ENABLE_JAVAME_CLDC1_1)
1859 utf_display_printable_ascii(name);
1862 if (thread->flags & THREAD_FLAG_DAEMON)
1865 #if SIZEOF_VOID_P == 8
1866 printf("prio=%d tid=0x%016lx\n", t->priority, (long) thread->tid);
1868 printf("prio=%d tid=0x%08lx\n", t->priority, (long) thread->tid);
1871 /* dump trace of thread */
1873 stacktrace_dump_trace(thread);
1876 thread = thread->next;
1877 } while ((thread != NULL) && (thread != mainthreadobj));
1881 /* threads_table_dump *********************************************************
1883 Dump the threads table for debugging purposes.
1886 file..............stream to write to
1888 ******************************************************************************/
1890 #if !defined(NDEBUG) && 0
1891 static void threads_table_dump(FILE *file)
1897 pthread_mutex_lock(&threadlistlock);
1899 size = threads_table.size;
1901 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1903 for (i=0; i<size; ++i) {
1904 index = threads_table.table[i].nextfree;
1906 fprintf(file, "%4d: ", i);
1909 fprintf(file, "free, nextfree = %d\n", (int) index);
1912 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1916 fprintf(file, "======== END OF THREADS TABLE ========\n");
1918 pthread_mutex_unlock(&threadlistlock);
1923 * These are local overrides for various environment variables in Emacs.
1924 * Please do not remove this and leave it at the end of the file, where
1925 * Emacs will automagically detect them.
1926 * ---------------------------------------------------------------------
1929 * indent-tabs-mode: t
1933 * vim:noexpandtab:sw=4:ts=4: