* src/threads/native/threads.c (threads_init) [!ENABLE_GC_CACAO]: Fixed bug for
[cacao.git] / src / threads / native / threads.c
index daa171bf8be8f1996597765c516fdefd9b3696e2..c159e9ccc017000b3496a312568b9c5a0dcea816 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/native/threads.c - native threads support
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Stefan Ring
-            Christian Thalinger
-            Edwin Steiner
-
-   $Id: threads.c 6228 2006-12-26 19:56:58Z twisti $
+   $Id: threads.c 7478 2007-03-08 02:59:31Z michi $
 
 */
 
 
 #include "mm/gc-common.h"
 #include "mm/memory.h"
+
+#include "native/jni.h"
 #include "native/native.h"
 #include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
 #include "native/include/java_lang_Thread.h"
-#include "native/include/java_lang_ThreadGroup.h"
-#include "native/include/java_lang_VMThread.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/include/java_lang_ThreadGroup.h"
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_VMThread.h"
+#endif
+
+#include "threads/threads-common.h"
+
 #include "threads/native/threads.h"
+
 #include "toolbox/avl.h"
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/options.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
+#include "vmcore/options.h"
+
 #if !defined(__DARWIN__)
 # if defined(__LINUX__)
 #  define GC_LINUX_THREADS
@@ -663,6 +672,7 @@ void threads_preinit(void)
        pthread_mutex_init(&stopworldlock, NULL);
 
        mainthreadobj = NEW(threadobject);
+       mainthreadobj->object   = NULL;
        mainthreadobj->tid      = pthread_self();
        mainthreadobj->index    = 1;
        mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
@@ -695,12 +705,18 @@ void threads_preinit(void)
 bool threads_init(void)
 {
        java_lang_String      *threadname;
-       java_lang_VMThread    *vmt;
-       java_lang_ThreadGroup *threadgroup;
        threadobject          *tempthread;
-       methodinfo            *m;
        java_objectheader     *o;
+
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *threadgroup;
+       methodinfo            *m;
        java_lang_Thread      *t;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
 
        tempthread = mainthreadobj;
 
@@ -708,31 +724,55 @@ bool threads_init(void)
        /*     with the new locking algorithm.                */
        /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
 
+#if 0
        /* This is kinda tricky, we grow the java.lang.Thread object so we
           can keep the execution environment there. No Thread object must
           have been created at an earlier time. */
 
        class_java_lang_Thread->instancesize = sizeof(threadobject);
+#endif
 
        /* get methods we need in this file */
 
+#if defined(WITH_CLASSPATH_GNU)
        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);
+#else
+       method_thread_init =
+               class_resolveclassmethod(class_java_lang_Thread,
+                                                                utf_init,
+                                                                utf_new_char("(Ljava/lang/String;)V"),
+                                                                class_java_lang_Thread,
+                                                                true);
+#endif
 
        if (method_thread_init == NULL)
                return false;
 
-       /* create a java.lang.Thread for the main thread */
+       /* create a vm internal thread object for the main thread */
+       /* XXX Michi: we do not need to do this here, we could use the one
+              created by threads_preinit() */
 
-       mainthreadobj = (threadobject *) builtin_new(class_java_lang_Thread);
+#if defined(ENABLE_GC_CACAO)
+       mainthreadobj = NEW(threadobject);
+#else
+       mainthreadobj = GCNEW(threadobject);
+#endif
 
        if (mainthreadobj == NULL)
                return false;
 
+       /* create a java.lang.Thread for the main thread */
+
+       mainthreadobj->object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       if (mainthreadobj->object == NULL)
+               return false;
+
        FREE(tempthread, threadobject);
 
        threads_init_threadobject(mainthreadobj);
@@ -761,6 +801,7 @@ bool threads_init(void)
 
        threadname = javastring_new(utf_new_char("main"));
 
+#if defined(ENABLE_JAVASE)
        /* allocate and init ThreadGroup */
 
        threadgroup = (java_lang_ThreadGroup *)
@@ -768,6 +809,7 @@ bool threads_init(void)
 
        if (threadgroup == NULL)
                throw_exception_exit();
+#endif
 
 #if defined(WITH_CLASSPATH_GNU)
        /* create a java.lang.VMThread for the main thread */
@@ -779,22 +821,31 @@ bool threads_init(void)
 
        /* set the thread */
 
-       t           = (java_lang_Thread *) mainthreadobj;
-       vmt->thread = t;
+       vmt->thread = mainthreadobj->object;
+       vmt->vmdata = (java_lang_Object *) mainthreadobj;
 
        /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
-       o = (java_objectheader *) mainthreadobj;
+       o = (java_objectheader *) mainthreadobj->object;
 
        (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
                                                  false);
-#else
-#error IMPLEMENT ME!
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       /* set the thread */
+
+       mainthreadobj->object->vm_thread = (java_lang_Object *) mainthreadobj;
+
+       /* call public Thread(String name) */
+
+       o = (java_objectheader *) mainthreadobj->object;
+
+       (void) vm_call_method(method_thread_init, o, threadname);
 #endif
 
        if (*exceptionptr)
                return false;
 
-       mainthreadobj->o.group = threadgroup;
+#if defined(ENABLE_JAVASE)
+       mainthreadobj->object->group = threadgroup;
 
        /* add main thread to java.lang.ThreadGroup */
 
@@ -805,13 +856,15 @@ bool threads_init(void)
                                                                 true);
 
        o = (java_objectheader *) threadgroup;
-       t = (java_lang_Thread *) mainthreadobj;
+       t = mainthreadobj->object;
 
        (void) vm_call_method(m, o, t);
 
        if (*exceptionptr)
                return false;
 
+#endif
+
        threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
 
        /* initialize the thread attribute object */
@@ -1044,7 +1097,7 @@ static void *threads_startup_thread(void *t)
 
        /* set our priority */
 
-       threads_set_thread_priority(thread->tid, thread->o.priority);
+       threads_set_thread_priority(thread->tid, thread->object->priority);
 
 #if defined(ENABLE_INTRP)
        /* set interpreter stack */
@@ -1074,7 +1127,7 @@ static void *threads_startup_thread(void *t)
 
                c   = class_java_lang_VMThread;
 #elif defined(WITH_CLASSPATH_CLDC1_1)
-               c   = thread->o.header.vftbl->class;
+               c   = thread->object->header.vftbl->class;
 #endif
 
                m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
@@ -1095,11 +1148,11 @@ static void *threads_startup_thread(void *t)
 #if defined(WITH_CLASSPATH_GNU)
                /* we need to start the run method of java.lang.VMThread */
 
-               vmt = (java_lang_VMThread *) thread->o.vmThread;
+               vmt = (java_lang_VMThread *) thread->object->vmThread;
                o   = (java_objectheader *) vmt;
 
 #elif defined(WITH_CLASSPATH_CLDC1_1)
-               o   = (java_objectheader *) thread;
+               o   = (java_objectheader *) thread->object;
 #endif
 
                (void) vm_call_method(m, o);
@@ -1141,9 +1194,46 @@ static void *threads_startup_thread(void *t)
 }
 
 
+/* threads_start_javathread ***************************************************
+
+   Start a thread in the JVM. Only the java thread object exists so far.
+
+   IN:
+      object.....the java thread object java.lang.Thread
+
+******************************************************************************/
+
+void threads_start_javathread(java_lang_Thread *object)
+{
+       threadobject *thread;
+
+       /* create the vm internal threadobject */
+
+       thread = NEW(threadobject);
+       assert(thread);
+
+       /* link the two objects together */
+
+       thread->object = object;
+
+#if defined(WITH_CLASSPATH_GNU)
+       assert(object->vmThread);
+       assert(object->vmThread->vmdata == NULL);
+       object->vmThread->vmdata = (java_lang_Object *) thread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       object->vm_thread = (java_lang_Object *) thread;
+#endif
+
+       /* actually start the thread */
+       /* don't pass a function pointer (NULL) since we want Thread.run()V here */
+
+       threads_start_thread(thread, NULL);
+}
+
+
 /* threads_start_thread ********************************************************
 
-   Start a thread in the JVM.
+   Start a thread in the JVM. Both (vm internal and java) thread objects exist.
 
    IN:
       thread.......the thread object
@@ -1230,24 +1320,35 @@ void threads_set_thread_priority(pthread_t tid, int priority)
 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 {
        threadobject          *thread;
-       java_lang_VMThread    *vmt;
        utf                   *u;
        java_lang_String      *s;
-       java_lang_ThreadGroup *group;
-       methodinfo            *m;
        java_objectheader     *o;
        java_lang_Thread      *t;
 
-       /* create a java.lang.Thread object */
+#if defined(ENABLE_JAVASE)
+       java_lang_ThreadGroup *group;
+       methodinfo            *m;
+#endif
 
-       thread = (threadobject *) builtin_new(class_java_lang_Thread);
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread    *vmt;
+#endif
+
+       /* create a vm internal thread object */
+
+       thread = NEW(threadobject);
 
        if (thread == NULL)
                return false;
 
-       /* cast for convenience */
+       /* create a java.lang.Thread object */
+
+       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+
+       if (t == NULL)
+               return false;
 
-       t = (java_lang_Thread *) thread;
+       thread->object = t;
 
        threads_init_threadobject(thread);
        threads_set_current_threadobject(thread);
@@ -1266,10 +1367,13 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
        pthread_mutex_unlock(&threadlistlock);
 
-       /* mark main thread as Java thread */
+       /* mark thread as Java thread */
 
        thread->flags = THREAD_FLAG_JAVA;
 
+       if (isdaemon)
+               thread->flags |= THREAD_FLAG_DAEMON;
+
 #if defined(ENABLE_INTRP)
        /* create interpreter stack */
 
@@ -1290,33 +1394,42 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
        /* set the thread */
 
        vmt->thread = t;
+       vmt->vmdata = (java_lang_Object *) thread;
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       t->vm_thread = (java_lang_Object *) thread;
 #endif
 
        if (vm_aargs != NULL) {
                u     = utf_new_char(vm_aargs->name);
+#if defined(ENABLE_JAVASE)
                group = (java_lang_ThreadGroup *) vm_aargs->group;
+#endif
        }
        else {
                u     = utf_null;
-               group = mainthreadobj->o.group;
+#if defined(ENABLE_JAVASE)
+               group = mainthreadobj->object->group;
+#endif
        }
 
        s = javastring_new(u);
 
-       o = (java_objectheader *) thread;
+       o = (java_objectheader *) thread->object;
 
 #if defined(WITH_CLASSPATH_GNU)
        (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
                                                  isdaemon);
-#else
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       (void) vm_call_method(method_thread_init, o, s);
 #endif
 
        if (*exceptionptr)
                return false;
 
+#if defined(ENABLE_JAVASE)
        /* store the thread group in the object */
 
-       thread->o.group = group;
+       thread->object->group = group;
 
        /* add thread to given thread-group */
 
@@ -1332,6 +1445,7 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
        if (*exceptionptr)
                return false;
+#endif
 
        return true;
 }
@@ -1345,10 +1459,12 @@ bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
 bool threads_detach_thread(threadobject *thread)
 {
+#if defined(ENABLE_JAVASE)
        java_lang_ThreadGroup *group;
        methodinfo            *m;
        java_objectheader     *o;
        java_lang_Thread      *t;
+#endif
 
        /* Allow lock record pools to be used by other threads. They
           cannot be deleted so we'd better not waste them. */
@@ -1359,9 +1475,10 @@ bool threads_detach_thread(threadobject *thread)
 
        /* XXX implement uncaught exception stuff (like JamVM does) */
 
+#if defined(ENABLE_JAVASE)
        /* remove thread from the thread group */
 
-       group = thread->o.group;
+       group = thread->object->group;
 
        /* XXX TWISTI: should all threads be in a ThreadGroup? */
 
@@ -1376,13 +1493,14 @@ bool threads_detach_thread(threadobject *thread)
                        return false;
 
                o = (java_objectheader *) group;
-               t = (java_lang_Thread *) thread;
+               t = thread->object;
 
                (void) vm_call_method(m, o, t);
 
                if (*exceptionptr)
                        return false;
        }
+#endif
 
        /* remove thread from thread list and threads table, do this
           inside a lock */
@@ -1406,6 +1524,10 @@ bool threads_detach_thread(threadobject *thread)
 
        pthread_cond_broadcast(&(thread->joincond));
 
+       /* free the vm internal thread object */
+
+       FREE(thread, threadobject);
+
        return true;
 }
 
@@ -1423,7 +1545,7 @@ bool threads_detach_thread(threadobject *thread)
 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
 {
        while (thread != mainthreadobj) {
-               if (!thread->o.daemon)
+               if (!(thread->flags & THREAD_FLAG_DAEMON))
                        return thread;
 
                thread = thread->prev;
@@ -1743,7 +1865,7 @@ void threads_sleep(s8 millis, s4 nanos)
        wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
 
        if (wasinterrupted)
-               *exceptionptr = new_exception(string_java_lang_InterruptedException);
+               exceptions_throw_interruptedexception();
 }
 
 
@@ -1783,26 +1905,30 @@ void threads_dump(void)
        do {
                /* get thread object */
 
-               t = (java_lang_Thread *) thread;
+               t = thread->object;
 
                /* the thread may be currently in initalization, don't print it */
 
                if (t != NULL) {
                        /* get thread name */
 
+#if defined(ENABLE_JAVASE)
                        name = javastring_toutf(t->name, false);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+                       name = t->name;
+#endif
 
                        printf("\n\"");
                        utf_display_printable_ascii(name);
                        printf("\" ");
 
-                       if (t->daemon)
+                       if (thread->flags & THREAD_FLAG_DAEMON)
                                printf("daemon ");
 
 #if SIZEOF_VOID_P == 8
-                       printf("prio=%d tid=0x%016lx\n", t->priority, (long) thread->tid);
+                       printf("prio=%d tid=0x%016lx\n", t->priority, (ptrint) thread->tid);
 #else
-                       printf("prio=%d tid=0x%08lx\n", t->priority, (long) thread->tid);
+                       printf("prio=%d tid=0x%08lx\n", t->priority, (ptrint) thread->tid);
 #endif
 
                        /* dump trace of thread */