* src/threads/native/threads.c (threads_dump): Cast pthread_t to long
[cacao.git] / src / threads / native / threads.c
index a9925e60b318ec5e127d37e86726cdfa1badcf50..e89e44006321ce0f4b7e03ba57d031242ba9415c 100644 (file)
@@ -29,7 +29,7 @@
    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 $
 
 */
 
@@ -201,7 +201,7 @@ static s4 threads_table_add(threadobject *thread);
 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
 
@@ -212,6 +212,9 @@ static void threads_table_dump(FILE *file);
 /* 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.  */
@@ -640,6 +643,7 @@ int cacao_suspendhandler(ucontext_t *ctx)
 }
 #endif
 
+
 /* threads_set_current_threadobject ********************************************
 
    Set the current thread object.
@@ -678,6 +682,9 @@ threadobject *threads_get_current_threadobject(void)
 
    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)
@@ -695,13 +702,9 @@ 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)
@@ -735,7 +738,6 @@ bool threads_init(void)
        java_lang_Thread      *mainthread;
        java_lang_ThreadGroup *threadgroup;
        threadobject          *tempthread;
-       methodinfo            *method;
 
        tempthread = mainthreadobj;
 
@@ -749,6 +751,28 @@ bool threads_init(void)
 
        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);
@@ -803,17 +827,8 @@ bool threads_init(void)
 
        /* 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;
@@ -822,22 +837,14 @@ bool threads_init(void)
 
        /* 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 */
 
@@ -1102,13 +1109,12 @@ static void *threads_startup_thread(void *t)
                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 */
 
@@ -1148,37 +1154,12 @@ static void *threads_startup_thread(void *t)
 
 #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;
 }
@@ -1246,6 +1227,174 @@ void threads_start_thread(java_lang_Thread *t, functionptr function)
 }
 
 
+/* 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
@@ -1481,7 +1630,7 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 }
 
 
-/* threads_interrupt_thread ****************************************************
+/* threads_thread_interrupt ****************************************************
 
    Interrupt the given thread.
 
@@ -1493,17 +1642,26 @@ static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 
 *******************************************************************************/
 
-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);
 }
 
@@ -1578,7 +1736,7 @@ void threads_sleep(s8 millis, s4 nanos)
 }
 
 
-/* threads_yield *****************************************************************
+/* threads_yield ***************************************************************
 
    Yield to the scheduler.
 
@@ -1590,7 +1748,7 @@ void threads_yield(void)
 }
 
 
-/* threads_java_lang_Thread_set_priority ***********************************************************
+/* threads_java_lang_Thread_set_priority ***************************************
 
    Set the priority for the given java.lang.Thread.
 
@@ -1619,12 +1777,14 @@ void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
 
 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");
 
@@ -1633,12 +1793,12 @@ void threads_dump(void)
        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);
@@ -1651,22 +1811,18 @@ void threads_dump(void)
                                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));
 }
 
 
@@ -1679,7 +1835,7 @@ void threads_dump(void)
 
 ******************************************************************************/
 
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && 0
 static void threads_table_dump(FILE *file)
 {
        s4 i;
@@ -1698,7 +1854,7 @@ static void threads_table_dump(FILE *file)
                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);