/** * 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; } }
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 + "\""); }