Open austinxiao-ucsd opened 8 years ago
/* * Read a null-terminated string from this process's virtual memory. Read * at most maxLength + 1 bytes from the specified address, search * for the null terminator, and convert it to a java.lang.String, * without including the null terminator. If no null terminator is found, * returns null. * @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 null 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;
}
/**
* Transfer data from this process's virtual memory to the specified array.
* 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 read.
* @param data the array where the data will be stored.
* @param offset the first byte to write in the array.
* @param length the number of bytes to transfer from virtual memory to
* the array.
* @return the number of bytes successfully transferred.
*/
@Override
public int readVirtualMemory(int vaddr, byte[] data, int offset,
int length) {
Lib.assertTrue(offset >= 0 && length >= 0 && offset+length <= data.length);
byte[] memory = Machine.processor().getMemory();
int amount = 0;
while (length > 0) {
//get the page number from virtual address
int vpn = Processor.pageFromAddress(vaddr);
int off = Processor.offsetFromAddress(vaddr);
int transfer = Math.min(length, pageSize-off);
// need to handle page fault here as well
int ppn = pinVirtualPage(vpn, false);
if (ppn == -1)
break;
// Pin the physical pages
// also need to add a lock here.
// handle page faults
// Pin the physical pages
// also need to add a lock here.
// handle page faults
if(VMKernel.IPTable[ppn].vpn == -1)
pageFaultHandler(VMKernel.IPTable[vpn].vpn);
// increment the num of pages pinned
VMKernel.pinnedCount ++;
VMKernel.IPTable[ppn].pin = true;
System.arraycopy(memory, ppn*pageSize + off, data, offset,
transfer);
unpinVirtualPage(vpn);
VMKernel.IPTable[ppn].pin = false;
VMKernel.pinnedCount = 0;
VMKernel.allPinned.wakeAll();
vaddr += transfer;
offset += transfer;
amount += transfer;
length -= transfer;
}
return amount;
}
/**
* Transfer all data from the specified array to this process's virtual
* memory.
* Same as <tt>writeVirtualMemory(vaddr, data, 0, data.length)</tt>.
*
* @param vaddr the first byte of virtual memory to write.
* @param data the array containing the data to transfer.
* @return the number of bytes successfully transferred.
*/
@Override
public int writeVirtualMemory(int vaddr, byte[] data) {
return writeVirtualMemory(vaddr, data, 0, data.length);
}
/**
* 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 amount = 0;
while (length > 0) {
int vpn = Processor.pageFromAddress(vaddr);
int off = Processor.offsetFromAddress(vaddr);
int transfer = Math.min(length, pageSize-off);
int ppn = pinVirtualPage(vpn, true);
if (ppn == -1)
break;
// Pin the physical pages
// also need to add a lock here.
// handle page faults
if(VMKernel.IPTable[ppn].vpn == -1)
pageFaultHandler(VMKernel.IPTable[vpn].vpn);
// increment the num of pages pinned
VMKernel.pinnedCount ++;
VMKernel.IPTable[ppn].pin = true;
System.arraycopy(data, offset, memory, ppn*pageSize + off,
transfer);
unpinVirtualPage(vpn);
VMKernel.IPTable[ppn].pin = false;
VMKernel.pinnedCount = 0;
VMKernel.allPinned.wakeAll();
vaddr += transfer;
offset += transfer;
amount += transfer;
length -= transfer;
}
return amount;
}
protected int pinVirtualPage(int vpn, boolean isUserWrite) {
if (vpn < 0 || vpn >= pageTable.length)
return -1;
TranslationEntry entry = pageTable[vpn];
if (!entry.valid || entry.vpn != vpn)
return -1;
if (isUserWrite) {
if (entry.readOnly)
return -1;
entry.dirty = true;
}
entry.used = true;
return entry.ppn;
}
protected void unpinVirtualPage(int vpn) {
}
/* * Read a null-terminated string from this process's virtual memory. Read * at most maxLength + 1 bytes from the specified address, search * for the null terminator, and convert it to a java.lang.String, * without including the null terminator. If no null terminator is found, * returns null. * @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 null if no null terminator was * found. */ public String readVirtualMemoryString(int vaddr, int maxLength) { Lib.assertTrue(maxLength >= 0);