Example #1
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;
  }
Example #2
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;
  }
Example #3
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 #4
0
  private void allocatePage(int vpn) {
    // System.out.println("TLBMiss: VPN:" + vpn + " of Process " + processID);
    TranslationEntry t = pageTable[vpn];
    if (!t.valid) {
      // System.out.println("Allocating VPN: " + t.vpn);
      lock.acquire();
      if (UserKernel.freePages.size() > 0) {
        int ppn = ((Integer) UserKernel.freePages.removeFirst()).intValue();
        t.valid = true;
        if (!t.dirty) {
          t.ppn = ppn;
          IPT[ppn] = new IPTEntry();
          IPT[ppn].process = this;
          IPT[ppn].tE = t;

          boolean isCoffSection = false;
          for (int s = 0; s < coff.getNumSections(); s++) {
            if (isCoffSection) {
              break;
            }
            CoffSection section = coff.getSection(s);
            if (section.getFirstVPN() > t.vpn) {
              continue;
            }
            for (int i = 0; i < section.getLength(); i++) {
              int svpn = section.getFirstVPN() + i;
              if (svpn == t.vpn) {
                section.loadPage(i, pinVirtualPage(t.vpn, false));
                //                System.out.println("VPN \"" + t.vpn + "\" is a COFF section");
                // System.out.println("COFF section loaded into VPN \"" + t.vpn + "\" PPN \"" +
                // t.ppn + "\"");
                isCoffSection = true;
                break;
              }
            }
          }

          if (!isCoffSection) {
            //            System.out.println("VPN \"" + t.vpn + "\" is NOT a COFF section");
            // System.out.println("PPN \"" + t.ppn + "\" Zero'd Out");
            byte[] data = new byte[Processor.pageSize];
            // writeVirtualMemory(t.vpn, data, 0, Processor.pageSize);
            byte[] memory = Machine.processor().getMemory();
            System.arraycopy(data, 0, memory, t.ppn * Processor.pageSize, Processor.pageSize);
          }
        } else // Dirty
        {
          //          System.out.println("VPN \"" + t.vpn + "\" has been swapped out, swaping into
          // PPN \"" + ppn + "\"");
          int spn = t.ppn;
          byte[] data = new byte[pageSize];
          byte[] memory = Machine.processor().getMemory();
          OpenFile swap = ThreadedKernel.fileSystem.open(".Nachos.swp", false);
          swap.read(spn * pageSize, memory, ppn * pageSize, pageSize);
          swap.close();
          t.ppn = ppn;
          // System.out.println(spn);
          freeSwapPages.set(spn, true);
          IPT[ppn] = new IPTEntry();
          IPT[ppn].process = this;
          IPT[ppn].tE = t;
          //          System.out.println("SPN \"" + spn + "\" has been swapped in.");
        }
      } else {
        syncTLB();

        // Clock Algorithm
        unpinnedPageLock.acquire();
        int numPinnedPages = 0;
        while (IPT[victim] == null || IPT[victim].tE.used || IPT[victim].pinCount) {
          if (IPT[victim] != null) {
            IPT[victim].tE.used = false;
            // System.out.println("PPN " + victim + " is used.");
          }
          if (IPT[victim].pinCount) {
            numPinnedPages++;
            // System.out.println("PPN " + victim + " is pinned.");
          }
          if (numPinnedPages == IPT.length) unpinnedPage.sleep();
          //          System.out.println("This Process is " + this.processID + " and the IPT's
          // process is " + IPT[victim].processID);
          victim = (victim + 1) % Machine.processor().getNumPhysPages();
        }
        // System.out.println("PPN " + victim + " will be evicted.");
        unpinnedPageLock.release();
        int evict = IPT[victim].tE.vpn;
        VMProcess evictedOwner = IPT[victim].process;
        int evictedPPN = victim;
        victim = (victim + 1) % Machine.processor().getNumPhysPages();

        // System.out.println("Not enough pysical memory, evicting VPN \"" + evict + "\" of process
        // " + evictedOwner.processID);
        // Swap Files
        if (evictedOwner.isDirty(evict)) {
          // System.out.println("VPN \"" + evict + "\" is dirty, swapping out.");
          OpenFile swap = ThreadedKernel.fileSystem.open(".Nachos.swp", false);
          int spn = 0;
          for (spn = 0; spn < freeSwapPages.size(); spn++) {
            if (freeSwapPages.get(spn)) {
              break;
            }
          }
          if (spn == freeSwapPages.size()) {
            freeSwapPages.add(false);
          } else {
            freeSwapPages.set(spn, false);
          }
          UserKernel.freePages.add(evictedPPN);
          byte[] memory = Machine.processor().getMemory();
          swap.write(spn * pageSize, memory, evictedPPN * pageSize, pageSize);
          swap.close();
          if (evictedOwner.processID != this.processID) {
            evictedOwner.evict(evict, spn);
          } else {
            pageTable[evict].ppn = spn;
            pageTable[evict].valid = false;
          }
          for (int i = 0; i < Machine.processor().getTLBSize(); i++) {
            TranslationEntry tE = Machine.processor().readTLBEntry(i);
            if (tE.vpn == evict && tE.ppn == evictedPPN) {
              //              System.out.println("TLBEntry " + i + " invalid");
              tE.valid = false;
              Machine.processor().writeTLBEntry(i, tE);
            }
          }
          lock.release();

          //          System.out.println("VPN \"" + evict + "\" of Process " + this.processID + "
          // swapped out to SPN \"" + spn + "\".");
          // Machine.processor().readTLBEntry(evict).valid = false;
          allocatePage(vpn);
          return;
        } else {
          if (evictedOwner.processID != this.processID) {
            // System.out.println("Evicted VPN " + evict + " of Process " + this.processID);
            evictedOwner.evict(evict);
          } else {
            pageTable[evict].valid = false;
          }
          UserKernel.freePages.add(evictedPPN);
          for (int i = 0; i < Machine.processor().getTLBSize(); i++) {
            TranslationEntry tE = Machine.processor().readTLBEntry(i);
            if (tE.vpn == evict && tE.ppn == evictedPPN) {
              //              System.out.println("TLBEntry " + i + " invalid");
              tE.valid = false;
              Machine.processor().writeTLBEntry(i, tE);
            }
          }
          lock.release();
          allocatePage(vpn);
          return;
        }
      }
      lock.release();
    }
    for (int i = 0; i < Machine.processor().getTLBSize(); i++) {
      TranslationEntry tE = Machine.processor().readTLBEntry(i);
      if (!tE.valid) {
        // System.out.println("Evicted TLBEntry " + i);
        Machine.processor().writeTLBEntry(i, t);
        // System.out.println(t.valid);
        return;
      }
    }
    syncTLB();
    int evictedEntry = (int) (Math.random() * Machine.processor().getTLBSize());
    TranslationEntry tE = Machine.processor().readTLBEntry(evictedEntry);
    pageTable[tE.vpn] = tE;
    Machine.processor().writeTLBEntry(evictedEntry, t);
    // System.out.println("Evicted TLBEntry " + evictedEntry + " randomly");
    // System.out.println("TE entered is VPN \"" + t.vpn + "\" PPN \"" + t.ppn + "\"");

  }