/**
     * Initialize this kernel. Creates a synchronized console and sets the
     * processor's exception handler.
     */
    public void initialize(String[] args) {
	super.initialize(args);

	console = new SynchConsole(Machine.console());
	
	Machine.processor().setExceptionHandler(new Runnable() {
		public void run() { exceptionHandler(); }
	    });
    }
Exemple #2
0
public class SwapFile {

  public static OpenFile swapFile;
  private static String swapName;
  private static int PAGESIZE = Machine.processor().pageSize;
  public static List<Integer> freePages;
  public static List<Integer> allocatedPages;
  private static Lock swapLock;
  private static byte[] memory = Machine.processor().getMemory();

  public static void initialize(String filename) {
    swapFile = ThreadedKernel.fileSystem.open(filename, true);
    swapName = filename;
    freePages = new LinkedList<Integer>();
    allocatedPages = new LinkedList<Integer>();
    swapLock = new Lock();
  }

  public static void close() {
    swapFile.close();
    ThreadedKernel.fileSystem.remove(swapName);
  }

  public static int insertPage(int spn, int ppn) {
    swapLock.acquire();
    int numBits = swapFile.write(spn * PAGESIZE, memory, ppn * PAGESIZE, PAGESIZE);
    // assert that numBits == PAGESIZE
    allocatedPages.add(spn);
    swapLock.release();
    return spn;
  }

  /* we will try to allocate a free page from the freepages*/
  public static int insertPage(int ppn) {
    int numBits = 0;
    int spn = swapFile.length() / PAGESIZE;
    if (freePages.size() > 0) {
      spn = freePages.remove(0);
    }
    return insertPage(spn, ppn);
  }

  public static void readPage(int spn, int ppn) {
    if (allocatedPages.contains(spn)) {
      swapLock.acquire();
      swapFile.read(spn * PAGESIZE, memory, ppn * PAGESIZE, PAGESIZE);
      swapLock.release();
    } else {
    }
  }

  public static void free(int page) {
    swapLock.acquire();
    freePages.add(page);
    swapLock.release();
  }
}
Exemple #3
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(); // +hy+

    ((KThread) waitQueue.removeFirst()).ready(); // +hy+

    Machine.interrupt().restore(intStatus); // +hy+
  }
Exemple #4
0
  private void syncTLB() {
    for (int i = 0; i < Machine.processor().getTLBSize(); i++) {

      TranslationEntry tE = Machine.processor().readTLBEntry(i);
      if (tE.valid) {
        pageTable[tE.vpn].dirty = tE.dirty;
        pageTable[tE.vpn].used = tE.used;
      }
    }
  }
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
  /** Moves this thread to the ready state and adds this to the scheduler's ready queue. */
  public void ready() {
    Lib.debug(dbgThread, "Ready thread: " + toString());

    Lib.assertTrue(Machine.interrupt().disabled());
    Lib.assertTrue(status != statusReady);

    status = statusReady;
    if (this != idleThread) readyQueue.waitForAccess(this);

    Machine.autoGrader().readyThread(this);
  }
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
  /**
   * 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 #9
0
  /**
   * Save the state of this process in preparation for a context switch. Called by
   * <tt>UThread.saveState()</tt>.
   */
  public void saveState() {
    for (int i = 0; i < Machine.processor().getTLBSize(); i++) {

      TranslationEntry tE = Machine.processor().readTLBEntry(i);
      if (tE.valid) {
        pageTable[tE.vpn].dirty = tE.dirty;
        pageTable[tE.vpn].used = tE.used;
      }
      tE.valid = false;
      Machine.processor().writeTLBEntry(i, tE);
      // savedState[i] = tE.vpn;
    }
  }
Exemple #10
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 #11
0
 public void run() {
   long wakeTime = randomDelay();
   System.out.println(
       "** "
           + name
           + ": Sleeping for "
           + wakeTime
           + " (i.e., until time="
           + (wakeTime + Machine.timer().getTime())
           + ")");
   ThreadedKernel.alarm.waitUntil(wakeTime);
   System.out.println(name + " is Done Sleeping (time=" + Machine.timer().getTime() + ")");
 }
Exemple #12
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;
  }
  /**
   * 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;

    sleep();
  }
Exemple #14
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 #15
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);
  }
    /**
     * 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 #17
0
  /**
   * Transfer data from the specified array to this process's virtual memory. This method handles
   * address translation details. This method must <i>not</i> destroy the current process if an
   * error occurs, but instead should return the number of bytes successfully copied (or zero if no
   * data could be copied).
   *
   * @param vaddr the first byte of virtual memory to write.
   * @param data the array containing the data to transfer.
   * @param offset the first byte to transfer from the array.
   * @param length the number of bytes to transfer from the array to virtual memory.
   * @return the number of bytes successfully transferred.
   */
  public int writeVirtualMemory(int vaddr, byte[] data, int offset, int length) {
    Lib.assertTrue(offset >= 0 && length >= 0 && offset + length <= data.length);

    byte[] memory = Machine.processor().getMemory();

    int transferred = 0;
    while (length > 0 && offset < data.length) {
      int addrOffset = vaddr % 1024;
      int virtualPage = vaddr / 1024;

      if (virtualPage >= pageTable.length || virtualPage < 0) {
        break;
      }

      TranslationEntry pte = pageTable[virtualPage];
      if (!pte.valid || pte.readOnly) {
        break;
      }
      pte.used = true;
      pte.dirty = true;

      int physPage = pte.ppn;
      int physAddr = physPage * 1024 + addrOffset;

      int transferLength = Math.min(data.length - offset, Math.min(length, 1024 - addrOffset));
      System.arraycopy(data, offset, memory, physAddr, transferLength);
      vaddr += transferLength;
      offset += transferLength;
      length -= transferLength;
      transferred += transferLength;
    }

    return transferred;
  }
Exemple #18
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() {
    boolean intStatus = Machine.interrupt().disable();
    Lib.debug(dbgThread, "Joining to thread: " + toString());

    Lib.assertTrue(this != currentThread);

    if (cont == 0) {
      cont = 1;
      if (this.status == statusFinished) {
        return;
      } else {
        this.joinList.add(currentThread);
        currentThread.sleep();
      }
    }
    Machine.interrupt().restore(intStatus);
  }
Exemple #19
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;
    }
  }
Exemple #20
0
  @Override
  protected void init() {
    super.init();

    System.out.println("\ninitializing VMGrader..");
    System.out.println("physical pages = " + Machine.processor().getNumPhysPages());

    if (hasArgument(SwapFile)) swapFile = getStringArgument(SwapFile);
  }
Exemple #21
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());

    // FIXME Touhid :: Wake threads that have joined the currently running
    // thread
    currentThread.wakeJoinedThreads();

    Machine.interrupt().disable();

    Machine.autoGrader().finishingCurrentThread();

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

    currentThread.status = statusFinished;

    sleep();
  }
Exemple #22
0
 /**
  * Allocate a new Alarm. Set the machine's timer interrupt handler to this alarm's callback.
  *
  * <p><b>Note</b>: Nachos will not function correctly with more than one alarm.
  */
 public Alarm() {
   Machine.timer()
       .setInterruptHandler(
           new Runnable() {
             public void run() {
               timerInterrupt();
             }
           });
 }
Exemple #23
0
  /**
   * Wait for a thread to speak through this communicator, and then return the <i>word</i> that
   * thread passed to <tt>speak()</tt>.
   *
   * @return the integer transferred.
   */
  public int listen() {
    boolean intStatus = Machine.interrupt().disable();

    condLock.acquire();

    listenCount++;

    speakCond.wake();

    if (msgList.isEmpty()) listenCond.sleep();

    condLock.release();

    Machine.interrupt().restore(intStatus);

    // Must have msg if reach here.
    return msgList.remove(0);
  }
Exemple #24
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 #25
0
  /** Handle the halt() system call. */
  private int handleHalt() {
    if (this.process_id != ROOT) {
      return 0;
    }
    Machine.halt();

    Lib.assertNotReached("Machine.halt() did not halt machine!");
    return 0;
  }
Exemple #26
0
  private void begin() {
    Lib.debug(dbgThread, "Beginning thread: " + toString());

    Lib.assertTrue(this == currentThread);

    restoreState();

    Machine.interrupt().enable();
  }
    /**
     * 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 #28
0
  /**
   * Wait for a thread to listen through this communicator, and then transfer <i>word</i> to the
   * listener.
   *
   * <p>Does not return until this thread is paired up with a listening thread. Exactly one listener
   * should receive <i>word</i>.
   *
   * @param word the integer to transfer.
   */
  public void speak(int word) {
    boolean intStatus = Machine.interrupt().disable();

    condLock.acquire();

    if (listenCount == 0) {
      speakCond.sleep();
    }

    listenCount--;

    msgList.add(word);

    listenCond.wake();

    condLock.release();

    Machine.interrupt().restore(intStatus);
  }
Exemple #29
0
  /**
   * Causes this thread to begin execution. The result is that two threads are running concurrently:
   * the current thread (which returns from the call to the <tt>fork</tt> method) and the other
   * thread (which executes its target's <tt>run</tt> method).
   */
  public void fork() {
    Lib.assertTrue(status == statusNew);
    Lib.assertTrue(target != null);

    Lib.debug(dbgThread, "Forking thread: " + toString() + " Runnable: " + target);

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

    tcb.start(
        new Runnable() {
          public void run() {
            runThread();
          }
        });

    ready();

    Machine.interrupt().restore(intStatus);
  }
Exemple #30
0
 @Override
 protected int handleTestSystemCall(int type, int a0, int a1, int a2) {
   switch (type) {
     case ActionPhyPages:
       return Machine.processor().getNumPhysPages();
     case ActionGetSwapSize:
       return getSwapSize();
     default:
       return super.handleTestSystemCall(type, a0, a1, a2);
   }
 }