/* 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
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);
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;
/* 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);
threadname = javastring_new(utf_new_char("main"));
+#if defined(ENABLE_JAVASE)
/* allocate and init ThreadGroup */
threadgroup = (java_lang_ThreadGroup *)
if (threadgroup == NULL)
throw_exception_exit();
+#endif
#if defined(WITH_CLASSPATH_GNU)
/* create a java.lang.VMThread for the main thread */
/* 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 */
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 */
/* 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 */
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);
#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);
}
+/* 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
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);
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 */
/* 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 */
if (*exceptionptr)
return false;
+#endif
return true;
}
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. */
/* 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? */
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 */
pthread_cond_broadcast(&(thread->joincond));
+ /* free the vm internal thread object */
+
+ FREE(thread, threadobject);
+
return true;
}
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;
wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
if (wasinterrupted)
- *exceptionptr = new_exception(string_java_lang_InterruptedException);
+ exceptions_throw_interruptedexception();
}
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 */