/**
     * The exception handler. This handler is called by the processor whenever
     * a user instruction causes a processor exception.
     *
     * <p>
     * When the exception handler is invoked, interrupts are enabled, and the
     * processor's cause register contains an integer identifying the cause of
     * the exception (see the <tt>exceptionZZZ</tt> constants in the
     * <tt>Processor</tt> class). If the exception involves a bad virtual
     * address (e.g. page fault, TLB miss, read-only, bus error, or address
     * error), the processor's BadVAddr register identifies the virtual address
     * that caused the exception.
     */
    public void exceptionHandler() {
	Lib.assert(KThread.currentThread() instanceof UThread);

	UserProcess process = ((UThread) KThread.currentThread()).process;
	int cause = Machine.processor().readRegister(Processor.regCause);
	process.handleException(cause);
    }
Exemple #2
0
    public void run() {
      Lib.debug('t', "### Try to listen from " + KThread.currentThread().toString());

      int res = comm.listen();

      Lib.debug('t', "### listened " + res + " from " + KThread.currentThread().toString());
    }
Exemple #3
0
  /**
   * Relinquish the CPU, because the current thread has either finished or it is blocked. This
   * thread must be the current thread.
   *
   * <p>If the current thread is blocked (on a synchronization primitive, i.e. a <tt>Semaphore</tt>,
   * <tt>Lock</tt>, or <tt>Condition</tt>), eventually some thread will wake this thread up, putting
   * it back on the ready queue so that it can be rescheduled. Otherwise, <tt>finish()</tt> should
   * have scheduled this thread to be destroyed by the next thread to run.
   */
  public static void sleep() {
    Lib.debug(dbgThread, "Sleeping thread: " + currentThread.toString());

    Lib.assertTrue(Machine.interrupt().disabled());

    if (currentThread.status != statusFinished) currentThread.status = statusBlocked;

    runNextThread();
  }
Exemple #4
0
    public void run() {
      lock.acquire();

      System.out.print(KThread.currentThread().getName() + " acquired lock\n");
      condition.sleep();
      System.out.print(KThread.currentThread().getName() + " acquired lock again\n");

      lock.release();
      System.out.print(KThread.currentThread().getName() + " released lock \n");
    }
Exemple #5
0
 public void wakeJoinedThreads() {
   boolean oldInterruptStatus = Machine.interrupt().disable();
   KThread thread = null;
   do {
     thread = waitingKThreadListToJoin.nextThread();
     if (thread != null) {
       thread.ready();
     }
   } while (thread != null);
   Machine.interrupt().restore(oldInterruptStatus);
 }
Exemple #6
0
  /**
   * Wake up at most one thread sleeping on this condition variable. The current thread must hold
   * the associated lock.
   */
  public void wake() {
    Lib.assertTrue(conditionLock.isHeldByCurrentThread());

    boolean intStatus = Machine.interrupt().disable();

    KThread thread = waitQueue.nextThread();
    if (thread != null) {
      thread.ready();
    }

    Machine.interrupt().restore(intStatus);
  }
Exemple #7
0
  /**
   * Atomically release the associated lock and go to sleep on this condition variable until another
   * thread wakes it using <tt>wake()</tt>. The current thread must hold the associated lock. The
   * thread will automatically reacquire the lock before <tt>sleep()</tt> returns.
   */
  public void sleep() {
    Lib.assertTrue(conditionLock.isHeldByCurrentThread());

    boolean intStatus = Machine.interrupt().disable();

    conditionLock.release();
    waitQueue.waitForAccess(KThread.currentThread());
    KThread.sleep();
    conditionLock.acquire();

    Machine.interrupt().restore(intStatus);
  }
Exemple #8
0
  /**
   * Relinquish the CPU if any other thread is ready to run. If so, put the current thread on the
   * ready queue, so that it will eventually be rescheuled.
   *
   * <p>Returns immediately if no other thread is ready to run. Otherwise returns when the current
   * thread is chosen to run again by <tt>readyQueue.nextThread()</tt>.
   *
   * <p>Interrupts are disabled, so that the current thread can atomically add itself to the ready
   * queue and switch to the next thread. On return, restores interrupts to the previous state, in
   * case <tt>yield()</tt> was called with interrupts disabled.
   */
  public static void yield() {
    Lib.debug(dbgThread, "Yielding thread: " + currentThread.toString());

    Lib.assertTrue(currentThread.status == statusRunning);

    boolean intStatus = Machine.interrupt().disable();

    currentThread.ready();

    runNextThread();

    Machine.interrupt().restore(intStatus);
  }
Exemple #9
0
  /**
   * Put the current thread to sleep for at least <i>x</i> ticks, waking it up in the timer
   * interrupt handler. The thread must be woken up (placed in the scheduler ready set) during the
   * first timer interrupt where
   *
   * <p>
   *
   * <blockquote>
   *
   * (current time) >= (WaitUntil called time)+(x)
   *
   * </blockquote>
   *
   * @param x the minimum number of clock ticks to wait.
   * @see nachos.machine.Timer#getTime()
   */
  public void waitUntil(long x) {
    // disable interrupts
    Machine.interrupt().disable(); // let's see if this works? DAC DEBUG
    // calculate wakeTime
    long wakeTime = Machine.timer().getTime() + x;
    // create AlarmBucket
    AlarmBucket Abuck = new AlarmBucket(wakeTime, KThread.currentThread());
    // add current thread (alarm bucket) to waitQueue
    waitQueue.add(Abuck);
    // put current thread to sleep
    KThread.currentThread().sleep();

    return;
  }
Exemple #10
0
  /**
   * Dispatch the CPU to this thread. Save the state of the current thread, switch to the new thread
   * by calling <tt>TCB.contextSwitch()</tt>, and load the state of the new thread. The new thread
   * becomes the current thread.
   *
   * <p>If the new thread and the old thread are the same, this method must still call
   * <tt>saveState()</tt>, <tt>contextSwitch()</tt>, and <tt>restoreState()</tt>.
   *
   * <p>The state of the previously running thread must already have been changed from running to
   * blocked or ready (depending on whether the thread is sleeping or yielding).
   *
   * @param finishing <tt>true</tt> if the current thread is finished, and should be destroyed by
   *     the new thread.
   */
  private void run() {
    Lib.assertTrue(Machine.interrupt().disabled());

    Machine.yield();

    currentThread.saveState();

    Lib.debug(dbgThread, "Switching from: " + currentThread.toString() + " to: " + toString());

    currentThread = this;

    tcb.contextSwitch();

    currentThread.restoreState();
  }
Exemple #11
0
  /**
   * Create the idle thread. Whenever there are no threads ready to be run, and
   * <tt>runNextThread()</tt> is called, it will run the idle thread. The idle thread must never
   * block, and it will only be allowed to run when all other threads are blocked.
   *
   * <p>Note that <tt>ready()</tt> never adds the idle thread to the ready set.
   */
  private static void createIdleThread() {
    Lib.assertTrue(idleThread == null);

    idleThread =
        new KThread(
            new Runnable() {
              public void run() {
                while (true) yield();
              }
            });
    idleThread.setName("idle");

    Machine.autoGrader().setIdleThread(idleThread);

    idleThread.fork();
  }
Exemple #12
0
  /** Test if this module is working. */
  public static void selfTest() {

    System.out.print("Enter Condition2.selfTest\n");

    Lock lock = new Lock();
    Condition2 condition = new Condition2(lock);

    KThread t[] = new KThread[10];
    for (int i = 0; i < 10; i++) {
      t[i] = new KThread(new Condition2Test(lock, condition));
      t[i].setName("Thread" + i).fork();
    }

    KThread.yield();

    lock.acquire();

    System.out.print("condition.wake();\n");
    condition.wake();

    System.out.print("condition.wakeAll();\n");
    condition.wakeAll();

    lock.release();

    System.out.print("Leave Condition2.selfTest\n");

    t[9].join();
  }
Exemple #13
0
  /**
   * Prepare this thread to be run. Set <tt>status</tt> to <tt>statusRunning</tt> and check
   * <tt>toBeDestroyed</tt>.
   */
  protected void restoreState() {
    Lib.debug(dbgThread, "Running thread: " + currentThread.toString());

    Lib.assertTrue(Machine.interrupt().disabled());
    Lib.assertTrue(this == currentThread);
    Lib.assertTrue(tcb == TCB.currentTCB());

    Machine.autoGrader().runningThread(this);

    status = statusRunning;

    if (toBeDestroyed != null) {
      toBeDestroyed.tcb.destroy();
      toBeDestroyed.tcb = null;
      toBeDestroyed = null;
    }
  }
    /**
     * Start running user programs, by creating a process and running a shell
     * program in it. The name of the shell program it must run is returned by
     * <tt>Machine.getShellProgramName()</tt>.
     *
     * @see	nachos.machine.Machine#getShellProgramName
     */
    public void run() {
	super.run();

	UserProcess process = UserProcess.newUserProcess();
	
	String shellProgram = Machine.getShellProgramName();	
	Lib.assert(process.execute(shellProgram, new String[] { }));

	KThread.currentThread().finish();
    }
Exemple #15
0
  /**
   * Finish the current thread and schedule it to be destroyed when it is safe to do so. This method
   * is automatically called when a thread's <tt>run</tt> method returns, but it may also be called
   * directly.
   *
   * <p>The current thread cannot be immediately destroyed because its stack and other execution
   * state are still in use. Instead, this thread will be destroyed automatically by the next thread
   * to run, when it is safe to delete this thread.
   */
  public static void finish() {
    Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString());

    Machine.interrupt().disable();

    Machine.autoGrader().finishingCurrentThread();

    Lib.assertTrue(toBeDestroyed == null);
    toBeDestroyed = currentThread;

    currentThread.status = statusFinished;

    // When this thread is finished, we need to reset the status of all
    // waited/blocked thread to ready state.
    while (!currentThread.waitedThreadList.isEmpty()) {
      KThread threadToRestore = currentThread.waitedThreadList.remove(0);
      threadToRestore.ready();
    }

    sleep();
  }
Exemple #16
0
  /**
   * Finish the current thread and schedule it to be destroyed when it is safe to do so. This method
   * is automatically called when a thread's <tt>run</tt> method returns, but it may also be called
   * directly.
   *
   * <p>The current thread cannot be immediately destroyed because its stack and other execution
   * state are still in use. Instead, this thread will be destroyed automatically by the next thread
   * to run, when it is safe to delete this thread.
   */
  public static void finish() {
    Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString());

    Machine.interrupt().disable();

    Machine.autoGrader().finishingCurrentThread();

    Lib.assertTrue(toBeDestroyed == null);
    toBeDestroyed = currentThread;

    currentThread.status = statusFinished;

    KThread aux = null;
    if (joinList.size() > 0) {
      aux = joinList.getFirst();
    }
    if (aux != null) {
      aux.ready();
      joinList.removeFirst();
    }
    sleep();
  }
Exemple #17
0
  /**
   * Waits for this thread to finish. If this thread is already finished, return immediately. This
   * method must only be called once; the second call is not guaranteed to return. This thread must
   * not be the current thread.
   */
  public void join() {
    Lib.debug(dbgThread, "Joining to thread: " + toString());

    // FIXME Touhid :: join() edit starts
    boolean intStatus = Machine.interrupt().setStatus(false);

    if (status != statusFinished) { // Joinee is not finished yet
      waitingKThreadListToJoin.waitForAccess(currentThread());
      KThread.sleep();
    }
    Machine.interrupt().restore(intStatus);
    // join() edit ends

    Lib.assertTrue(this != currentThread);
  }
Exemple #18
0
  public static void selfTest() {
    final Lock lock = new Lock();

    final Condition2 empty = new Condition2(lock);
    final LinkedList<Integer> list = new LinkedList<>();

    KThread consumer =
        new KThread(
            new Runnable() {
              public void run() {
                lock.acquire();
                while (list.isEmpty()) {
                  empty.sleep();
                }
                Lib.assertTrue(list.size() == 5, "List should have 5 values.");
                while (!list.isEmpty()) {
                  System.out.println("Removed " + list.removeFirst());
                }
                lock.release();
              }
            });

    KThread producer =
        new KThread(
            new Runnable() {
              public void run() {
                lock.acquire();
                for (int i = 0; i < 5; i++) {
                  list.add(i);
                  System.out.println("Added " + i);
                }
                empty.wake();
                lock.release();
              }
            });

    consumer.setName("Consumer");
    producer.setName("Producer");
    consumer.fork();
    producer.fork();
    consumer.join();
    producer.join();
  }
Exemple #19
0
  private void handleExit(int status) {
    if (myChildProcess != null) {
      myChildProcess.status = status;
    }

    // close all the opened files
    for (int i = 0; i < 16; i++) {
      handleClose(i);
    }

    // part2 implemented
    this.unloadSections();

    if (this.process_id == ROOT) {
      Kernel.kernel.terminate();
    } else {
      KThread.finish();
      Lib.assertNotReached();
    }
  }
Exemple #20
0
  /**
   * Waits for this thread to finish. If this thread is already finished, return immediately. This
   * method must only be called once; the second call is not guaranteed to return. This thread must
   * not be the current thread.
   */
  public void join() {
    Lib.debug(dbgThread, "Joining to thread: " + toString());

    // Precondition: this thread must not be the current thread. Moreover,
    // return if this thread is already finished.
    Lib.assertTrue(this != currentThread);
    if (this.status == this.statusFinished) return;

    // Calling sleep on a KThread requires interrupts to be disabled. We
    // will restore the status after we put the current thread to sleep.
    boolean intStatus = Machine.interrupt().disable();

    // Add the current thread into the buffer to indicate that it's blocked
    // before this thread is finished.
    this.waitedThreadList.add(this.currentThread);

    // Put the current thread to sleep, and restore the interrupt.
    currentThread.sleep();
    Machine.interrupt().restore(intStatus);
  }
Exemple #21
0
 /**
  * The timer interrupt handler. This is called by the machine's timer periodically (approximately
  * every 500 clock ticks). Causes the current thread to yield, forcing a context switch if there
  * is another thread that should be run.
  */
 public void timerInterrupt() {
   // disable interrupts (maybe not necessary)
   Machine.interrupt().disable(); // let's see if this works?
   // get current time
   long currentTime = Machine.timer().getTime();
   // go through waitQueue and put each thread that is "less than" current wait time on ready queue
   AlarmBucket placeholder = null;
   int count = waitQueue.size();
   while (count > 0) {
     placeholder = waitQueue.peek();
     if (placeholder.getTime() <= currentTime) {
       placeholder = waitQueue.poll();
       placeholder.getKThread().ready();
       count = waitQueue.size();
     } else {
       count = 0;
     }
   }
   // yield current thread
   KThread.currentThread().yield();
   // Machine.interrupt().enable(); //let's see if this works? DAC DEBUG
 }
    /**
     * Returns the current process.
     *
     * @return	the current process, or <tt>null</tt> if no process is current.
     */
    public static UserProcess currentProcess() {
	if (!(KThread.currentThread() instanceof UThread))
	    return null;
	
	return ((UThread) KThread.currentThread()).process;
    }
Exemple #23
0
  public static void selfTest() {
    comm = new Communicator();

    KThread t6 = new KThread(new TestListener()).setName("Listener 1");
    t6.fork();

    KThread t7 = new KThread(new TestListener()).setName("Listener 2");
    t7.fork();

    KThread t8 = new KThread(new TestListener()).setName("Listener 3");
    t8.fork();

    KThread t9 = new KThread(new TestListener()).setName("Listener 4");
    t9.fork();

    KThread t10 = new KThread(new TestListener()).setName("Listener 5");
    t10.fork();

    KThread t1 = new KThread(new TestSpeaker(123)).setName("Speaker 1");
    t1.fork();

    KThread t2 = new KThread(new TestSpeaker(456)).setName("Speaker 2");
    t2.fork();

    KThread t3 = new KThread(new TestSpeaker(789)).setName("Speaker 3");
    t3.fork();

    KThread t4 = new KThread(new TestSpeaker(101112)).setName("Speaker 4");
    t4.fork();

    KThread t5 = new KThread(new TestSpeaker(131415)).setName("Speaker 5");
    t5.fork();

    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();
    t6.join();
    t7.join();
    t8.join();
    t9.join();
    t10.join();

    KThread.yield();
  }
Exemple #24
0
    public void run() {
      Lib.debug('t', "### Speak " + word + " from " + KThread.currentThread().toString());

      comm.speak(word);
    }
Exemple #25
0
 public void run() {
   for (int i = 0; i < 5; i++) {
     System.out.println("*** thread " + which + " looped " + i + " times");
     currentThread.yield();
   }
 }
Exemple #26
0
  /** Determine the next thread to run, then dispatch the CPU to the thread using <tt>run()</tt>. */
  private static void runNextThread() {
    KThread nextThread = readyQueue.nextThread();
    if (nextThread == null) nextThread = idleThread;

    nextThread.run();
  }