private void threadroot() {
	// this should be running the current thread
	Lib.assertTrue(javaThread == Thread.currentThread());

	if (!isFirstTCB) {
	    /* start() is waiting for us to wake it up, signalling that it's OK
	     * to context switch to us. We leave the running flag false so that
	     * we'll still run if a context switch happens before we go to
	     * sleep. All we have to do is wake up the current TCB and then
	     * wait to get woken up by contextSwitch() or destroy().
	     */
	    
	    currentTCB.interrupt();
	    this.yield();
	}
	else {
	    /* start() called us directly, so we just need to initialize
	     * a couple things.
	     */
	    
	    currentTCB = this;
	    running = true;
	}

	try {
	    target.run();

	    // no way out of here without going throw one of the catch blocks
	    Lib.assertNotReached();
	}
	catch (ThreadDeath e) {
	    // make sure this TCB is being destroyed properly
	    if (!done) {
		System.out.print("\nTCB terminated improperly!\n");
		privilege.exit(1);
	    }

	    runningThreads.removeElement(this);
	    if (runningThreads.isEmpty())
		privilege.exit(0);
	}
	catch (Throwable e) {
	    System.out.print("\n");
	    e.printStackTrace();

	    runningThreads.removeElement(this);
	    if (runningThreads.isEmpty())
		privilege.exit(1);
	    else
		die();
	}
    }