private int handleClose(int a0) { OpenFile file = openfiles.get(a0); if (file == null) return -1; file.close(); openfiles.remove(a0); available_descriptors.add(a0); return 0; }
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 { } }
/* 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 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; }
private int handleWrite(int a0, int bufaddr, int count) { OpenFile file = openfiles.get(a0); if (file == null) return -1; byte[] transfer_buffer = new byte[Processor.pageSize]; int total_transfer = 0; while (count > 0) { int readlen = Math.min(Processor.pageSize, count); int actualread = readVirtualMemory(bufaddr, transfer_buffer, 0, readlen); if (actualread == -1) return -1; if (actualread < readlen) return -1; int written_bytes = file.write(transfer_buffer, 0, actualread); if (written_bytes != actualread) { return -1; } count -= actualread; bufaddr += actualread; total_transfer += actualread; } return total_transfer; }
/** * 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; }
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 + "\""); }
public static void close() { swapFile.close(); ThreadedKernel.fileSystem.remove(swapName); }