#include "vm/types.h"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#if defined(ENABLE_GC_BOEHM)
/* We need to include Boehm's gc.h here for GC_register_my_thread and
# include "mm/boehm-gc/include/gc.h"
#endif
-#include "native/jni.h"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/method.hpp"
+#include "vm/options.h"
#include "vm/string.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vm/jit/stacktrace.hpp"
-
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/utf8.h"
-
+#include "vm/jit/stacktrace.hpp"
-// FIXME
-extern "C" {
/* global variables ***********************************************************/
static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
{
- java_handle_t *o;
- java_lang_Thread *to;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmto;
- classinfo *c;
- methodinfo *m;
- bool isdaemon;
-#endif
-
/* Create a java.lang.Thread Java object. */
- o = builtin_new(class_java_lang_Thread);
+ java_handle_t* h = builtin_new(class_java_lang_Thread);
- if (o == NULL)
+ if (h == NULL)
return false;
- to = (java_lang_Thread *) o;
+ java_lang_Thread jlt(h);
- /* Set the Java object in the thread data-structure. This
- indicates that the thread is attached to the VM. */
-
- thread_set_object(t, (java_handle_t *) to);
+ // Set the Java object in the thread data-structure. This
+ // indicates that the thread is attached to the VM.
+ thread_set_object(t, jlt.get_handle());
#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* Create a java.lang.VMThread Java object. */
-
- vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+ h = builtin_new(class_java_lang_VMThread);
- if (vmto == NULL)
+ if (h == NULL)
return false;
- /* Set the Java thread object in the Java VM-thread object. */
-
- LLNI_field_set_ref(vmto, thread, to);
-
- /* Set the thread data-structure in the Java VM-thread object. */
-
- LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
+ // Create and initialize a java.lang.VMThread object.
+ java_lang_VMThread jlvmt(h, jlt.get_handle(), t);
/* Call:
java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
- isdaemon = thread_is_daemon(t);
+ bool isdaemon = thread_is_daemon(t);
- (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
- isdaemon);
+ (void) vm_call_method(thread_method_init, jlt.get_handle(), jlvmt.get_handle(),
+ name, NORM_PRIORITY, isdaemon);
if (exceptions_get_exception())
return false;
- /* Set the threadgroup in the Java thread object. */
-
- LLNI_field_set_ref(to, group, (java_lang_ThreadGroup *) group);
+ // Set the ThreadGroup in the Java thread object.
+ jlt.set_group(group);
/* Add thread to the threadgroup. */
+ classinfo* c;
LLNI_class_get(group, c);
- m = class_resolveclassmethod(c,
- utf_addThread,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_addThread,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
if (m == NULL)
return false;
- (void) vm_call_method(m, group, to);
+ (void) vm_call_method(m, group, jlt.get_handle());
if (exceptions_get_exception())
return false;
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* OpenJDK's java.lang.Thread does not have a VMThread field in
- the class. Nothing to do here. */
-
/* Set the priority. java.lang.Thread.<init> requires it because
it sets the priority of the current thread to the parent's one
(which is the current thread in this case). */
+ jlt.set_priority(NORM_PRIORITY);
- LLNI_field_set_val(to, priority, NORM_PRIORITY);
-
- /* Call:
- java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
+ // Call: java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V
- (void) vm_call_method(thread_method_init, o, group, name);
+ (void) vm_call_method(thread_method_init, jlt.get_handle(), group, name);
if (exceptions_get_exception())
return false;
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- /* Set the thread data-structure in the Java thread object. */
+ // Set the thread data-structure in the Java thread object.
+ jlt.set_vm_thread(t);
- LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
-
- /* Call: public Thread(Ljava/lang/String;)V */
-
- (void) vm_call_method(thread_method_init, o, name);
+ // Call: public Thread(Ljava/lang/String;)V
+ (void) vm_call_method(thread_method_init, jlt.get_handle(), name);
if (exceptions_get_exception())
return false;
/* Get the main-thread (NOTE: The main thread is always the first
thread in the list). */
- t = threadlist_first();
+ t = ThreadList::get_main_thread();
/* The thread name. */
/* Lock the thread lists */
- threadlist_lock();
+ ThreadList::lock();
- index = threadlist_get_free_index();
+ index = ThreadList::get_free_thread_index();
/* Allocate a thread data structure. */
/* First, try to get one from the free-list. */
- t = threadlist_free_first();
+ t = ThreadList::get_free_thread();
if (t != NULL) {
- /* Remove from free list. */
-
- threadlist_free_remove(t);
-
/* Equivalent of MZERO on the else path */
threads_impl_thread_clear(t);
MZERO(t, threadobject, 1);
+ // Initialize the mutex and the condition.
+ t->flc_lock = new Mutex();
+ t->flc_cond = new Condition();
+
+ t->waitmutex = new Mutex();
+ t->waitcond = new Condition();
+
+ t->suspendmutex = new Mutex();
+ t->suspendcond = new Condition();
+
+#if defined(ENABLE_TLH)
+ tlh_init(&(t->tlh));
+#endif
+
#if defined(ENABLE_GC_CACAO)
/* Register reference to java.lang.Thread with the GC. */
/* FIXME is it ok to do this only once? */
gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
#endif
- /* Initialize the implementation-specific bits. */
-
- threads_impl_thread_init(t);
+ t->_dumpmemory = new DumpMemory();
}
/* Pre-compute the thinlock-word. */
assert(index != 0);
t->index = index;
- t->thinlock = lock_pre_compute_thinlock(t->index);
+ t->thinlock = Lockword::pre_compute_thinlock(t->index);
t->flags = 0;
t->state = THREAD_STATE_NEW;
/* Add the thread to the thread list. */
- threadlist_add(t);
+ ThreadList::add_to_active_thread_list(t);
/* Unlock the thread lists. */
- threadlist_unlock();
+ ThreadList::unlock();
return t;
}
void thread_free(threadobject *t)
{
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- /* Remove the thread from the thread-list. */
-
- threadlist_remove(t);
-
- /* Add the thread index to the free list. */
-
- threadlist_index_add(t->index);
-
/* Set the reference to the Java object to NULL. */
thread_set_object(t, NULL);
- /* Add the thread data structure to the free list. */
-
- threadlist_free_add(t);
-
- /* Unlock the thread lists. */
+ /* Release the thread. */
- threadlist_unlock();
+ ThreadList::release_thread(t);
}
void threads_thread_start(java_handle_t *object)
{
- java_lang_Thread *to;
- threadobject *t;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmto;
-#endif
-
- to = (java_lang_Thread *) object;
+ java_lang_Thread jlt(object);
/* Enter the join-mutex, so if the main-thread is currently
waiting to join all threads, the number of non-daemon threads
/* Create internal thread data-structure. */
- t = thread_new();
+ threadobject* t = thread_new();
/* this is a normal Java thread */
#if defined(ENABLE_JAVASE)
/* Is this a daemon thread? */
- if (LLNI_field_direct(to, daemon) == true)
+ if (jlt.get_daemon() == true)
t->flags |= THREAD_FLAG_DAEMON;
#endif
#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
/* Get the java.lang.VMThread object and do some sanity checks. */
+ java_lang_VMThread jlvmt(jlt.get_vmThread());
- LLNI_field_get_ref(to, vmThread, vmto);
+ assert(jlvmt.get_handle() != NULL);
+ assert(jlvmt.get_vmdata() == NULL);
- assert(vmto);
- assert(LLNI_field_direct(vmto, vmdata) == NULL);
-
- LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
+ jlvmt.set_vmdata(t);
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* Nothing to do. */
+ // Nothing to do.
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
+ jlt.set_vm_thread(t);
#else
# error unknown classpath configuration
void thread_fprint_name(threadobject *t, FILE *stream)
{
- java_lang_Thread *to;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_String *name;
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- java_chararray_t *name;
-#endif
-
- to = (java_lang_Thread *) thread_get_object(t);
-
- if (to == NULL)
+ if (thread_get_object(t) == NULL)
vm_abort("");
- LLNI_field_get_ref(to, name, name);
+ java_lang_Thread jlt(thread_get_object(t));
#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- javastring_fprint((java_handle_t *) name, stream);
+ java_handle_t* name = jlt.get_name();
+ javastring_fprint(name, stream);
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
/* FIXME: In OpenJDK and CLDC the name is a char[]. */
+ //java_chararray_t *name;
+
/* FIXME This prints to stdout. */
utf_display_printable_ascii(utf_null);
void thread_print_info(threadobject *t)
{
- java_lang_Thread *to;
- int state;
-
- /* If the thread is currently in initalization, don't print it. */
-
- to = (java_lang_Thread *) thread_get_object(t);
+ java_lang_Thread jlt(thread_get_object(t));
/* Print as much as we can when we are in state NEW. */
- if (to != NULL) {
+ if (jlt.get_handle() != NULL) {
/* Print thread name. */
printf("\"");
if (thread_is_daemon(t))
printf(" daemon");
- if (to != NULL) {
- printf(" prio=%d", LLNI_field_direct(to, priority));
+ if (jlt.get_handle() != NULL) {
+ printf(" prio=%d", jlt.get_priority());
}
#if SIZEOF_VOID_P == 8
/* Print thread state. */
- state = cacaothread_get_state(t);
+ int state = cacaothread_get_state(t);
switch (state) {
case THREAD_STATE_NEW:
case THREAD_STATE_TIMED_WAITING:
printf(" waiting on condition");
break;
+ case THREAD_STATE_PARKED:
+ printf(" parked");
+ break;
+ case THREAD_STATE_TIMED_PARKED:
+ printf(" timed parked");
+ break;
case THREAD_STATE_TERMINATED:
printf(" terminated");
break;
}
+/**
+ * Set the current state of the given thread. This method should only
+ * be called while holding the threadlist-lock and after checking that
+ * the new state is valid. It is best to not call this method directly
+ * but call the specific setter methods below.
+ */
+static inline void thread_set_state(threadobject *t, int state)
+{
+ // Set the state of our internal threadobject.
+ t->state = state;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ // Set the state of the java.lang.Thread object.
+ java_lang_Thread thread(thread_get_object(t));
+ assert(thread.is_non_null());
+ thread.set_threadStatus(state);
+#endif
+}
+
+
/* thread_set_state_runnable ***************************************************
Set the current state of the given thread to THREAD_STATE_RUNNABLE.
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_RUNNABLE;
+ thread_set_state(t, THREAD_STATE_RUNNABLE);
DEBUGTHREADS("is RUNNABLE", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_WAITING;
+ thread_set_state(t, THREAD_STATE_WAITING);
DEBUGTHREADS("is WAITING", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_TIMED_WAITING;
+ thread_set_state(t, THREAD_STATE_TIMED_WAITING);
DEBUGTHREADS("is TIMED_WAITING", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
+}
+
+
+/* thread_set_state_parked *****************************************************
+
+ Set the current state of the given thread to THREAD_STATE_PARKED.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_parked(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ ThreadList::lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ thread_set_state(t, THREAD_STATE_PARKED);
+
+ DEBUGTHREADS("is PARKED", t);
+ }
+
+ ThreadList::unlock();
+}
+
+
+/* thread_set_state_timed_parked ***********************************************
+
+ Set the current state of the given thread to THREAD_STATE_TIMED_PARKED.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_timed_parked(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ ThreadList::lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ thread_set_state(t, THREAD_STATE_TIMED_PARKED);
+
+ DEBUGTHREADS("is TIMED_PARKED", t);
+ }
+
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
- t->state = THREAD_STATE_TERMINATED;
+ thread_set_state(t, THREAD_STATE_TERMINATED);
DEBUGTHREADS("is TERMINATED", t);
- threadlist_unlock();
+ ThreadList::unlock();
}
threadobject *thread_get_thread(java_handle_t *h)
{
- threadobject *t;
#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmto;
- java_lang_Object *to;
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- bool equal;
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- vmto = (java_lang_VMThread *) h;
-
- LLNI_field_get_val(vmto, vmdata, to);
-
- t = (threadobject *) to;
+ java_lang_VMThread jlvmt(h);
+ threadobject* t = jlvmt.get_vmdata();
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
/* XXX This is just a quick hack. */
-
- threadlist_lock();
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- LLNI_equals(t->object, h, equal);
-
- if (equal == true)
- break;
- }
-
- threadlist_unlock();
+ threadobject* t = ThreadList::get_thread_from_java_object(h);
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- log_println("threads_get_thread: IMPLEMENT ME!");
+ log_println("thread_get_thread: IMPLEMENT ME!");
+ threadobject* t = NULL;
#else
# error unknown classpath configuration
case THREAD_STATE_BLOCKED:
case THREAD_STATE_WAITING:
case THREAD_STATE_TIMED_WAITING:
+ case THREAD_STATE_PARKED:
+ case THREAD_STATE_TIMED_PARKED:
return true;
default:
return false;
}
+/* thread_is_interrupted *******************************************************
-/* threads_dump ****************************************************************
+ Check if the given thread has been interrupted.
- Dumps info for all threads running in the JVM. This function is
- called when SIGQUIT (<ctrl>-\) is sent to CACAO.
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN VALUE:
+ true, if the given thread had been interrupted
*******************************************************************************/
-void threads_dump(void)
+bool thread_is_interrupted(threadobject *t)
{
- threadobject *t;
-
- /* XXX we should stop the world here */
+ /* We need the mutex because classpath will call this function when
+ a blocking system call is interrupted. The mutex ensures that it will
+ see the correct value for the interrupted flag. */
- /* Lock the thread lists. */
+ t->waitmutex->lock();
+ bool interrupted = t->interrupted;
+ t->waitmutex->unlock();
- threadlist_lock();
-
- printf("Full thread dump CACAO "VERSION":\n");
-
- /* iterate over all started threads */
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- /* ignore threads which are in state NEW */
- if (t->state == THREAD_STATE_NEW)
- continue;
-
-#if defined(ENABLE_GC_CACAO)
- /* Suspend the thread. */
- /* XXX Is the suspend reason correct? */
-
- if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
- vm_abort("threads_dump: threads_suspend_thread failed");
-#endif
-
- /* Print thread info. */
-
- printf("\n");
- thread_print_info(t);
- printf("\n");
+ return interrupted;
+}
- /* Print trace of thread. */
- stacktrace_print_of_thread(t);
+/* thread_set_interrupted ******************************************************
-#if defined(ENABLE_GC_CACAO)
- /* Resume the thread. */
+ Set the interrupted flag to the given value.
- if (threads_resume_thread(t) == false)
- vm_abort("threads_dump: threads_resume_thread failed");
-#endif
- }
+ ARGUMENTS:
+ interrupted ... value to set
- /* Unlock the thread lists. */
+*******************************************************************************/
- threadlist_unlock();
+void thread_set_interrupted(threadobject *t, bool interrupted)
+{
+ t->waitmutex->lock();
+ t->interrupted = interrupted;
+ t->waitmutex->unlock();
}
-} // extern "C"
/*