paulszh / CSE-120-Project-3

1 stars 1 forks source link

read && write virtual #1

Open austinxiao-ucsd opened 8 years ago

austinxiao-ucsd commented 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) {
}
austinxiao-ucsd commented 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) {
}