* Removed all Id tags.
[cacao.git] / src / threads / threads-common.c
index 97d7aadfad6b676590c586fe365ae8abf3096a0e..89515056c98594f327eee75f526386e795cb11c2 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: threads-common.c 7963 2007-05-24 10:21:16Z twisti $
-
 */
 
 
 #include "config.h"
 
 #include <assert.h>
+#include <stdint.h>
+#include <unistd.h>
 
 #include "vm/types.h"
 
 #include "mm/memory.h"
 
 #include "native/jni.h"
+#include "native/llni.h"
 
 #include "native/include/java_lang_Object.h"
 #include "native/include/java_lang_String.h"
@@ -75,6 +76,11 @@ static list_t *list_threads;
 /* global threads free-list */
 static list_t *list_threads_free;
 
+#if defined(__LINUX__)
+/* XXX Remove for exact-GC. */
+bool threads_pthreads_implementation_nptl;
+#endif
+
 
 /* threads_preinit *************************************************************
 
@@ -88,6 +94,42 @@ static list_t *list_threads_free;
 void threads_preinit(void)
 {
        threadobject *mainthread;
+#if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
+       char         *pathbuf;
+       size_t        len;
+#endif
+
+#if defined(__LINUX__)
+       /* XXX Remove for exact-GC. */
+
+       /* On Linux we need to check the pthread implementation. */
+
+       /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
+       /* If the glibc is a pre-2.3.2 version, we fall back to
+          linuxthreads. */
+
+# if defined(_CS_GNU_LIBPTHREAD_VERSION)
+       len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
+
+       /* Some systems return as length 0 (maybe cross-compilation
+          related).  In this case we also fall back to linuxthreads. */
+
+       if (len > 0) {
+               pathbuf = MNEW(char, len);
+
+               (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
+
+               if (strstr(pathbuf, "NPTL") != NULL)
+                       threads_pthreads_implementation_nptl = true;
+               else
+                       threads_pthreads_implementation_nptl = false;
+       }
+       else
+               threads_pthreads_implementation_nptl = false;
+# else
+       threads_pthreads_implementation_nptl = false;
+# endif
+#endif
 
        /* initialize the threads lists */
 
@@ -274,7 +316,8 @@ threadobject *threads_thread_new(void)
 
 void threads_thread_free(threadobject *t)
 {
-       s4 index;
+       int32_t  index;
+       uint32_t state;
 
        /* lock the threads-lists */
 
@@ -288,15 +331,19 @@ void threads_thread_free(threadobject *t)
 
        list_remove_unsynced(list_threads, t);
 
-       /* Clear memory, but keep the thread-index. */
+       /* Clear memory, but keep the thread-index and the
+          thread-state. */
+
        /* ATTENTION: Do this after list_remove, otherwise the linkage
           pointers are invalid. */
 
        index = t->index;
+       state = t->state;
 
        MZERO(t, threadobject, 1);
 
        t->index = index;
+       t->state = state;
 
        /* add the thread to the free list */
 
@@ -321,52 +368,73 @@ void threads_thread_free(threadobject *t)
 
 bool threads_thread_start_internal(utf *name, functionptr f)
 {
-       threadobject       *thread;
-       java_lang_Thread   *t;
+       threadobject       *t;
+       java_lang_Thread   *object;
 #if defined(WITH_CLASSPATH_GNU)
        java_lang_VMThread *vmt;
 #endif
 
+       /* Enter the join-mutex, so if the main-thread is currently
+          waiting to join all threads, the number of non-daemon threads
+          is correct. */
+
+       threads_mutex_join_lock();
+
        /* create internal thread data-structure */
 
-       thread = threads_thread_new();
+       t = threads_thread_new();
+
+       t->flags = THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+
+       /* The thread is flagged as (non-)daemon thread, we can leave the
+          mutex. */
+
+       threads_mutex_join_unlock();
 
        /* create the java thread object */
 
-       t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
+       object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
 
-       if (t == NULL)
+       /* XXX memory leak!!! */
+       if (object == NULL)
                return false;
 
 #if defined(WITH_CLASSPATH_GNU)
        vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
 
+       /* XXX memory leak!!! */
        if (vmt == NULL)
                return false;
 
-       vmt->thread = t;
-       vmt->vmdata = (java_lang_Object *) thread;
+       LLNI_field_set_ref(vmt, thread, object);
+       LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) t);
 
-       t->vmThread = vmt;
+       LLNI_field_set_ref(object, vmThread, vmt);
 #elif defined(WITH_CLASSPATH_CLDC1_1)
-       t->vm_thread = (java_lang_Object *) thread;
+       LLNI_field_set_val(object, vm_thread, (java_lang_Object *) t);
 #endif
 
-       thread->object = t;
-
-       thread->flags = THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+       t->object = object;
 
        /* set java.lang.Thread fields */
 
-       t->name     = (java_lang_String *) javastring_new(name);
+#if defined(WITH_CLASSPATH_GNU)
+       LLNI_field_set_ref(object, name    , (java_lang_String *) javastring_new(name));
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+       /* FIXME: In cldc the name is a char[] */
+/*     LLNI_field_set_ref(object, name    , (java_chararray *) javastring_new(name)); */
+       LLNI_field_set_ref(object, name    , NULL);
+#endif
+
 #if defined(ENABLE_JAVASE)
-       t->daemon   = true;
+       LLNI_field_set_val(object, daemon  , true);
 #endif
-       t->priority = NORM_PRIORITY;
+
+       LLNI_field_set_val(object, priority, NORM_PRIORITY);
 
        /* start the thread */
 
-       threads_impl_thread_start(thread, f);
+       threads_impl_thread_start(t, f);
 
        /* everything's ok */
 
@@ -387,14 +455,19 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 void threads_thread_start(java_lang_Thread *object)
 {
        threadobject *thread;
+#if defined(WITH_CLASSPATH_GNU)
+       java_lang_VMThread *vmt;
+#endif
 
-       /* create internal thread data-structure */
+       /* Enter the join-mutex, so if the main-thread is currently
+          waiting to join all threads, the number of non-daemon threads
+          is correct. */
 
-       thread = threads_thread_new();
+       threads_mutex_join_lock();
 
-       /* link the two objects together */
+       /* create internal thread data-structure */
 
-       thread->object = object;
+       thread = threads_thread_new();
 
        /* this is a normal Java thread */
 
@@ -403,17 +476,28 @@ void threads_thread_start(java_lang_Thread *object)
 #if defined(ENABLE_JAVASE)
        /* is this a daemon thread? */
 
-       if (object->daemon == true)
+       if (LLNI_field_direct(object, daemon) == true)
                thread->flags |= THREAD_FLAG_DAEMON;
 #endif
 
+       /* The thread is flagged and (non-)daemon thread, we can leave the
+          mutex. */
+
+       threads_mutex_join_unlock();
+
+       /* link the two objects together */
+
+       thread->object = object;
+
 #if defined(WITH_CLASSPATH_GNU)
-       assert(object->vmThread);
-       assert(object->vmThread->vmdata == NULL);
+       LLNI_field_get_ref(object, vmThread, vmt);
+
+       assert(vmt);
+       assert(LLNI_field_direct(vmt, vmdata) == NULL);
 
-       object->vmThread->vmdata = (java_lang_Object *) thread;
+       LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
 #elif defined(WITH_CLASSPATH_CLDC1_1)
-       object->vm_thread = (java_lang_Object *) thread;
+       LLNI_field_set_val(object, vm_thread, (java_lang_Object *) thread);
 #endif
 
        /* Start the thread.  Don't pass a function pointer (NULL) since
@@ -443,10 +527,14 @@ void threads_thread_print_info(threadobject *t)
        if (object != NULL) {
                /* get thread name */
 
-#if defined(ENABLE_JAVASE)
-               name = javastring_toutf((java_objectheader *) object->name, false);
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-               name = object->name;
+#if defined(WITH_CLASSPATH_GNU)
+               name = javastring_toutf((java_handle_t *) LLNI_field_direct(object, name), false);
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+               /* FIXME: In cldc the name is a char[] */
+/*             name = object->name; */
+               name = utf_null;
+#else
+# error unknown classpath configuration
 #endif
 
                printf("\"");
@@ -456,7 +544,7 @@ void threads_thread_print_info(threadobject *t)
                if (t->flags & THREAD_FLAG_DAEMON)
                        printf(" daemon");
 
-               printf(" prio=%d", object->priority);
+               printf(" prio=%d", LLNI_field_direct(object, priority));
 
 #if SIZEOF_VOID_P == 8
                printf(" t=0x%016lx tid=0x%016lx (%ld)",