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 7813 2007-04-25 19:20:13Z 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
193 #define THREADS_INITIAL_TABLE_SIZE 8
196 /* startupinfo *****************************************************************
198 Struct used to pass info from threads_start_thread to
199 threads_startup_thread.
201 ******************************************************************************/
204 threadobject *thread; /* threadobject for this thread */
205 functionptr function; /* function to run in the new thread */
206 sem_t *psem; /* signals when thread has been entered */
207 /* in the thread list */
208 sem_t *psem_first; /* signals when pthread_create has returned */
212 /* prototypes *****************************************************************/
214 static void threads_table_init(void);
215 static s4 threads_table_add(threadobject *thread);
216 static void threads_table_remove(threadobject *thread);
217 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
219 #if !defined(NDEBUG) && 0
220 static void threads_table_dump(FILE *file);
223 /******************************************************************************/
224 /* GLOBAL VARIABLES */
225 /******************************************************************************/
227 /* the main thread */
228 threadobject *mainthreadobj;
230 static methodinfo *method_thread_init;
232 /* the thread object of the current thread */
233 /* This is either a thread-local variable defined with __thread, or */
234 /* a thread-specific value stored with key threads_current_threadobject_key. */
235 #if defined(HAVE___THREAD)
236 __thread threadobject *threads_current_threadobject;
238 pthread_key_t threads_current_threadobject_key;
241 /* global threads table */
242 static threads_table_t threads_table;
244 /* global mutex for changing the thread list */
245 static pthread_mutex_t threadlistlock;
247 /* global mutex for stop-the-world */
248 static pthread_mutex_t stopworldlock;
250 /* global mutex and condition for joining threads on exit */
251 static pthread_mutex_t mutex_join;
252 static pthread_cond_t cond_join;
254 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
256 static volatile int stopworldwhere;
258 /* semaphore used for acknowleding thread suspension */
259 static sem_t suspend_ack;
260 #if defined(__MIPS__)
261 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
262 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
265 static pthread_attr_t threadattr;
267 /* mutexes used by the fake atomic instructions */
268 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
269 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
270 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
271 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
275 /* threads_sem_init ************************************************************
277 Initialize a semaphore. Checks against errors and interruptions.
280 sem..............the semaphore to initialize
281 shared...........true if this semaphore will be shared between processes
282 value............the initial value for the semaphore
284 *******************************************************************************/
286 void threads_sem_init(sem_t *sem, bool shared, int value)
293 r = sem_init(sem, shared, value);
296 } while (errno == EINTR);
298 vm_abort("sem_init failed: %s", strerror(errno));
302 /* threads_sem_wait ************************************************************
304 Wait for a semaphore, non-interruptible.
306 IMPORTANT: Always use this function instead of `sem_wait` directly, as
307 `sem_wait` may be interrupted by signals!
310 sem..............the semaphore to wait on
312 *******************************************************************************/
314 void threads_sem_wait(sem_t *sem)
324 } while (errno == EINTR);
326 vm_abort("sem_wait failed: %s", strerror(errno));
330 /* threads_sem_post ************************************************************
332 Increase the count of a semaphore. Checks for errors.
335 sem..............the semaphore to increase the count of
337 *******************************************************************************/
339 void threads_sem_post(sem_t *sem)
345 /* unlike sem_wait, sem_post is not interruptible */
351 vm_abort("sem_post failed: %s", strerror(errno));
355 /* lock_stopworld **************************************************************
357 Enter the stopworld lock, specifying why the world shall be stopped.
360 where........ STOPWORLD_FROM_GC (1) from within GC
361 STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
363 ******************************************************************************/
365 void lock_stopworld(int where)
367 pthread_mutex_lock(&stopworldlock);
368 stopworldwhere = where;
372 /* unlock_stopworld ************************************************************
374 Release the stopworld lock.
376 ******************************************************************************/
378 void unlock_stopworld(void)
381 pthread_mutex_unlock(&stopworldlock);
384 #if !defined(__DARWIN__)
385 /* Caller must hold threadlistlock */
386 static int threads_cast_sendsignals(int sig, int count)
389 threadobject *tobj = mainthreadobj;
390 threadobject *self = THREADOBJECT;
396 } while (tobj != mainthreadobj);
399 assert(tobj == mainthreadobj);
403 pthread_kill(tobj->tid, sig);
405 } while (tobj != mainthreadobj);
412 static void threads_cast_darwinstop(void)
414 threadobject *tobj = mainthreadobj;
415 threadobject *self = THREADOBJECT;
420 thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
421 mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
422 #if defined(__I386__)
423 i386_thread_state_t thread_state;
425 ppc_thread_state_t thread_state;
427 mach_port_t thread = tobj->mach_thread;
430 r = thread_suspend(thread);
432 if (r != KERN_SUCCESS)
433 vm_abort("thread_suspend failed");
435 r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
436 &thread_state_count);
438 if (r != KERN_SUCCESS)
439 vm_abort("thread_get_state failed");
441 thread_restartcriticalsection((ucontext_t *) &thread_state);
443 r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
446 if (r != KERN_SUCCESS)
447 vm_abort("thread_set_state failed");
451 } while (tobj != mainthreadobj);
454 static void threads_cast_darwinresume(void)
456 threadobject *tobj = mainthreadobj;
457 threadobject *self = THREADOBJECT;
462 mach_port_t thread = tobj->mach_thread;
465 r = thread_resume(thread);
467 if (r != KERN_SUCCESS)
468 vm_abort("thread_resume failed");
472 } while (tobj != mainthreadobj);
477 #if defined(__MIPS__)
478 static void threads_cast_irixresume(void)
480 pthread_mutex_lock(&suspend_ack_lock);
481 pthread_cond_broadcast(&suspend_cond);
482 pthread_mutex_unlock(&suspend_ack_lock);
486 #if !defined(DISABLE_GC)
488 void threads_cast_stopworld(void)
490 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
494 lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
495 pthread_mutex_lock(&threadlistlock);
497 #if defined(__DARWIN__)
498 threads_cast_darwinstop();
499 #elif defined(__CYGWIN__)
503 count = threads_cast_sendsignals(GC_signum1(), 0);
504 for (i = 0; i < count; i++)
505 threads_sem_wait(&suspend_ack);
508 pthread_mutex_unlock(&threadlistlock);
511 void threads_cast_startworld(void)
513 pthread_mutex_lock(&threadlistlock);
514 #if defined(__DARWIN__)
515 threads_cast_darwinresume();
516 #elif defined(__MIPS__)
517 threads_cast_irixresume();
518 #elif defined(__CYGWIN__)
522 threads_cast_sendsignals(GC_signum2(), -1);
524 pthread_mutex_unlock(&threadlistlock);
529 #if !defined(__DARWIN__)
530 static void threads_sigsuspend_handler(ucontext_t *ctx)
535 /* XXX TWISTI: this is just a quick hack */
536 #if defined(ENABLE_JIT)
537 thread_restartcriticalsection(ctx);
540 /* Do as Boehm does. On IRIX a condition variable is used for wake-up
541 (not POSIX async-safe). */
542 #if defined(__IRIX__)
543 pthread_mutex_lock(&suspend_ack_lock);
544 threads_sem_post(&suspend_ack);
545 pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
546 pthread_mutex_unlock(&suspend_ack_lock);
547 #elif defined(__CYGWIN__)
551 threads_sem_post(&suspend_ack);
555 sigdelset(&sigs, sig);
560 /* This function is called from Boehm GC code. */
562 int cacao_suspendhandler(ucontext_t *ctx)
564 if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
567 threads_sigsuspend_handler(ctx);
572 #endif /* DISABLE_GC */
575 /* threads_set_current_threadobject ********************************************
577 Set the current thread object.
580 thread.......the thread object to set
582 *******************************************************************************/
584 void threads_set_current_threadobject(threadobject *thread)
586 #if !defined(HAVE___THREAD)
587 if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
588 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
590 threads_current_threadobject = thread;
595 /* threads_init_threadobject **************************************************
597 Initialize implementation fields of a threadobject.
600 thread............the threadobject
602 ******************************************************************************/
604 void threads_init_threadobject(threadobject *thread)
606 /* get the pthread id */
608 thread->tid = pthread_self();
612 /* TODO destroy all those things */
614 pthread_mutex_init(&(thread->waitmutex), NULL);
615 pthread_cond_init(&(thread->waitcond), NULL);
617 thread->interrupted = false;
618 thread->signaled = false;
619 thread->sleeping = false;
623 /* threads_get_current_threadobject ********************************************
625 Return the threadobject of the current thread.
628 the current threadobject * (an instance of java.lang.Thread)
630 *******************************************************************************/
632 threadobject *threads_get_current_threadobject(void)
638 /* threads_preinit *************************************************************
640 Do some early initialization of stuff required.
642 ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
643 is called AFTER this function!
645 *******************************************************************************/
647 void threads_preinit(void)
649 pthread_mutex_init(&threadlistlock, NULL);
650 pthread_mutex_init(&stopworldlock, NULL);
652 /* initialize exit mutex and condition (on exit we join all
655 pthread_mutex_init(&mutex_join, NULL);
656 pthread_cond_init(&cond_join, NULL);
658 #if !defined(HAVE___THREAD)
659 pthread_key_create(&threads_current_threadobject_key, NULL);
662 /* create internal thread data-structure */
664 mainthreadobj = threads_create_thread();
666 mainthreadobj->object = NULL;
667 mainthreadobj->index = 1;
668 mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
670 /* store the internal thread data-structure in the TSD */
672 threads_set_current_threadobject(mainthreadobj);
674 threads_sem_init(&suspend_ack, 0, 0);
676 /* initialize the threads table */
678 threads_table_init();
680 /* initialize subsystems */
688 /* threads_init ****************************************************************
690 Initializes the threads required by the JVM: main, finalizer.
692 *******************************************************************************/
694 bool threads_init(void)
696 java_objectheader *threadname;
698 java_objectheader *o;
700 #if defined(ENABLE_JAVASE)
701 java_lang_ThreadGroup *threadgroup;
705 #if defined(WITH_CLASSPATH_GNU)
706 java_lang_VMThread *vmt;
709 /* get methods we need in this file */
711 #if defined(WITH_CLASSPATH_GNU)
713 class_resolveclassmethod(class_java_lang_Thread,
715 utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
716 class_java_lang_Thread,
720 class_resolveclassmethod(class_java_lang_Thread,
722 utf_new_char("(Ljava/lang/String;)V"),
723 class_java_lang_Thread,
727 if (method_thread_init == NULL)
730 /* create a java.lang.Thread for the main thread */
732 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
737 /* set the object in the internal data structure */
739 mainthreadobj->object = t;
741 /* thread is running */
743 mainthreadobj->state = THREAD_STATE_RUNNABLE;
745 mainthreadobj->next = mainthreadobj;
746 mainthreadobj->prev = mainthreadobj;
748 threads_table_add(mainthreadobj);
750 /* mark main thread as Java thread */
752 mainthreadobj->flags = THREAD_FLAG_JAVA;
754 #if defined(ENABLE_INTRP)
755 /* create interpreter stack */
758 MSET(intrp_main_stack, 0, u1, opt_stacksize);
759 mainthreadobj->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
763 threadname = javastring_new(utf_new_char("main"));
765 #if defined(ENABLE_JAVASE)
766 /* allocate and init ThreadGroup */
768 threadgroup = (java_lang_ThreadGroup *)
769 native_new_and_init(class_java_lang_ThreadGroup);
771 if (threadgroup == NULL)
775 #if defined(WITH_CLASSPATH_GNU)
776 /* create a java.lang.VMThread for the main thread */
778 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
786 vmt->vmdata = (java_lang_Object *) mainthreadobj;
788 /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
789 o = (java_objectheader *) t;
791 (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
793 #elif defined(WITH_CLASSPATH_CLDC1_1)
796 t->vm_thread = (java_lang_Object *) mainthreadobj;
798 /* call public Thread(String name) */
800 o = (java_objectheader *) t;
802 (void) vm_call_method(method_thread_init, o, threadname);
808 #if defined(ENABLE_JAVASE)
809 t->group = threadgroup;
811 /* add main thread to java.lang.ThreadGroup */
813 m = class_resolveclassmethod(class_java_lang_ThreadGroup,
815 utf_java_lang_Thread__V,
816 class_java_lang_ThreadGroup,
819 o = (java_objectheader *) threadgroup;
821 (void) vm_call_method(m, o, t);
827 threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
829 /* initialize the thread attribute object */
831 if (pthread_attr_init(&threadattr)) {
832 log_println("pthread_attr_init failed: %s", strerror(errno));
836 pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
838 /* everything's ok */
844 /* threads_table_init *********************************************************
846 Initialize the global threads table.
848 ******************************************************************************/
850 static void threads_table_init(void)
855 size = THREADS_INITIAL_TABLE_SIZE;
857 threads_table.size = size;
858 threads_table.table = MNEW(threads_table_entry_t, size);
860 /* link the entries in a freelist */
862 for (i=0; i<size; ++i) {
863 threads_table.table[i].nextfree = i+1;
866 /* terminate the freelist */
868 threads_table.table[size-1].nextfree = 0; /* index 0 is never free */
872 /* threads_table_add **********************************************************
874 Add a thread to the global threads table. The index is entered in the
875 threadobject. The thinlock value for the thread is pre-computed.
878 thread............the thread to add
881 The table index for the newly added thread. This value has also been
882 entered in the threadobject.
885 The caller must hold the threadlistlock!
887 ******************************************************************************/
889 static s4 threads_table_add(threadobject *thread)
896 /* table[0] serves as the head of the freelist */
898 index = threads_table.table[0].nextfree;
900 /* if we got a free index, use it */
904 threads_table.table[0].nextfree = threads_table.table[index].nextfree;
905 threads_table.table[index].thread = thread;
906 thread->index = index;
907 thread->thinlock = lock_pre_compute_thinlock(index);
911 /* we must grow the table */
913 oldsize = threads_table.size;
914 newsize = oldsize * 2;
916 threads_table.table = MREALLOC(threads_table.table, threads_table_entry_t,
918 threads_table.size = newsize;
920 /* link the new entries to a free list */
922 for (i=oldsize; i<newsize; ++i) {
923 threads_table.table[i].nextfree = i+1;
926 /* terminate the freelist */
928 threads_table.table[newsize-1].nextfree = 0; /* index 0 is never free */
930 /* use the first of the new entries */
937 /* threads_table_remove *******************************************************
939 Remove a thread from the global threads table.
942 thread............the thread to remove
945 The caller must hold the threadlistlock!
947 ******************************************************************************/
949 static void threads_table_remove(threadobject *thread)
953 index = thread->index;
955 /* put the index into the freelist */
957 threads_table.table[index] = threads_table.table[0];
958 threads_table.table[0].nextfree = index;
960 /* delete the index in the threadobject to discover bugs */
967 /* threads_startup_thread ******************************************************
969 Thread startup function called by pthread_create.
971 Thread which have a startup.function != NULL are marked as internal
972 threads. All other threads are threated as normal Java threads.
974 NOTE: This function is not called directly by pthread_create. The Boehm GC
975 inserts its own GC_start_routine in between, which then calls
979 t............the argument passed to pthread_create, ie. a pointer to
980 a startupinfo struct. CAUTION: When the `psem` semaphore
981 is posted, the startupinfo struct becomes invalid! (It
982 is allocated on the stack of threads_start_thread.)
984 ******************************************************************************/
986 static void *threads_startup_thread(void *t)
988 startupinfo *startup;
989 threadobject *thread;
990 #if defined(WITH_CLASSPATH_GNU)
991 java_lang_VMThread *vmt;
997 java_objectheader *o;
998 functionptr function;
1000 #if defined(ENABLE_INTRP)
1001 u1 *intrp_thread_stack;
1003 /* create interpreter stack */
1006 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1007 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1010 intrp_thread_stack = NULL;
1013 /* get passed startupinfo structure and the values in there */
1016 t = NULL; /* make sure it's not used wrongly */
1018 thread = startup->thread;
1019 function = startup->function;
1020 psem = startup->psem;
1022 /* Seems like we've encountered a situation where thread->tid was not set by
1023 * pthread_create. We alleviate this problem by waiting for pthread_create
1025 threads_sem_wait(startup->psem_first);
1027 #if defined(__DARWIN__)
1028 thread->mach_thread = mach_thread_self();
1031 /* store the internal thread data-structure in the TSD */
1033 threads_set_current_threadobject(thread);
1035 /* thread is running */
1037 thread->state = THREAD_STATE_RUNNABLE;
1039 /* insert the thread into the threadlist and the threads table */
1041 pthread_mutex_lock(&threadlistlock);
1043 thread->prev = mainthreadobj;
1044 thread->next = tnext = mainthreadobj->next;
1045 mainthreadobj->next = thread;
1046 tnext->prev = thread;
1048 threads_table_add(thread);
1050 pthread_mutex_unlock(&threadlistlock);
1052 /* tell threads_startup_thread that we registered ourselves */
1053 /* CAUTION: *startup becomes invalid with this! */
1056 threads_sem_post(psem);
1058 /* set our priority */
1060 threads_set_thread_priority(thread->tid, thread->object->priority);
1062 #if defined(ENABLE_INTRP)
1063 /* set interpreter stack */
1066 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1069 #if defined(ENABLE_JVMTI)
1070 /* fire thread start event */
1073 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1076 /* find and run the Thread.run()V method if no other function was passed */
1078 if (function == NULL) {
1079 /* this is a normal Java thread */
1081 thread->flags |= THREAD_FLAG_JAVA;
1083 #if defined(WITH_CLASSPATH_GNU)
1084 /* We need to start the run method of
1085 java.lang.VMThread. Since this is a final class, we can use
1086 the class object directly. */
1088 c = class_java_lang_VMThread;
1089 #elif defined(WITH_CLASSPATH_CLDC1_1)
1090 c = thread->object->header.vftbl->class;
1093 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1096 vm_abort("threads_startup_thread: run() method not found in class");
1098 /* set ThreadMXBean variables */
1100 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1101 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1103 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1104 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1105 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1106 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1108 #if defined(WITH_CLASSPATH_GNU)
1109 /* we need to start the run method of java.lang.VMThread */
1111 vmt = (java_lang_VMThread *) thread->object->vmThread;
1112 o = (java_objectheader *) vmt;
1114 #elif defined(WITH_CLASSPATH_CLDC1_1)
1115 o = (java_objectheader *) thread->object;
1118 /* run the thread */
1120 (void) vm_call_method(m, o);
1123 /* this is an internal thread */
1125 thread->flags |= THREAD_FLAG_INTERNAL;
1127 /* set ThreadMXBean variables */
1129 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1130 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1132 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1133 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1134 _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1135 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1137 /* call passed function, e.g. finalizer_thread */
1142 #if defined(ENABLE_JVMTI)
1143 /* fire thread end event */
1146 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1149 if (!threads_detach_thread(thread))
1150 vm_abort("threads_startup_thread: threads_detach_thread failed");
1152 /* set ThreadMXBean variables */
1154 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1160 /* threads_start_thread ********************************************************
1162 Start a thread in the JVM. Both (vm internal and java) thread objects exist.
1165 thread.......the thread object
1166 function.....function to run in the new thread. NULL means that the
1167 "run" method of the object `t` should be called
1169 ******************************************************************************/
1171 void threads_start_thread(threadobject *thread, functionptr function)
1175 pthread_attr_t attr;
1176 startupinfo startup;
1178 /* fill startupinfo structure passed by pthread_create to
1179 * threads_startup_thread */
1181 startup.thread = thread;
1182 startup.function = function; /* maybe we don't call Thread.run()V */
1183 startup.psem = &sem;
1184 startup.psem_first = &sem_first;
1186 threads_sem_init(&sem, 0, 0);
1187 threads_sem_init(&sem_first, 0, 0);
1189 /* initialize thread attribute object */
1191 if (pthread_attr_init(&attr))
1192 vm_abort("pthread_attr_init failed: %s", strerror(errno));
1194 /* initialize thread stacksize */
1196 if (pthread_attr_setstacksize(&attr, opt_stacksize))
1197 vm_abort("pthread_attr_setstacksize failed: %s", strerror(errno));
1199 /* create the thread */
1201 if (pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup))
1202 vm_abort("pthread_create failed: %s", strerror(errno));
1204 /* signal that pthread_create has returned, so thread->tid is valid */
1206 threads_sem_post(&sem_first);
1208 /* wait here until the thread has entered itself into the thread list */
1210 threads_sem_wait(&sem);
1215 sem_destroy(&sem_first);
1219 /* threads_set_thread_priority *************************************************
1221 Set the priority of the given thread.
1224 tid..........thread id
1225 priority.....priority to set
1227 ******************************************************************************/
1229 void threads_set_thread_priority(pthread_t tid, int priority)
1231 struct sched_param schedp;
1234 pthread_getschedparam(tid, &policy, &schedp);
1235 schedp.sched_priority = priority;
1236 pthread_setschedparam(tid, policy, &schedp);
1240 /* threads_attach_current_thread ***********************************************
1242 Attaches the current thread to the VM. Used in JNI.
1244 *******************************************************************************/
1246 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1248 threadobject *thread;
1250 java_objectheader *s;
1251 java_objectheader *o;
1252 java_lang_Thread *t;
1254 #if defined(ENABLE_JAVASE)
1255 java_lang_ThreadGroup *group;
1259 #if defined(WITH_CLASSPATH_GNU)
1260 java_lang_VMThread *vmt;
1263 /* create internal thread data-structure */
1265 thread = threads_create_thread();
1267 /* create a java.lang.Thread object */
1269 t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1276 /* thread is running */
1278 thread->state = THREAD_STATE_RUNNABLE;
1280 /* insert the thread into the threadlist and the threads table */
1282 pthread_mutex_lock(&threadlistlock);
1284 thread->prev = mainthreadobj;
1285 thread->next = mainthreadobj->next;
1286 mainthreadobj->next = thread;
1287 thread->next->prev = thread;
1289 threads_table_add(thread);
1291 pthread_mutex_unlock(&threadlistlock);
1293 /* mark thread as Java thread */
1295 thread->flags = THREAD_FLAG_JAVA;
1298 thread->flags |= THREAD_FLAG_DAEMON;
1300 #if defined(ENABLE_INTRP)
1301 /* create interpreter stack */
1304 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1305 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1309 #if defined(WITH_CLASSPATH_GNU)
1310 /* create a java.lang.VMThread object */
1312 vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1317 /* set the thread */
1320 vmt->vmdata = (java_lang_Object *) thread;
1321 #elif defined(WITH_CLASSPATH_CLDC1_1)
1322 t->vm_thread = (java_lang_Object *) thread;
1325 if (vm_aargs != NULL) {
1326 u = utf_new_char(vm_aargs->name);
1327 #if defined(ENABLE_JAVASE)
1328 group = (java_lang_ThreadGroup *) vm_aargs->group;
1333 #if defined(ENABLE_JAVASE)
1334 group = mainthreadobj->object->group;
1338 /* the the thread name */
1340 s = javastring_new(u);
1342 /* for convenience */
1344 o = (java_objectheader *) thread->object;
1346 #if defined(WITH_CLASSPATH_GNU)
1347 (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1349 #elif defined(WITH_CLASSPATH_CLDC1_1)
1350 (void) vm_call_method(method_thread_init, o, s);
1356 #if defined(ENABLE_JAVASE)
1357 /* store the thread group in the object */
1359 thread->object->group = group;
1361 /* add thread to given thread-group */
1363 m = class_resolveclassmethod(group->header.vftbl->class,
1365 utf_java_lang_Thread__V,
1366 class_java_lang_ThreadGroup,
1369 o = (java_objectheader *) group;
1371 (void) vm_call_method(m, o, t);
1381 /* threads_detach_thread *******************************************************
1383 Detaches the passed thread from the VM. Used in JNI.
1385 *******************************************************************************/
1387 bool threads_detach_thread(threadobject *thread)
1389 #if defined(ENABLE_JAVASE)
1390 java_lang_ThreadGroup *group;
1392 java_objectheader *o;
1393 java_lang_Thread *t;
1396 /* Allow lock record pools to be used by other threads. They
1397 cannot be deleted so we'd better not waste them. */
1399 /* XXX We have to find a new way to free lock records */
1400 /* with the new locking algorithm. */
1401 /* lock_record_free_pools(thread->ee.lockrecordpools); */
1403 /* XXX implement uncaught exception stuff (like JamVM does) */
1405 #if defined(ENABLE_JAVASE)
1406 /* remove thread from the thread group */
1408 group = thread->object->group;
1410 /* XXX TWISTI: should all threads be in a ThreadGroup? */
1412 if (group != NULL) {
1413 m = class_resolveclassmethod(group->header.vftbl->class,
1415 utf_java_lang_Thread__V,
1416 class_java_lang_ThreadGroup,
1422 o = (java_objectheader *) group;
1425 (void) vm_call_method(m, o, t);
1432 /* thread is terminated */
1434 thread->state = THREAD_STATE_TERMINATED;
1436 /* lock thread list */
1438 pthread_mutex_lock(&threadlistlock);
1440 /* remove thread from thread list and threads table */
1442 thread->next->prev = thread->prev;
1443 thread->prev->next = thread->next;
1445 threads_table_remove(thread);
1447 /* unlock thread list */
1449 pthread_mutex_unlock(&threadlistlock);
1451 /* signal that this thread has finished */
1453 pthread_mutex_lock(&mutex_join);
1454 pthread_cond_signal(&cond_join);
1455 pthread_mutex_unlock(&mutex_join);
1457 /* free the vm internal thread object */
1459 #if defined(ENABLE_GC_BOEHM)
1462 FREE(thread, threadobject);
1465 #if defined(ENABLE_STATISTICS)
1467 size_threadobject -= sizeof(threadobject);
1474 /* threads_find_non_daemon_thread **********************************************
1476 Helper function used by threads_join_all_threads for finding
1477 non-daemon threads that are still running.
1479 *******************************************************************************/
1481 static threadobject *threads_find_non_daemon_thread(void)
1483 threadobject *thread;
1485 /* lock the thread list */
1487 pthread_mutex_lock(&threadlistlock);
1489 /* iterate over all threads */
1491 thread = mainthreadobj->next;
1493 while (thread != mainthreadobj) {
1494 if (!(thread->flags & THREAD_FLAG_DAEMON)) {
1495 /* unlock thread list */
1497 pthread_mutex_unlock(&threadlistlock);
1502 thread = thread->next;
1505 /* unlock thread list */
1507 pthread_mutex_unlock(&threadlistlock);
1513 /* threads_join_all_threads ****************************************************
1515 Join all non-daemon threads.
1517 *******************************************************************************/
1519 void threads_join_all_threads(void)
1521 threadobject *thread;
1523 /* get current thread */
1525 thread = THREADOBJECT;
1527 /* this thread is waiting for all non-daemon threads to exit */
1529 thread->state = THREAD_STATE_WAITING;
1531 /* enter join mutex */
1533 pthread_mutex_lock(&mutex_join);
1535 /* wait for condition as long as we have non-daemon threads */
1537 while (threads_find_non_daemon_thread() != NULL)
1538 pthread_cond_wait(&cond_join, &mutex_join);
1540 /* leave join mutex */
1542 pthread_mutex_unlock(&mutex_join);
1546 /* threads_timespec_earlier ****************************************************
1548 Return true if timespec tv1 is earlier than timespec tv2.
1551 tv1..........first timespec
1552 tv2..........second timespec
1555 true, if the first timespec is earlier
1557 *******************************************************************************/
1559 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1560 const struct timespec *tv2)
1562 return (tv1->tv_sec < tv2->tv_sec)
1564 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1568 /* threads_current_time_is_earlier_than ****************************************
1570 Check if the current time is earlier than the given timespec.
1573 tv...........the timespec to compare against
1576 true, if the current time is earlier
1578 *******************************************************************************/
1580 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1582 struct timeval tvnow;
1583 struct timespec tsnow;
1585 /* get current time */
1587 if (gettimeofday(&tvnow, NULL) != 0)
1588 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1590 /* convert it to a timespec */
1592 tsnow.tv_sec = tvnow.tv_sec;
1593 tsnow.tv_nsec = tvnow.tv_usec * 1000;
1595 /* compare current time with the given timespec */
1597 return threads_timespec_earlier(&tsnow, tv);
1601 /* threads_wait_with_timeout ***************************************************
1603 Wait until the given point in time on a monitor until either
1604 we are notified, we are interrupted, or the time is up.
1607 t............the current thread
1608 wakeupTime...absolute (latest) wakeup time
1609 If both tv_sec and tv_nsec are zero, this function
1610 waits for an unlimited amount of time.
1613 true.........if the wait has been interrupted,
1614 false........if the wait was ended by notification or timeout
1616 *******************************************************************************/
1618 static bool threads_wait_with_timeout(threadobject *thread,
1619 struct timespec *wakeupTime)
1621 bool wasinterrupted;
1623 /* acquire the waitmutex */
1625 pthread_mutex_lock(&thread->waitmutex);
1627 /* mark us as sleeping */
1629 thread->sleeping = true;
1631 /* wait on waitcond */
1633 if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1635 while (!thread->interrupted && !thread->signaled
1636 && threads_current_time_is_earlier_than(wakeupTime))
1638 thread->state = THREAD_STATE_TIMED_WAITING;
1640 pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1643 thread->state = THREAD_STATE_RUNNABLE;
1648 while (!thread->interrupted && !thread->signaled) {
1649 thread->state = THREAD_STATE_WAITING;
1651 pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1653 thread->state = THREAD_STATE_RUNNABLE;
1657 /* check if we were interrupted */
1659 wasinterrupted = thread->interrupted;
1661 /* reset all flags */
1663 thread->interrupted = false;
1664 thread->signaled = false;
1665 thread->sleeping = false;
1667 /* release the waitmutex */
1669 pthread_mutex_unlock(&thread->waitmutex);
1671 return wasinterrupted;
1675 /* threads_wait_with_timeout_relative ******************************************
1677 Wait for the given maximum amount of time on a monitor until either
1678 we are notified, we are interrupted, or the time is up.
1681 t............the current thread
1682 millis.......milliseconds to wait
1683 nanos........nanoseconds to wait
1686 true.........if the wait has been interrupted,
1687 false........if the wait was ended by notification or timeout
1689 *******************************************************************************/
1691 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1694 struct timespec wakeupTime;
1696 /* calculate the the (latest) wakeup time */
1698 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1702 return threads_wait_with_timeout(thread, &wakeupTime);
1706 /* threads_calc_absolute_time **************************************************
1708 Calculate the absolute point in time a given number of ms and ns from now.
1711 millis............milliseconds from now
1712 nanos.............nanoseconds from now
1715 *tm...............receives the timespec of the absolute point in time
1717 *******************************************************************************/
1719 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1721 if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1724 gettimeofday(&tv, NULL);
1725 tv.tv_sec += millis / 1000;
1727 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1728 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1729 tm->tv_nsec = nsec % 1000000000;
1738 /* threads_thread_interrupt ****************************************************
1740 Interrupt the given thread.
1742 The thread gets the "waitcond" signal and
1743 its interrupted flag is set to true.
1746 thread............the thread to interrupt
1748 *******************************************************************************/
1750 void threads_thread_interrupt(threadobject *thread)
1752 /* Signal the thread a "waitcond" and tell it that it has been
1755 pthread_mutex_lock(&thread->waitmutex);
1757 /* Interrupt blocking system call using a signal. */
1759 pthread_kill(thread->tid, SIGHUP);
1761 if (thread->sleeping)
1762 pthread_cond_signal(&thread->waitcond);
1764 thread->interrupted = true;
1766 pthread_mutex_unlock(&thread->waitmutex);
1770 /* threads_check_if_interrupted_and_reset **************************************
1772 Check if the current thread has been interrupted and reset the
1776 true, if the current thread had been interrupted
1778 *******************************************************************************/
1780 bool threads_check_if_interrupted_and_reset(void)
1782 threadobject *thread;
1785 thread = THREADOBJECT;
1787 /* get interrupted flag */
1789 intr = thread->interrupted;
1791 /* reset interrupted flag */
1793 thread->interrupted = false;
1799 /* threads_thread_has_been_interrupted *****************************************
1801 Check if the given thread has been interrupted
1804 t............the thread to check
1807 true, if the given thread had been interrupted
1809 *******************************************************************************/
1811 bool threads_thread_has_been_interrupted(threadobject *thread)
1813 return thread->interrupted;
1817 /* threads_sleep ***************************************************************
1819 Sleep the current thread for the specified amount of time.
1821 *******************************************************************************/
1823 void threads_sleep(s8 millis, s4 nanos)
1825 threadobject *thread;
1826 struct timespec wakeupTime;
1827 bool wasinterrupted;
1829 thread = THREADOBJECT;
1831 threads_calc_absolute_time(&wakeupTime, millis, nanos);
1833 wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1836 exceptions_throw_interruptedexception();
1840 /* threads_yield ***************************************************************
1842 Yield to the scheduler.
1844 *******************************************************************************/
1846 void threads_yield(void)
1852 /* threads_table_dump *********************************************************
1854 Dump the threads table for debugging purposes.
1857 file..............stream to write to
1859 ******************************************************************************/
1861 #if !defined(NDEBUG) && 0
1862 static void threads_table_dump(FILE *file)
1868 pthread_mutex_lock(&threadlistlock);
1870 size = threads_table.size;
1872 fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1874 for (i=0; i<size; ++i) {
1875 index = threads_table.table[i].nextfree;
1877 fprintf(file, "%4d: ", i);
1880 fprintf(file, "free, nextfree = %d\n", (int) index);
1883 fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1887 fprintf(file, "======== END OF THREADS TABLE ========\n");
1889 pthread_mutex_unlock(&threadlistlock);
1894 * These are local overrides for various environment variables in Emacs.
1895 * Please do not remove this and leave it at the end of the file, where
1896 * Emacs will automagically detect them.
1897 * ---------------------------------------------------------------------
1900 * indent-tabs-mode: t
1904 * vim:noexpandtab:sw=4:ts=4: