示例#1
0
 /**
  * Handle a syscall exception. Called by <tt>handleException()</tt>. The <i>syscall</i> argument
  * identifies which syscall the user executed:
  *
  * <table>
  * <tr><td>syscall#</td><td>syscall prototype</td></tr>
  * <tr><td>0</td><td><tt>void halt();</tt></td></tr>
  * <tr><td>1</td><td><tt>void exit(int status);</tt></td></tr>
  * <tr><td>2</td><td><tt>int  exec(char *name, int argc, char **argv);
  * 								</tt></td></tr>
  * <tr><td>3</td><td><tt>int  join(int pid, int *status);</tt></td></tr>
  * <tr><td>4</td><td><tt>int  creat(char *name);</tt></td></tr>
  * <tr><td>5</td><td><tt>int  open(char *name);</tt></td></tr>
  * <tr><td>6</td><td><tt>int  read(int fd, char *buffer, int size);
  * 							</tt></td></tr>
  * <tr><td>7</td><td><tt>int  write(int fd, char *buffer, int size);
  * 							</tt></td></tr>
  * <tr><td>8</td><td><tt>int  close(int fd);</tt></td></tr>
  * <tr><td>9</td><td><tt>int  unlink(char *name);</tt></td></tr>
  * </table>
  *
  * @param syscall the syscall number.
  * @param a0 the first syscall argument.
  * @param a1 the second syscall argument.
  * @param a2 the third syscall argument.
  * @param a3 the fourth syscall argument.
  * @return the value to be returned to the user.
  */
 public int handleSyscall(int syscall, int a0, int a1, int a2, int a3) {
   switch (syscall) {
     case syscallHalt:
       return handleHalt();
     case syscallCreate:
       return handleCreate(a0);
     case syscallOpen:
       return handleOpen(a0);
     case syscallRead:
       return handleRead(a0, a1, a2);
     case syscallWrite:
       return handleWrite(a0, a1, a2);
     case syscallClose:
       return handleClose(a0);
     case syscallUnlink:
       return handleUnlink(a0);
     case syscallExit:
       handleExit(a0);
     case syscallExec:
       return handleExec(a0, a1, a2);
     case syscallJoin:
       return handleJoin(a0, a1);
     default:
       Lib.debug(dbgProcess, "Unknown syscall " + syscall);
       Lib.assertNotReached("Unknown system call!");
   }
   return 0;
 }
示例#2
0
  /**
   * Initializes page tables for this process so that the executable can be demand-paged.
   *
   * @return <tt>true</tt> if successful.
   */
  protected boolean loadSections() {
    UserKernel.memoryLock.acquire();
    pageTable = new TranslationEntry[numPages];

    for (int vpn = 0; vpn < numPages; vpn++) {
      pageTable[vpn] = new TranslationEntry(vpn, -1, false, false, false, false);
    }

    UserKernel.memoryLock.release();

    // load sections

    for (int s = 0; s < coff.getNumSections(); s++) {
      CoffSection section = coff.getSection(s);

      Lib.debug(
          dbgProcess,
          "\tinitializing " + section.getName() + " section (" + section.getLength() + " pages)");

      for (int i = 0; i < section.getLength(); i++) {
        int vpn = section.getFirstVPN() + i;

        pageTable[vpn].readOnly = section.isReadOnly();
        // section.loadPage(i, pinVirtualPage(vpn, false));
      }
    }

    return true;
  }
示例#3
0
  /**
   * Allocates memory for this process, and loads the COFF sections into memory. If this returns
   * successfully, the process will definitely be run (this is the last step in process
   * initialization that can fail).
   *
   * @return <tt>true</tt> if the sections were successfully loaded.
   */
  protected boolean loadSections() {
    if (numPages > Machine.processor().getNumPhysPages()) {
      coff.close();
      Lib.debug(dbgProcess, "\tinsufficient physical memory");
      return false;
    }
    pageTable = new TranslationEntry[numPages];

    for (int i = 0; i < numPages; i++) {
      int physPage = UserKernel.allocatePage();
      if (physPage < 0) {
        Lib.debug(dbgProcess, "\tunable to allocate pages; tried " + numPages + ", did " + i);
        for (int j = 0; j < i; j++) {
          if (pageTable[j].valid) {
            UserKernel.deallocatePage(pageTable[j].ppn);
            pageTable[j].valid = false;
          }
        }
        coff.close();
        return false;
      }
      pageTable[i] = new TranslationEntry(i, physPage, true, false, false, false);
    }

    // load sections
    for (int s = 0; s < coff.getNumSections(); s++) {
      CoffSection section = coff.getSection(s);

      Lib.debug(
          dbgProcess,
          "\tinitializing " + section.getName() + " section (" + section.getLength() + " pages)");

      for (int i = 0; i < section.getLength(); i++) {
        int vpn = section.getFirstVPN() + i;

        // for now, just assume virtual addresses=physical addresses
        int ppn = pageTable[vpn].ppn;
        section.loadPage(i, ppn);
        if (section.isReadOnly()) {
          pageTable[vpn].readOnly = true;
        }
      }
    }

    coff.close();
    return true;
  }
示例#4
0
  /**
   * Handle a user exception. Called by <tt>UserKernel.exceptionHandler()</tt>. The <i>cause</i>
   * argument identifies which exception occurred; see the <tt>Processor.exceptionZZZ</tt>
   * constants.
   *
   * @param cause the user exception that occurred.
   */
  public void handleException(int cause) {
    Processor processor = Machine.processor();

    switch (cause) {
      case Processor.exceptionSyscall:
        int result =
            handleSyscall(
                processor.readRegister(Processor.regV0),
                processor.readRegister(Processor.regA0),
                processor.readRegister(Processor.regA1),
                processor.readRegister(Processor.regA2),
                processor.readRegister(Processor.regA3));
        processor.writeRegister(Processor.regV0, result);
        processor.advancePC();
        break;

      default:
        Lib.debug(dbgProcess, "Unexpected exception: " + Processor.exceptionNames[cause]);
        handleExit(-1);
        Lib.assertNotReached("Unexpected exception");
    }
  }
示例#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;
  }