Changes: Christian Thalinger
Edwin Steiner
- $Id: threads.c 5590 2006-09-30 13:51:12Z michi $
+ $Id: threads.c 5867 2006-10-30 11:04:47Z edwin $
*/
static void threads_table_remove(threadobject *thread);
static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && 0
static void threads_table_dump(FILE *file);
#endif
/* the main thread */
threadobject *mainthreadobj;
+static methodinfo *method_thread_init;
+static methodinfo *method_threadgroup_add;
+
/* the thread object of the current thread */
/* This is either a thread-local variable defined with __thread, or */
/* a thread-specific value stored with key threads_current_threadobject_key. */
}
#endif
+
/* threads_set_current_threadobject ********************************************
Set the current thread object.
Do some early initialization of stuff required.
+ ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
+ is called AFTER this function!
+
*******************************************************************************/
void threads_preinit(void)
pthread_mutex_init(&threadlistlock, NULL);
pthread_mutex_init(&stopworldlock, NULL);
- /* Allocate something so the garbage collector's signal handlers
- are installed. */
- heap_allocate(1, false, NULL);
-
mainthreadobj = NEW(threadobject);
- mainthreadobj->tid = pthread_self();
- mainthreadobj->index = 1;
+ mainthreadobj->tid = pthread_self();
+ mainthreadobj->index = 1;
mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
#if !defined(HAVE___THREAD)
java_lang_Thread *mainthread;
java_lang_ThreadGroup *threadgroup;
threadobject *tempthread;
- methodinfo *method;
tempthread = mainthreadobj;
class_java_lang_VMThread->instancesize = sizeof(threadobject);
+ /* get methods we need in this file */
+
+ method_thread_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
+ class_java_lang_Thread,
+ true);
+
+ if (method_thread_init == NULL)
+ return false;
+
+ method_threadgroup_add =
+ class_resolveclassmethod(class_java_lang_ThreadGroup,
+ utf_new_char("addThread"),
+ utf_new_char("(Ljava/lang/Thread;)V"),
+ class_java_lang_ThreadGroup,
+ true);
+
+ if (method_threadgroup_add == NULL)
+ return false;
+
/* create a VMThread */
mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
/* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
- method = class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
- class_java_lang_Thread,
- true);
-
- if (method == NULL)
- return false;
-
- (void) vm_call_method(method, (java_objectheader *) mainthread,
- mainthreadobj, threadname, 5, false);
+ (void) vm_call_method(method_thread_init, (java_objectheader *) mainthread,
+ mainthreadobj, threadname, NORM_PRIORITY, false);
if (*exceptionptr)
return false;
/* add mainthread to ThreadGroup */
- method = class_resolveclassmethod(class_java_lang_ThreadGroup,
- utf_new_char("addThread"),
- utf_new_char("(Ljava/lang/Thread;)V"),
- class_java_lang_ThreadGroup,
- true);
-
- if (method == NULL)
- return false;
-
- (void) vm_call_method(method, (java_objectheader *) threadgroup,
+ (void) vm_call_method(method_threadgroup_add,
+ (java_objectheader *) threadgroup,
mainthread);
if (*exceptionptr)
return false;
- threads_set_thread_priority(pthread_self(), 5);
+ threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
/* initialize the thread attribute object */
thread->_global_sp = (void *) (intrp_thread_stack + opt_stacksize);
#endif
-
-
#if defined(ENABLE_JVMTI)
/* fire thread start event */
- if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
-#endif
+ if (jvmti)
+ jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
+#endif
/* find and run the Thread.run()V method if no other function was passed */
#if defined(ENABLE_JVMTI)
/* fire thread end event */
- if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
-#endif
-
-
- /* Allow lock record pools to be used by other threads. They
- cannot be deleted so we'd better not waste them. */
-
- /* XXX We have to find a new way to free lock records */
- /* with the new locking algorithm. */
- /* lock_record_free_pools(thread->ee.lockrecordpools); */
-
- /* remove thread from thread list and threads table, do this inside a lock */
-
- pthread_mutex_lock(&threadlistlock);
-
- thread->next->prev = thread->prev;
- thread->prev->next = thread->next;
-
- threads_table_remove(thread);
-
- pthread_mutex_unlock(&threadlistlock);
-
- /* reset thread id (lock on joinmutex? TWISTI) */
- pthread_mutex_lock(&thread->joinmutex);
- thread->tid = 0;
- pthread_mutex_unlock(&thread->joinmutex);
+ if (jvmti)
+ jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
- /* tell everyone that a thread has finished */
-
- pthread_cond_broadcast(&thread->joincond);
+ threads_detach_thread(thread);
return NULL;
}
}
+/* threads_attach_current_thread ***********************************************
+
+ Attaches the current thread to the VM. Used in JNI.
+
+*******************************************************************************/
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+ threadobject *thread;
+ java_lang_Thread *t;
+ utf *u;
+ java_lang_String *s;
+ java_lang_ThreadGroup *group;
+ java_objectheader *o;
+
+ /* create a java.lang.VMThread object */
+
+ thread = (threadobject *) builtin_new(class_java_lang_VMThread);
+
+ if (thread == NULL)
+ return false;
+
+ threads_init_threadobject(&thread->o);
+ threads_set_current_threadobject(thread);
+ lock_init_execution_env(thread);
+
+ /* insert the thread into the threadlist and the threads table */
+
+ pthread_mutex_lock(&threadlistlock);
+
+ thread->prev = mainthreadobj;
+ thread->next = mainthreadobj->next;
+ mainthreadobj->next = thread;
+ thread->next->prev = thread;
+
+ threads_table_add(thread);
+
+ pthread_mutex_unlock(&threadlistlock);
+
+ /* mark main thread as Java thread */
+
+ thread->flags = THREAD_FLAG_JAVA;
+
+#if defined(ENABLE_INTRP)
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ thread->_global_sp = intrp_main_stack + opt_stacksize;
+ }
+#endif
+
+ /* create a java.lang.Thread object */
+
+ t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+ if (t == NULL)
+ return false;
+
+ thread->o.thread = t;
+
+ if (vm_aargs != NULL) {
+ u = utf_new_char(vm_aargs->name);
+ group = (java_lang_ThreadGroup *) vm_aargs->group;
+ }
+ else {
+ u = utf_null;
+ group = mainthreadobj->o.thread->group;
+ }
+
+ s = javastring_new(u);
+
+ o = (java_objectheader *) t;
+
+ (void) vm_call_method(method_thread_init, o, thread, s, NORM_PRIORITY,
+ isdaemon);
+
+ if (*exceptionptr)
+ return false;
+
+ /* store the thread group in the object */
+
+ t->group = group;
+
+ o = (java_objectheader *) group;
+
+ (void) vm_call_method(method_threadgroup_add, o, t);
+
+ if (*exceptionptr)
+ return false;
+
+ return true;
+}
+
+
+/* threads_detach_thread *******************************************************
+
+ Detaches the passed thread from the VM. Used in JNI.
+
+*******************************************************************************/
+
+bool threads_detach_thread(threadobject *thread)
+{
+ java_lang_Thread *t;
+ java_lang_ThreadGroup *group;
+ methodinfo *m;
+ java_objectheader *o;
+
+ /* Allow lock record pools to be used by other threads. They
+ cannot be deleted so we'd better not waste them. */
+
+ /* XXX We have to find a new way to free lock records */
+ /* with the new locking algorithm. */
+ /* lock_record_free_pools(thread->ee.lockrecordpools); */
+
+ /* XXX implement uncaught exception stuff (like JamVM does) */
+
+ /* remove thread from the thread group */
+
+ t = thread->o.thread;
+ group = t->group;
+
+ /* XXX TWISTI: should all threads be in a ThreadGroup? */
+
+ if (group != NULL) {
+ m = class_resolveclassmethod(group->header.vftbl->class,
+ utf_removeThread,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+
+ if (m == NULL)
+ return false;
+
+ o = (java_objectheader *) group;
+
+ (void) vm_call_method(m, o, t);
+
+ if (*exceptionptr)
+ return false;
+ }
+
+ /* remove thread from thread list and threads table, do this
+ inside a lock */
+
+ pthread_mutex_lock(&threadlistlock);
+
+ thread->next->prev = thread->prev;
+ thread->prev->next = thread->next;
+
+ threads_table_remove(thread);
+
+ pthread_mutex_unlock(&threadlistlock);
+
+ /* reset thread id (lock on joinmutex? TWISTI) */
+
+ pthread_mutex_lock(&thread->joinmutex);
+ thread->tid = 0;
+ pthread_mutex_unlock(&thread->joinmutex);
+
+ /* tell everyone that a thread has finished */
+
+ pthread_cond_broadcast(&thread->joincond);
+
+ return true;
+}
+
+
/* threads_find_non_daemon_thread **********************************************
Helper function used by threads_join_all_threads for finding
}
-/* threads_interrupt_thread ****************************************************
+/* threads_thread_interrupt ****************************************************
Interrupt the given thread.
*******************************************************************************/
-void threads_interrupt_thread(java_lang_VMThread *thread)
+void threads_thread_interrupt(java_lang_VMThread *thread)
{
- threadobject *t = (threadobject*) thread;
+ threadobject *t;
+
+ t = (threadobject *) thread;
- /* signal the thread a "waitcond" and tell it that it has been */
- /* interrupted */
+ /* Signal the thread a "waitcond" and tell it that it has been
+ interrupted. */
pthread_mutex_lock(&t->waitmutex);
+
+ /* Interrupt blocking system call using a signal. */
+
+ pthread_kill(t->tid, SIGHUP);
+
if (t->sleeping)
pthread_cond_signal(&t->waitcond);
+
t->interrupted = true;
+
pthread_mutex_unlock(&t->waitmutex);
}
}
-/* threads_yield *****************************************************************
+/* threads_yield ***************************************************************
Yield to the scheduler.
}
-/* threads_java_lang_Thread_set_priority ***********************************************************
+/* threads_java_lang_Thread_set_priority ***************************************
Set the priority for the given java.lang.Thread.
void threads_dump(void)
{
- threadobject *tobj;
+ threadobject *thread;
java_lang_VMThread *vmt;
java_lang_Thread *t;
utf *name;
- tobj = mainthreadobj;
+ thread = mainthreadobj;
+
+ /* XXX we should stop the world here */
printf("Full thread dump CACAO "VERSION":\n");
do {
/* get thread objects */
- vmt = &tobj->o;
+ vmt = &thread->o;
t = vmt->thread;
/* the thread may be currently in initalization, don't print it */
- if (t) {
+ if (t != NULL) {
/* get thread name */
name = javastring_toutf(t->name, false);
printf("daemon ");
#if SIZEOF_VOID_P == 8
- printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
+ printf("prio=%d tid=0x%016lx\n", t->priority, (long) thread->tid);
#else
- printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
+ printf("prio=%d tid=0x%08lx\n", t->priority, (long) thread->tid);
#endif
- /* send SIGUSR1 to thread to print stacktrace */
-
- pthread_kill(tobj->tid, SIGUSR1);
-
- /* sleep this thread a bit, so the signal can reach the thread */
+ /* dump trace of thread */
- threads_sleep(10, 0);
+ stacktrace_dump_trace(thread);
}
- tobj = tobj->next;
- } while (tobj && (tobj != mainthreadobj));
+ thread = thread->next;
+ } while ((thread != NULL) && (thread != mainthreadobj));
}
******************************************************************************/
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && 0
static void threads_table_dump(FILE *file)
{
s4 i;
fprintf(file, "%4d: ", i);
if (index < size) {
- fprintf(file, "free, nextfree = %d\n", index);
+ fprintf(file, "free, nextfree = %d\n", (int) index);
}
else {
fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);