vmthread.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 712 行 · 第 1/2 页

JAVA
712
字号
/**
 * $Id: VmThread.java,v 1.5 2004/02/24 08:04:48 epr Exp $
 */

package org.jnode.vm;

import org.jnode.vm.classmgr.ObjectFlags;

/**
 * VM thread implementation
 * 
 * @author Ewout Prangsma (epr@users.sourceforge.net)
 */
public abstract class VmThread extends VmSystemObject {

	/**
	 * If the stackpointer grows to this distance from the size of the stack, a stack overflow
	 * exception is raised.
	 */
	public static final int STACK_OVERFLOW_LIMIT = 1024;

	public static final int DEFAULT_STACK_SIZE = 48 * 1024;

	/** A link to my java.lang.Thread */
	private Thread javaThread;

	/** Next pointer used in queues */
	protected final VmThreadQueueEntry queueEntry = new VmThreadQueueEntry(this);
	protected final VmThreadQueueEntry sleepQueueEntry = new VmThreadQueueEntry(this);

	/** The size (in bytes) of the stack of this thread */
	private int stackSize;

	/** The pointer to the stack */
	private Object stack;

	/** The pointer to end of the stack (used by native code) */
	volatile Address stackEnd;

	/** Has this thread had a stackoverflow? */
	private boolean stackOverflow;

	/** The current state of this thread */
	private int threadState = CREATED;

	/** When to wakeup (if sleeping) */
	protected long wakeupTime;

	/** The monitor i'm waiting for */
	private Monitor waitForMonitor;

	/** My priority */
	protected int priority = Thread.NORM_PRIORITY;

	/** Identifier of this thread */
	private final int id;

	/** Identifier of the last created thread */
	private static int lastId;

	/** Has this thread been interrupted? */
	private boolean interrupted;

	/** Is this thread in an exception initialization? */
	boolean inException;
	
	/** Is this thread in the process of being stopped? */
	private boolean stopping;

	/**
	 * State is set to CREATED by the static initializer. Once set to other than CREATED, it should
	 * never go back. Alternates between RUNNING and SUSPENDED/WAITING as suspend()/wait() and
	 * reseume() are called.
	 * <p>
	 * Can be set to INTERRUPTED if ASLEEP, or WAITING. Can be set to DESTROYED at any time. Can be
	 * set to STOPPED at any time.
	 * <p>
	 * If a Thread blocks in a wait(), its state stays as RUNNING. This might need to change.
	 * <p>
	 * Can sleep if RUNNING. <blockquote>
	 * 
	 * <pre>
	 *  /--------------------\ V | CREATED -> RUNNING -> SUSPENDED /
	 * </blockquote></pre>
	 */
	private final static int CREATED = 0;
	private final static int ASLEEP = 3;
	private final static int DESTROYED = 5;
	private final static int RUNNING = 1;
	private final static int STOPPED = 4;
	private final static int SUSPENDED = 2;
	private final static int WAITING = 6;
	private final static int YIELDING = 7;
	final static int MAXSTATE = YIELDING;
	final static String[] STATE_NAMES = { "CREATED", "RUNNING", "SUSPENDED", "ASLEEP", "STOPPED", "DESTROYED", "WAITING", "YIELDING" };

	/**
	 * Create a new instance. This constructor can only be called during the bootstrap phase.
	 */
	public VmThread() {
		this.threadState = RUNNING;
		this.stackSize = DEFAULT_STACK_SIZE;
		this.id = (1 << ObjectFlags.THREAD_ID_SHIFT);
	}

	/**
	 * Create a new instance.
	 * 
	 * @param javaThread
	 */
	public VmThread(Thread javaThread) {
		this.javaThread = javaThread;
		this.threadState = CREATED;
		this.stackSize = DEFAULT_STACK_SIZE;
		this.id = createId();
	}

	/**
	 * Return the current thread
	 * @return The current thread
	 */
	public static VmThread currentThread() {
		return Unsafe.getCurrentProcessor().getCurrentThread();
	}

	/**
	 * Initialize the threading system.
	 */
	static void initialize() {
		// Ensure that we have a java.lang.Thread object for the root thread.
		final VmThread currentThread = currentThread();
		currentThread.asThread();
		lastId = currentThread.id;
	}

	/**
	 * Count the number of stackframes in this thread.
	 * 
	 * @return int
	 */
	public final int countStackFrames() {
		final VmProcessor proc = Unsafe.getCurrentProcessor();
		final VmStackReader reader = proc.getArchitecture().getStackReader();
		return reader.countStackFrames(Unsafe.getCurrentFrame());
	}

	/**
	 * Get the Thread to which this VmThread belongs
	 * @return The java thread
	 */
	public final Thread asThread() {
		if (javaThread == null) {
			javaThread = new Thread(this);
		}
		return javaThread;
	}

	/**
	 * Has this object already a reference to a java.lang.Thread object?
	 * @return boolean
	 */
	public final boolean hasJavaThread() {
		return (javaThread != null);
	}

	final void checkAccess() {
		asThread().checkAccess();
	}

	public final void start() {
		switch (threadState) {
			case CREATED :
				{
					//Screen.debug("thread.start");
					stack = VmSystem.allocStack(stackSize);
					Unsafe.initThread(this, stack, stackSize);
					stackEnd = getStackEnd(stack, stackSize);
					threadState = RUNNING;
					final VmProcessor proc = Unsafe.getCurrentProcessor();
					proc.addToReadyQueue(this, false, "thread.start");
				}
				break;
			case RUNNING :
			case SUSPENDED :
			case WAITING :
			case ASLEEP :
				throw new IllegalThreadStateException("already started");
			case STOPPED :
				/* XXX */
				break;
			case DESTROYED :
				throw new IllegalThreadStateException("destroyed");
			default :
				throw new IllegalThreadStateException("Unknown thread state");
		}
	}

	/**
	 * Stop the thread permanently.
	 * 
	 * @param ex
	 * @throws PragmaUninterruptible
	 */
	public final void stop(Throwable ex) throws PragmaUninterruptible {
		this.stopping = true;
		if (javaThread != null) {
			javaThread.onExit();
		}
		final VmProcessor proc = Unsafe.getCurrentProcessor();
		final VmThread current = proc.getCurrentThread();
		proc.disableReschedule();
		this.threadState = STOPPED;
		if (current == this) {
			proc.suspend();
		} else {
			proc.enableReschedule();
		}
	}

	/**
	 * Destroys this thread, without any cleanup. Any monitors it has locked remain locked. (This
	 * method is not implemented.)
	 */
	public final void destroy() {
	}

	/**
	 * Interrupt this thread.
	 * @throws PragmaUninterruptible
	 */
	public final void interrupt() throws PragmaUninterruptible {
		final VmProcessor proc = Unsafe.getCurrentProcessor();
		proc.disableReschedule();
		try {
			switch (threadState) {
				case ASLEEP :
				case WAITING :
					{
						// Set interrupted state
						this.interrupted = true;
						// Remove from queues
						wakeUpByScheduler();
						// Add to ready queue
						proc.addToReadyQueue(this, false, "thread.interrupt");
					}
					break;
			}
		} finally {
			proc.enableReschedule();
		}
	}

	/**
	 * Test the interruption status. If interrupted, the interrupted status is cleared and an
	 * InterruptedException is thrown, otherwise this method returns without any change in state.
	 * 
	 * @throws PragmaUninterruptible
	 * @throws InterruptedException
	 */
	final void testAndClearInterruptStatus() throws PragmaUninterruptible, InterruptedException {
		final boolean throwIE = this.interrupted;
		if (throwIE) {
			this.interrupted = false;
			throw new InterruptedException();
		}
	}

	/**
	 * Resume this thread.
	 */
	public final void resume() {
		checkAccess();
		if (threadState != SUSPENDED) {
			throw new IllegalThreadStateException("Not suspended");
		} else {
			final VmProcessor proc = Unsafe.getCurrentProcessor();
			threadState = RUNNING;
			proc.addToReadyQueue(this, false, "thread.resume");
		}
	}

	/**
	 * Suspend this thread.
	 * @throws PragmaUninterruptible
	 */
	public final void suspend() throws PragmaUninterruptible {
		checkAccess();
		if (threadState != RUNNING) {
			throw new IllegalThreadStateException("Not running");
		} else {
			final VmProcessor proc = Unsafe.getCurrentProcessor();
			proc.disableReschedule();
			this.threadState = SUSPENDED;
			proc.suspend();
		}
	}

	/**
	 * Give up the CPU.
	 */
	public static void yield() {
		final VmProcessor proc = Unsafe.getCurrentProcessor();
		proc.yield(false);
	}

	/**
	 * Set the state to YIELDING.
	 * @throws PragmaUninterruptible
	 */
	final void setYieldingState() throws PragmaUninterruptible {
		if (threadState == RUNNING) {
			threadState = YIELDING;
		}
	}

	/**
	 * Go to sleep for the given period.
	 * @param millis
	 * @param nanos
	 * @throws InterruptedException
	 * @throws PragmaUninterruptible
	 */
	public final void sleep(long millis, int nanos) throws InterruptedException, PragmaUninterruptible {
		if (currentThread() != this) {
			return;
		}
		if (threadState != RUNNING) {
			return;
		}

		final VmProcessor proc = Unsafe.getCurrentProcessor();
		proc.disableReschedule();
		this.wakeupTime = VmSystem.currentKernelMillis() + millis;
		this.threadState = ASLEEP;
		proc.addToSleepQueue(this);

		/* Now un-schedule myself */
		proc.suspend();

		/* We're back alive */
		testAndClearInterruptStatus();
	}

	/**
	 * Returns <code>true</code> if the thread represented by this object is running (including
	 * suspended, asleep, or interrupted). Returns <code>false</code> if the thread hasn't be
	 * started yet, is stopped or destroyed.
	 * 
	 * @return <code>true</code> if thread is alive, <code>false</code> if not.
	 * @see #start()
	 * @see #stop(Throwable)
	 * @see #suspend()
	 * @see #interrupt()
	 */
	public final boolean isAlive() {
		switch (threadState) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?