The following natives are implemented:
java/lang/VMThread.isInterrupted()
java/lang/VMThread.interrupted()
java/lang/VMThread.interrupt()

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 Makefile                        |    1 +
 include/vm/preload.h            |    1 +
 include/vm/thread.h             |    7 ++++
 regression/jvm/MonitorTest.java |   65 +++++++++++++++++++++++++++++++++++++++
 test/vm/preload-stub.c          |    1 +
 vm/jato.c                       |   24 ++++++++++++++
 vm/monitor.c                    |   18 +++++++++--
 vm/preload.c                    |    2 +
 vm/thread.c                     |   47 ++++++++++++++++++++++++++++
 9 files changed, 163 insertions(+), 3 deletions(-)
 create mode 100644 regression/jvm/MonitorTest.java

diff --git a/Makefile b/Makefile
index 6dcd736..93088c9 100644
--- a/Makefile
+++ b/Makefile
@@ -293,6 +293,7 @@ REGRESSION_TEST_SUITE_CLASSES = \
        regression/jvm/LongArithmeticTest.java \
        regression/jvm/MethodInvocationAndReturnTest.java \
        regression/jvm/MethodInvocationExceptionsTest.java \
+       regression/jvm/MonitorTest.java \
        regression/jvm/MultithreadingTest.java \
        regression/jvm/ObjectArrayTest.java \
        regression/jvm/ObjectCreationAndManipulationExceptionsTest.java \
diff --git a/include/vm/preload.h b/include/vm/preload.h
index b65b938..c71d8f9 100644
--- a/include/vm/preload.h
+++ b/include/vm/preload.h
@@ -49,6 +49,7 @@ extern struct vm_class *vm_java_lang_Short;
 extern struct vm_class *vm_java_lang_IllegalArgumentException;
 extern struct vm_class *vm_java_lang_ClassLoader;
 extern struct vm_class *vm_java_lang_Number;
+extern struct vm_class *vm_java_lang_InterruptedException;
 extern struct vm_class *vm_boolean_class;
 extern struct vm_class *vm_char_class;
 extern struct vm_class *vm_float_class;
diff --git a/include/vm/thread.h b/include/vm/thread.h
index afb5ede..f6e6551 100644
--- a/include/vm/thread.h
+++ b/include/vm/thread.h
@@ -3,6 +3,8 @@
 
 #include "lib/list.h"
 
+#include "vm/object.h"
+
 #include <stdio.h> /* for NOT_IMPLEMENTED */
 #include <pthread.h>
 
@@ -26,6 +28,8 @@ struct vm_thread {
        pthread_t posix_id;
        enum vm_thread_state state;
        struct list_head list_node;
+       bool interrupted;
+       struct vm_monitor *wait_mon;
 };
 
 struct vm_exec_env {
@@ -52,5 +56,8 @@ void vm_thread_wait_for_non_daemons(void);
 void vm_thread_set_state(struct vm_thread *thread, enum vm_thread_state state);
 struct vm_object *vm_thread_get_java_thread(struct vm_thread *thread);
 char *vm_thread_get_name(struct vm_thread *thread);
+bool vm_thread_is_interrupted(struct vm_thread *thread);
+bool vm_thread_interrupted(struct vm_thread *thread);
+void vm_thread_interrupt(struct vm_thread *thread);
 
 #endif
diff --git a/regression/jvm/MonitorTest.java b/regression/jvm/MonitorTest.java
new file mode 100644
index 0000000..61ad5ef
--- /dev/null
+++ b/regression/jvm/MonitorTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 Tomasz Grabiec
+ *
+ * This file is released under the GPL version 2 with the following
+ * clarification and special exception:
+ *
+ *     Linking this library statically or dynamically with other modules is
+ *     making a combined work based on this library. Thus, the terms and
+ *     conditions of the GNU General Public License cover the whole
+ *     combination.
+ *
+ *     As a special exception, the copyright holders of this library give you
+ *     permission to link this library with independent modules to produce an
+ *     executable, regardless of the license terms of these independent
+ *     modules, and to copy and distribute the resulting executable under terms
+ *     of your choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module. An
+ *     independent module is a module which is not derived from or based on
+ *     this library. If you modify this library, you may extend this exception
+ *     to your version of the library, but you are not obligated to do so. If
+ *     you do not wish to do so, delete this exception statement from your
+ *     version.
+ *
+ * Please refer to the file LICENSE for details.
+ */
+package jvm;
+
+/**
+ * @author Tomasz Grabiec
+ */
+public class MonitorTest extends TestCase {
+    public static void testInterruptedWait() {
+        Thread t = new Thread() {
+                public void run() {
+                    boolean caught = false;
+
+                    synchronized (this) {
+                        notify();
+                        try {
+                            wait();
+                        } catch (InterruptedException e) {
+                            caught = true;
+                        }
+
+                        assertTrue(caught);
+                    }
+                }
+            };
+
+        try {
+            synchronized (t) {
+                t.start();
+                t.wait();
+                t.interrupt();
+            }
+
+            t.join();
+        } catch (InterruptedException e) {
+        }
+    }
+
+    public static void main(String [] args) {
+        testInterruptedWait();
+    }
+}
diff --git a/test/vm/preload-stub.c b/test/vm/preload-stub.c
index e7d3046..ca3e77f 100644
--- a/test/vm/preload-stub.c
+++ b/test/vm/preload-stub.c
@@ -53,6 +53,7 @@ struct vm_class *vm_java_lang_ThreadGroup;
 struct vm_class *vm_java_lang_VMThread;
 struct vm_class *vm_java_lang_IllegalMonitorStateException;
 struct vm_class *vm_java_lang_OutOfMemoryError;
+struct vm_class *vm_java_lang_InterruptedException;
 
 struct vm_method *vm_java_lang_Throwable_initCause;
 struct vm_method *vm_java_lang_Throwable_getCause;
diff --git a/vm/jato.c b/vm/jato.c
index 5d0b815..19f6425 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -727,6 +727,27 @@ static void native_vmthread_start(struct vm_object 
*vmthread, jlong stacksize)
        vm_thread_start(vmthread);
 }
 
+static jboolean native_vmthread_interrupted(void)
+{
+       return vm_thread_interrupted(vm_thread_self());
+}
+
+static jboolean native_vmthread_isinterrupted(struct vm_object *vmthread)
+{
+       struct vm_thread *thread;
+
+       thread = (struct vm_thread *)field_get_object(vmthread, 
vm_java_lang_VMThread_vmdata);
+       return vm_thread_is_interrupted(thread);
+}
+
+static void native_vmthread_interrupt(struct vm_object *vmthread)
+{
+       struct vm_thread *thread;
+
+       thread = (struct vm_thread *)field_get_object(vmthread, 
vm_java_lang_VMThread_vmdata);
+       vm_thread_interrupt(thread);
+}
+
 static void native_vmobject_notify(struct vm_object *obj)
 {
        vm_monitor_notify(&obj->monitor);
@@ -866,6 +887,9 @@ static struct vm_native natives[] = {
        DEFINE_NATIVE("java/lang/VMSystem", "nanoTime", 
&native_vmsystem_nano_time),
        DEFINE_NATIVE("java/lang/VMThread", "currentThread", 
&native_vmthread_current_thread),
        DEFINE_NATIVE("java/lang/VMThread", "start", &native_vmthread_start),
+       DEFINE_NATIVE("java/lang/VMThread", "isInterrupted", 
&native_vmthread_isinterrupted),
+       DEFINE_NATIVE("java/lang/VMThread", "interrupted", 
&native_vmthread_interrupted),
+       DEFINE_NATIVE("java/lang/VMThread", "interrupt", 
&native_vmthread_interrupt),
        DEFINE_NATIVE("java/lang/VMThrowable", "fillInStackTrace", 
&native_vmthrowable_fill_in_stack_trace),
        DEFINE_NATIVE("java/lang/VMThrowable", "getStackTrace", 
&native_vmthrowable_get_stack_trace),
        DEFINE_NATIVE("java/lang/reflect/Constructor", "getParameterTypes", 
&native_constructor_get_parameter_types),
diff --git a/vm/monitor.c b/vm/monitor.c
index 5705954..bf2b39d 100644
--- a/vm/monitor.c
+++ b/vm/monitor.c
@@ -145,6 +145,7 @@ static int vm_monitor_do_wait(struct vm_monitor *mon, 
struct timespec *timespec)
 {
        struct vm_thread *self;
        int old_lock_count;
+       bool interrupted;
        int err;
 
        if (vm_monitor_get_owner(mon) != vm_thread_self()) {
@@ -165,21 +166,32 @@ static int vm_monitor_do_wait(struct vm_monitor *mon, 
struct timespec *timespec)
        else
                self->state = VM_THREAD_STATE_WAITING;
 
+       self->wait_mon = mon;
+       interrupted = self->interrupted;
        pthread_mutex_unlock(&self->mutex);
 
-       if (timespec) {
+       if (interrupted)
+               err = 0;
+       else if (timespec) {
                err = pthread_cond_timedwait(&mon->cond, &mon->mutex, timespec);
                if (err == ETIMEDOUT)
                        err = 0;
        } else
                err = pthread_cond_wait(&mon->cond, &mon->mutex);
 
-       vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE);
+       pthread_mutex_lock(&self->mutex);
+       self->state = VM_THREAD_STATE_RUNNABLE;
+       self->wait_mon = NULL;
+       pthread_mutex_unlock(&self->mutex);
 
        vm_monitor_set_owner(mon, self);
        mon->lock_count = old_lock_count;
 
-       /* TODO: check if thread has been interrupted. */
+       if (vm_thread_interrupted(self)) {
+               signal_new_exception(vm_java_lang_InterruptedException, NULL);
+               return -1;
+       }
+
        return err;
 }
 
diff --git a/vm/preload.c b/vm/preload.c
index 0072acc..b2804da 100644
--- a/vm/preload.c
+++ b/vm/preload.c
@@ -90,6 +90,7 @@ struct vm_class *vm_java_lang_Long;
 struct vm_class *vm_java_lang_Short;
 struct vm_class *vm_java_lang_VMString;
 struct vm_class *vm_java_lang_Number;
+struct vm_class *vm_java_lang_InterruptedException;
 struct vm_class *vm_boolean_class;
 struct vm_class *vm_char_class;
 struct vm_class *vm_float_class;
@@ -140,6 +141,7 @@ static const struct preload_entry preload_entries[] = {
        { "[java/lang/reflect/Field", &vm_array_of_java_lang_reflect_Field },
        { "[java/lang/reflect/Method", &vm_array_of_java_lang_reflect_Method },
        { "java/lang/IllegalArgumentException", 
&vm_java_lang_IllegalArgumentException },
+       { "java/lang/InterruptedException", &vm_java_lang_InterruptedException 
},
        { "java/lang/Boolean", &vm_java_lang_Boolean },
        { "java/lang/Byte", &vm_java_lang_Byte },
        { "java/lang/Character", &vm_java_lang_Character },
diff --git a/vm/thread.c b/vm/thread.c
index 64052ca..83a4f4d 100644
--- a/vm/thread.c
+++ b/vm/thread.c
@@ -78,6 +78,8 @@ static struct vm_thread *vm_thread_alloc(void)
        thread->state = VM_THREAD_STATE_NEW;
        thread->vmthread = NULL;
        thread->posix_id = -1;
+       thread->interrupted = false;
+       thread->wait_mon = NULL;
 
        return thread;
 }
@@ -312,3 +314,48 @@ char *vm_thread_get_name(struct vm_thread *thread)
 
        return vm_string_to_cstr(name);
 }
+
+bool vm_thread_is_interrupted(struct vm_thread *thread)
+{
+       bool status;
+
+       pthread_mutex_lock(&thread->mutex);
+       status = thread->interrupted;
+       pthread_mutex_unlock(&thread->mutex);
+       return status;
+}
+
+bool vm_thread_interrupted(struct vm_thread *thread)
+{
+       bool status;
+
+       pthread_mutex_lock(&thread->mutex);
+       status = thread->interrupted;
+       thread->interrupted = false;
+       pthread_mutex_unlock(&thread->mutex);
+       return status;
+}
+
+void vm_thread_interrupt(struct vm_thread *thread)
+{
+       struct vm_monitor *mon;
+
+       pthread_mutex_lock(&thread->mutex);
+       thread->interrupted = true;
+       mon = thread->wait_mon;
+       pthread_mutex_unlock(&thread->mutex);
+
+       if (!mon)
+               return;
+
+       /*
+        * We should wait until thread actually enters a conditional
+        * wait so that the signal will not be lost. This can
+        * spuriously wake threads after @thread has left the wait()
+        * operation but it is fine with the JVM spec.
+        */
+       while (pthread_mutex_trylock(&mon->mutex))
+               sched_yield();
+       pthread_cond_broadcast(&mon->cond);
+       pthread_mutex_unlock(&mon->mutex);
+}
-- 
1.6.0.4


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to