|
From: <ls...@us...> - 2008-10-12 20:00:56
|
Revision: 4626
http://jnode.svn.sourceforge.net/jnode/?rev=4626&view=rev
Author: lsantha
Date: 2008-10-12 20:00:40 +0000 (Sun, 12 Oct 2008)
Log Message:
-----------
Prorgess with isolates: clarification of exit reason, initial system exit support, child isolates.
Modified Paths:
--------------
trunk/core/src/classpath/ext/javax/isolate/Isolate.java
trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java
trunk/core/src/classpath/vm/java/lang/VMRuntime.java
trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java
trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java
trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java
trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java
Modified: trunk/core/src/classpath/ext/javax/isolate/Isolate.java
===================================================================
--- trunk/core/src/classpath/ext/javax/isolate/Isolate.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/classpath/ext/javax/isolate/Isolate.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -21,24 +21,25 @@
package javax.isolate;
+import gnu.java.security.action.GetPropertiesAction;
+import java.security.AccessController;
import java.util.Properties;
-import java.security.AccessController;
-
import org.jnode.vm.isolate.VmIsolate;
-import gnu.java.security.action.GetPropertiesAction;
/**
* @author Ewout Prangsma (ep...@us...)
*/
public final class Isolate {
- /** The actual isolate implementation */
+ /**
+ * The actual isolate implementation
+ */
private final VmIsolate impl;
//todo hide this constructor
/**
* Constructor for the root isolate.
- *
+ *
* @param impl the JNode speciffic isolate implementation
*/
public Isolate(VmIsolate impl) {
@@ -47,7 +48,7 @@
/**
* Initialize this instance.
- *
+ *
* @param mainClass
* @param args
*/
@@ -57,7 +58,7 @@
/**
* Initialize this instance.
- *
+ *
* @param mainClass
* @param args
* @param properties
@@ -80,7 +81,7 @@
/**
* Gets the isolate that is running the current thread.
- *
+ *
* @return
*/
public static Isolate currentIsolate() {
@@ -89,7 +90,7 @@
/**
* If this object equal to the given object.
- *
+ *
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object other) {
@@ -98,7 +99,7 @@
/**
* Request normal termination of this isolate.
- *
+ *
* @param status
*/
public void exit(int status) {
@@ -107,17 +108,17 @@
/**
* Force termination of this isolate.
- *
+ *
* @param status
*/
public void halt(int status) {
- impl.halt(this, status);
+ impl.halt(status);
}
/**
* Gets a new Link associated with this Isolate from which the current
* isolate can receive status link messages.
- *
+ *
* @return
* @throws ClosedLinkException
*/
@@ -127,7 +128,7 @@
/**
* Start this isolate.
- *
+ *
* @param links
* @throws IsolateStartupException
*/
@@ -141,43 +142,46 @@
* terminated. New isolates may have been constructed or existing ones terminated by the time method returns.
*
* @return the active Isolate objects present at the time of the call
- *
* @throws SecurityException if a security manager is present and permission to query isolates is denied
*/
public static Isolate[] getIsolates() {
- //todo implement it
- throw new UnsupportedOperationException();
+ VmIsolate[] children = currentIsolate().impl.getChildren();
+ int c_nr = children.length;
+ Isolate[] ret = new Isolate[c_nr];
+ for (int i = 0; i < c_nr; i++)
+ ret[i] = children[i].getIsolate();
+
+ return ret;
}
/**
* Returns the name of the main class of this isolate.
- *
+ *
* @return the name of the main class of this isolate
*/
public String getMainClassName() {
- return impl.getMainClassName();
+ return impl.getMainClassName();
}
/**
* Returns the current state of the isolate.
*
* @return the current state of an isolate
- *
* @throws IllegalStateException if called before the isolate is started
- * @throws SecurityException if a security manager is present and permission to query isolates is denied
+ * @throws SecurityException if a security manager is present and permission to query isolates is denied
*/
- public IsolateStatus.State getState() {
+ public IsolateStatus.State getState() {
return impl.getIsolateState();
}
-
+
/**
* Retrieves a copy of the Link array passed to start() by the current
* isolate's creator. Modification of this array will have no effect on
* subsequent invocation of this method.
- *
+ * <p/>
* This method never returns null: it will return a zero-length array if
* this isolate's creator passed null to start().
- *
+ *
* @return
*/
public static Link[] getLinks() {
@@ -187,7 +191,7 @@
//todo hide this method
/**
* Gets the implementation instance.
- *
+ *
* @return
*/
final VmIsolate getImpl() {
Modified: trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java
===================================================================
--- trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -18,49 +18,75 @@
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
+
package javax.isolate;
+import org.jnode.vm.annotation.SharedStatics;
+
/**
+ * Represents isolate status, capturing such information as isolate state, exit code, and exit reason.
+ * State transitions in the isolate life cycle generate LinkMessages containing instances of this class
+ * which are sent over status links (but can be then forwarded over any link). If the isolate state is EXITED,
+ * the corresponding exit code and exit reason are contained in IsolateStatus.
+ *
* @author Ewout Prangsma (ep...@us...)
+ * @author Levente S\u00e1ntha
*/
public class IsolateStatus {
/**
* Defines the state of an Isolate.
- *
+ *
* @author Ewout Prangsma (ep...@us...)
*/
+ @SharedStatics
public static enum State {
- /** Isolate is starting */
+ /**
+ * Isolate is starting
+ */
STARTING,
- /** Isolate is started */
+ /**
+ * Isolate is started
+ */
STARTED,
- /** Isolate is exiting */
+ /**
+ * Isolate is exiting
+ */
EXITING,
- /** Isolate has exited */
+ /**
+ * Isolate has exited
+ */
EXITED,
- /** State is not known */
- UNKNOWN;
+ /**
+ * State is not known
+ */
+ UNKNOWN
}
/**
* Provides the reason for the termination of an isolate.
- *
+ *
* @author Ewout Prangsma (ep...@us...)
*/
+ @SharedStatics
public static enum ExitReason {
- /** The last non-deamon thread exited */
+ /**
+ * The last non-deamon thread exited
+ */
IMPLICIT_EXIT,
- /** Another isolate invoked Isolate.exit */
+ /**
+ * Another isolate invoked Isolate.exit
+ */
OTHER_EXIT,
- /** Another isolate invoed Isolated.halt */
+ /**
+ * Another isolate invoed Isolated.halt
+ */
OTHER_HALT,
/**
@@ -74,55 +100,91 @@
*/
SELF_HALT,
- /** The last non-deamon thread exited due to an uncaught exception */
- UNCAUGHT_EXCEPTION;
+ /**
+ * The last non-deamon thread exited due to an uncaught exception
+ */
+ UNCAUGHT_EXCEPTION
}
-
+
private final ExitReason exitReason;
private final State state;
private final int exitCode;
-
+
/**
* Initialize this instance.
+ *
* @param state
* @param exitReason
* @param exitCode
*/
protected IsolateStatus(State state, ExitReason exitReason, int exitCode) {
+ if (state == null)
+ throw new IllegalArgumentException();
+
+ if (state.equals(State.EXITED) && exitReason == null)
+ throw new IllegalArgumentException();
+
this.state = state;
this.exitReason = exitReason;
this.exitCode = exitCode;
}
-
+
/**
- * Are this and the given object equal.
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object other) {
- return super.equals(other);
- }
-
- /**
* Gets the exit reason.
+ *
* @return
*/
public ExitReason getExitReason() {
return exitReason;
}
-
+
/**
* Gets the exit code.
+ *
* @return
*/
public int getExitCode() {
return exitCode;
}
-
+
/**
* Gets the state of the isolate.
+ *
* @return
*/
public State getState() {
return state;
}
+
+ /**
+ * @param o
+ * @return
+ */
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof IsolateStatus)) return false;
+
+ IsolateStatus that = (IsolateStatus) o;
+
+ if (!state.equals(that.state)) return false;
+
+ if (state.equals(State.EXITED)) {
+ if (exitCode != that.exitCode) return false;
+ if (exitReason != that.exitReason) return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @return
+ */
+ public int hashCode() {
+ int result = state.hashCode();
+ if (state.equals(State.EXITED)) {
+ result = 31 * result + exitReason.hashCode();
+ result = 31 * result + exitCode;
+ }
+ return result;
+ }
}
Modified: trunk/core/src/classpath/vm/java/lang/VMRuntime.java
===================================================================
--- trunk/core/src/classpath/vm/java/lang/VMRuntime.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/classpath/vm/java/lang/VMRuntime.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -28,6 +28,8 @@
import org.jnode.vm.VmProcess;
import org.jnode.vm.VmSystem;
import org.jnode.vm.VmExit;
+import org.jnode.vm.isolate.VmIsolate;
+import javax.isolate.Isolate;
/**
* VMRuntime represents the interface to the Virtual Machine.
@@ -153,7 +155,11 @@
* @param status the status to end the process with
*/
static void exit(int status) {
- throw new VmExit(status);
+ if(VmIsolate.getRoot() == VmIsolate.currentIsolate()){
+ throw new VmExit(status);
+ } else {
+ VmIsolate.currentIsolate().systemExit(Isolate.currentIsolate(), status);
+ }
}
/**
Modified: trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java
===================================================================
--- trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -9,10 +9,15 @@
* @author Levente S\u00e1ntha
*/
public class IsolateStatusImpl extends IsolateStatus implements Cloneable {
- public IsolateStatusImpl(State state, ExitReason exitReason, int exitCode) {
- super(state, exitReason, exitCode);
+
+ public IsolateStatusImpl(State state) {
+ super(state, null, 0);
}
+ public IsolateStatusImpl(ExitReason exitReason, int exitCode) {
+ super(State.EXITED, exitReason, exitCode);
+ }
+
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
@@ -30,7 +35,7 @@
public String toString() {
State s = getState();
if (s.equals(State.EXITED)) {
- return getState() + "(" + getExitReason() + "," + getExitCode();
+ return getState() + "(" + getExitReason() + "," + getExitCode() + ")";
} else {
return getState().toString();
}
Modified: trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java
===================================================================
--- trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -153,6 +153,8 @@
*/
private BootableHashMap<VmIsolateLocal<?>, ?> isolateLocalMap = new BootableHashMap<VmIsolateLocal<?>, Object>();
+ private List<VmIsolate> children = new LinkedList<VmIsolate>();
+
/**
* Isolate states.
*
@@ -369,23 +371,49 @@
return isolate;
}
+ public final void exit(Isolate isolate, int status) {
+ exit0(isolate, status);
+ }
+
+ public final void systemExit(Isolate isolate, int status) {
+ //only this isolate may call this method
+ testIsolate(isolate);
+
+ this.exitReason = IsolateStatus.ExitReason.SELF_EXIT;
+ this.exitCode = status;
+
+ int ac = threadGroup.activeCount();
+ if (ac > 0) {
+ Thread[] ta = new Thread[ac];
+ int rc = threadGroup.enumerate(ta);
+ Thread current = Thread.currentThread();
+ boolean found = false;
+ for (int i = 0; i < rc; i++) {
+ Thread thread = ta[i];
+ if (current != thread) {
+ thread.getVmThread().stopForced(null);
+ } else {
+ found = true;
+ }
+ }
+ if (found) {
+ current.getVmThread().stop(null);
+ }
+ }
+ }
+
/**
* Request normal termination of this isolate.
*
* @param status
*/
- public final void exit(Isolate isolate, int status) {
- testIsolate(isolate);
+ public final void exit0(Isolate isolate, int status) {
+ //testIsolate(isolate);
//todo handle demon threads
if (threadGroup.activeCount() > 0 || threadGroup.activeGroupCount() > 0)
return;
changeState(State.EXITING);
- try {
- threadGroup.destroy();
- } catch (Throwable t) {
- t.printStackTrace();
- }
this.exitCode = status;
if (currentIsolate() == this) {
@@ -395,18 +423,60 @@
this.exitReason = IsolateStatus.ExitReason.OTHER_EXIT;
}
- changeState(State.EXITED);
- StaticData.isolates.remove(this);
+ doExit();
}
/**
+ * Request normal termination of this isolate.
+ *
+ * @param status
+ */
+ public final void implicitExit(int status) {
+ //on this isolate may call this method
+ testIsolate(currentIsolate().isolate);
+
+ //todo handle demon threads
+ if (threadGroup.activeCount() > 0 || threadGroup.activeGroupCount() > 0)
+ return;
+
+ changeState(State.EXITING);
+
+ if (exitReason == null) {
+ exitReason = IsolateStatus.ExitReason.IMPLICIT_EXIT;
+ this.exitCode = status;
+ }
+
+ doExit();
+ }
+
+ /**
+ * Request normal termination of this isolate.
+ *
+ * @param status
+ */
+ public final void uncaughtExceptionExit() {
+ //on this isolate may call this method
+ testIsolate(currentIsolate().isolate);
+
+ //todo handle demon threads
+ if (threadGroup.activeCount() > 0 || threadGroup.activeGroupCount() > 0)
+ return;
+
+ changeState(State.EXITING);
+
+ exitReason = IsolateStatus.ExitReason.UNCAUGHT_EXCEPTION;
+ this.exitCode = -1;
+
+ doExit();
+ }
+
+ /**
* Force termination of this isolate.
*
* @param status
*/
@SuppressWarnings("deprecation")
- public final void halt(Isolate isolate, int status) {
- testIsolate(isolate);
+ public final void halt(int status) {
changeState(State.EXITING);
switch (state) {
case EXITING:
@@ -414,19 +484,28 @@
break;
}
+ if (currentIsolate() == this) {
+ this.exitReason = IsolateStatus.ExitReason.SELF_HALT;
+ } else {
+ this.exitReason = IsolateStatus.ExitReason.OTHER_HALT;
+ }
+
+ this.exitCode = status;
+
+ doExit();
+ }
+
+ private void doExit() {
try {
threadGroup.destroy();
} catch (Throwable t) {
t.printStackTrace();
}
- this.exitCode = status;
- if (currentIsolate() == this) {
- this.exitReason = IsolateStatus.ExitReason.SELF_HALT;
- } else {
- this.exitReason = IsolateStatus.ExitReason.OTHER_HALT;
- }
+
+ this.creator.removeChild(this);
+ StaticData.isolates.remove(this);
+
changeState(State.EXITED);
- StaticData.isolates.remove(this);
}
/**
@@ -677,6 +756,8 @@
// Update the state of this isolate.
changeState(State.STARTED);
+ //add to parent
+ this.creator.addChild(this);
// Run main method.
mainMethod.invoke(null, new Object[]{args});
@@ -842,10 +923,21 @@
private void sendStatus(VmLink link, IsolateStatus.State state) {
if (state.equals(IsolateStatus.State.EXITED)) {
- org.jnode.vm.Unsafe.debugStackTrace();
- link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(state, exitReason, exitCode)));
+ link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(exitReason, exitCode)));
} else {
- link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(state, null, -1)));
+ link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(state)));
}
}
+
+ private synchronized void addChild(VmIsolate child) {
+ this.children.add(child);
+ }
+
+ private synchronized void removeChild(VmIsolate child) {
+ this.children.remove(child);
+ }
+
+ public synchronized VmIsolate[] getChildren() {
+ return this.children.toArray(new VmIsolate[children.size()]);
+ }
}
Modified: trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java
===================================================================
--- trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -32,6 +32,7 @@
import org.jnode.vm.VmStackReader;
import org.jnode.vm.VmSystem;
import org.jnode.vm.VmSystemObject;
+import org.jnode.vm.isolate.VmIsolate;
import org.jnode.vm.annotation.Inline;
import org.jnode.vm.annotation.Internal;
import org.jnode.vm.annotation.KernelSpace;
@@ -47,7 +48,6 @@
import org.jnode.vm.memmgr.VmHeapManager;
import org.vmmagic.pragma.UninterruptiblePragma;
import org.vmmagic.unboxed.Address;
-import javax.isolate.Isolate;
/**
* VM thread implementation
@@ -390,7 +390,10 @@
if (javaThread != null) {
javaThread.onExit();
//exit the current isolate if needed
- Isolate.currentIsolate().exit(0);
+ if (ex instanceof ThreadDeath)
+ VmIsolate.currentIsolate().implicitExit(0);
+ else
+ VmIsolate.currentIsolate().uncaughtExceptionExit();
// Notify joining threads
synchronized (javaThread) {
javaThread.notifyAll();
@@ -407,6 +410,26 @@
* @param ex
* @throws UninterruptiblePragma
*/
+ public final void stopForced(Throwable ex) throws UninterruptiblePragma {
+ this.stopping = true;
+ if (javaThread != null) {
+ javaThread.onExit();
+ // Notify joining threads
+ synchronized (javaThread) {
+ javaThread.notifyAll();
+ }
+ }
+
+ // Do the low level stop uninterrupted
+ doStop();
+ }
+
+ /**
+ * Stop the thread permanently.
+ *
+ * @param ex
+ * @throws UninterruptiblePragma
+ */
@Uninterruptible
private final void doStop() {
final VmProcessor proc = VmMagic.currentProcessor();
@@ -722,17 +745,22 @@
*/
@LoadStatics
protected static final void runThread(VmThread thread) {
+ Throwable t = null;
try {
thread.asThread().run();
} catch (Throwable ex) {
try {
+ t = ex;
ex.printStackTrace();
} catch (Throwable ex2) {
/* Ignore */
}
} finally {
try {
- thread.stop(new ThreadDeath());
+ if (t == null)
+ thread.stop(new ThreadDeath());
+ else
+ thread.stop(t);
} catch (Throwable ex) {
/* Ignore */
while (true) {
Modified: trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java
===================================================================
--- trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java 2008-10-12 10:33:26 UTC (rev 4625)
+++ trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java 2008-10-12 20:00:40 UTC (rev 4626)
@@ -4,7 +4,6 @@
package org.jnode.test.core;
import java.io.IOException;
-import java.io.InterruptedIOException;
import javax.isolate.Isolate;
import javax.isolate.IsolateStartupException;
import javax.isolate.IsolateStatus;
@@ -13,7 +12,7 @@
public class StatusLinkTest {
- public static void main(String[] args) throws IsolateStartupException, InterruptedIOException, IOException {
+ public static void main(String[] args) throws IsolateStartupException, IOException {
String clsName = ChildClass.class.getName();
Isolate child = new Isolate(clsName);
Link link = child.newStatusLink();
@@ -34,6 +33,7 @@
LinkMessage msg = link.receive();
if (msg.containsStatus()) {
IsolateStatus is = msg.extractStatus();
+ System.out.println("Isolate status: " + is);
if (is.getState().equals(IsolateStatus.State.EXITED)) {
System.out.println("Message: state=" + is.getState() + " code=" + is.getExitCode() +
" reason=" + is.getExitReason());
@@ -57,6 +57,23 @@
System.out.println("Child: started");
System.out.println("Child: sleeping 3 seconds");
Thread.sleep(3000);
+ //if(true)
+ // throw new RuntimeException();
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ System.out.println("Child thread: started");
+ System.out.println("Child thread: sleeping 3 seconds");
+ Thread.sleep(3000);
+ if (true)
+ throw new RuntimeException();
+ System.out.println("Child thread: exiting");
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+ }
+ }).start();
+
System.out.println("Child: exiting");
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|