private void extractArguments(String[] args) {
    String testArgsString = Config.getString("AutoGrader.testArgs");
    if (testArgsString == null) {
      testArgsString = "";
    }

    for (int i = 0; i < args.length; ) {
      String arg = args[i++];
      if (arg.length() > 0 && arg.charAt(0) == '-') {
        if (arg.equals("-#")) {
          Lib.assertTrue(i < args.length, "-# switch missing argument");
          testArgsString = args[i++];
        }
      }
    }

    StringTokenizer st = new StringTokenizer(testArgsString, ",\n\t\f\r");

    while (st.hasMoreTokens()) {
      StringTokenizer pair = new StringTokenizer(st.nextToken(), "=");

      Lib.assertTrue(pair.hasMoreTokens(), "test argument missing key");
      String key = pair.nextToken();

      Lib.assertTrue(pair.hasMoreTokens(), "test argument missing value");
      String value = pair.nextToken();

      testArgs.put(key, value);
    }
  }
Example #2
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;
  }
Example #3
0
  /**
   * Read a null-terminated string from this process's virtual memory. Read at most <tt>maxLength +
   * 1</tt> bytes from the specified address, search for the null terminator, and convert it to a
   * <tt>java.lang.String</tt>, without including the null terminator. If no null terminator is
   * found, returns <tt>null</tt>.
   *
   * @param vaddr the starting virtual address of the null-terminated string.
   * @param maxLength the maximum number of characters in the string, not including the null
   *     terminator.
   * @return the string read, or <tt>null</tt> if no null terminator was found.
   */
  public String readVirtualMemoryString(int vaddr, int maxLength) {
    Lib.assertTrue(maxLength >= 0);

    byte[] bytes = new byte[maxLength + 1];

    int bytesRead = readVirtualMemory(vaddr, bytes);

    for (int length = 0; length < bytesRead; length++) {
      if (bytes[length] == 0) return new String(bytes, 0, length);
    }

    return null;
  }
  /**
   * Start this autograder. Extract the <tt>-#</tt> arguments, call <tt>init()</tt>, load and
   * initialize the kernel, and call <tt>run()</tt>.
   *
   * @param privilege encapsulates privileged access to the Nachos machine.
   */
  public void start(Privilege privilege) {
    Lib.assertTrue(this.privilege == null, "start() called multiple times");
    this.privilege = privilege;

    String[] args = Machine.getCommandLineArguments();

    extractArguments(args);

    System.out.print(" grader");

    init();

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

    kernel = (Kernel) Lib.constructObject(Config.getString("Kernel.kernel"));
    kernel.initialize(args);

    run();
  }
Example #5
0
  /**
   * Load the executable with the specified name into this process, and prepare to pass it the
   * specified arguments. Opens the executable, reads its header information, and copies sections
   * and arguments into this process's virtual memory.
   *
   * @param name the name of the file containing the executable.
   * @param args the arguments to pass to the executable.
   * @return <tt>true</tt> if the executable was successfully loaded.
   */
  private boolean load(String name, String[] args) {
    Lib.debug(dbgProcess, "UserProcess.load(\"" + name + "\")");

    OpenFile executable = ThreadedKernel.fileSystem.open(name, false);
    if (executable == null) {
      Lib.debug(dbgProcess, "\topen failed");
      return false;
    }

    try {
      coff = new Coff(executable);
    } catch (EOFException e) {
      executable.close();
      Lib.debug(dbgProcess, "\tcoff load failed");
      return false;
    }

    // make sure the sections are contiguous and start at page 0
    numPages = 0;
    for (int s = 0; s < coff.getNumSections(); s++) {
      CoffSection section = coff.getSection(s);
      if (section.getFirstVPN() != numPages) {
        coff.close();
        Lib.debug(dbgProcess, "\tfragmented executable");
        return false;
      }
      numPages += section.getLength();
    }

    // make sure the argv array will fit in one page
    byte[][] argv = new byte[args.length][];
    int argsSize = 0;
    for (int i = 0; i < args.length; i++) {
      argv[i] = args[i].getBytes();
      // 4 bytes for argv[] pointer; then string plus one for null byte
      argsSize += 4 + argv[i].length + 1;
    }
    if (argsSize > pageSize) {
      coff.close();
      Lib.debug(dbgProcess, "\targuments too long");
      return false;
    }

    // program counter initially points at the program entry point
    initialPC = coff.getEntryPoint();

    // next comes the stack; stack pointer initially points to top of it
    numPages += stackPages;
    initialSP = numPages * pageSize;

    // and finally reserve 1 page for arguments
    numPages++;

    if (!loadSections()) return false;

    // store arguments in last page
    int entryOffset = (numPages - 1) * pageSize;
    int stringOffset = entryOffset + args.length * 4;

    this.argc = args.length;
    this.argv = entryOffset;

    for (int i = 0; i < argv.length; i++) {
      byte[] stringOffsetBytes = Lib.bytesFromInt(stringOffset);
      Lib.assertTrue(writeVirtualMemory(entryOffset, stringOffsetBytes) == 4);
      entryOffset += 4;
      Lib.assertTrue(writeVirtualMemory(stringOffset, argv[i]) == argv[i].length);
      stringOffset += argv[i].length;
      Lib.assertTrue(writeVirtualMemory(stringOffset, new byte[] {0}) == 1);
      stringOffset += 1;
    }

    return true;
  }
Example #6
0
 private void delay() {
   long time = Machine.timer().getTime();
   int amount = 1000;
   ThreadedKernel.alarm.waitUntil(amount);
   Lib.assertTrue(Machine.timer().getTime() >= time + amount);
 }
 String getStringArgument(String key) {
   String value = (String) testArgs.get(key);
   Lib.assertTrue(value != null, "getStringArgument(" + key + ") failed to find key");
   return value;
 }
 /**
  * Request permission to receive a packet. The autograder can use this to drop packets very
  * selectively.
  *
  * @param privilege proves the authenticity of this call.
  * @return <tt>true</tt> if the packet should be delivered to the kernel.
  */
 public boolean canReceivePacket(Privilege privilege) {
   Lib.assertTrue(privilege == this.privilege, "security violation");
   return true;
 }
 /**
  * Notify the autograder that <tt>Processor.run()</tt> was invoked. This can be used to simulate
  * user programs.
  *
  * @param privilege proves the authenticity of this call.
  */
 public void runProcessor(Privilege privilege) {
   Lib.assertTrue(privilege == this.privilege, "security violation");
 }
 /**
  * Notify the autograder that a user program executed a syscall instruction.
  *
  * @param privilege proves the authenticity of this call.
  * @return <tt>true</tt> if the kernel exception handler should be called.
  */
 public boolean exceptionHandler(Privilege privilege) {
   Lib.assertTrue(privilege == this.privilege, "security violation");
   return true;
 }
 /**
  * Notify the autograder that a timer interrupt occurred and was handled by software if a timer
  * interrupt handler was installed. Called by the hardware timer.
  *
  * @param privilege proves the authenticity of this call.
  * @param time the actual time at which the timer interrupt was issued.
  */
 public void timerInterrupt(Privilege privilege, long time) {
   Lib.assertTrue(privilege == this.privilege, "security violation");
 }
  void level(int level) {
    this.level++;
    Lib.assertTrue(level == this.level, "level() advanced more than one step: test jumped ahead");

    if (level == targetLevel) done();
  }