Untitled

 avatar
unknown
plain_text
a year ago
4.8 kB
9
Indexable
#include "VirtualMemory.h"
#include "PhysicalMemory.h"

void clearFrame(uint64_t baseAddress) {
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        PMwrite(baseAddress * PAGE_SIZE + i, 0);
    }
}

void VMinitialize() {
    clearFrame(0);
}

bool isValidAddress(uint64_t virtualAddress) {
    if (virtualAddress >= VIRTUAL_MEMORY_SIZE) {
        return false;
    }

    if (TABLES_DEPTH > NUM_FRAMES) {
        return false;
    }

    return true;
}

int translateAddress(uint64_t virtualAddress, word_t* value, bool isWrite);

int VMread(uint64_t virtualAddress, word_t* value) {
    if (!isValidAddress(virtualAddress) || value == nullptr) {
        return 0;
    }
    return translateAddress(virtualAddress, value, false);
}

int VMwrite(uint64_t virtualAddress, word_t value) {
    if (!isValidAddress(virtualAddress)) {
        return 0;
    }
    return translateAddress(virtualAddress, &value, true);
}

int translateAddress(uint64_t virtualAddress, word_t* value, bool isWrite) {
    uint64_t address = virtualAddress;
    uint64_t offset = address & (PAGE_SIZE - 1);
    uint64_t currentFrame = 0;

    for (int depth = 0; depth < TABLES_DEPTH; depth++) {
        uint64_t index = (address >> (OFFSET_WIDTH + (TABLES_DEPTH - depth - 1) * OFFSET_WIDTH)) & (PAGE_SIZE - 1);
        word_t nextFrame;
        PMread(currentFrame * PAGE_SIZE + index, &nextFrame);

        if (nextFrame == 0) {
            if (!isWrite) {
                return 0; // Page fault or address not mapped
            }
            nextFrame = findFreeFrame(currentFrame, depth);
            if (nextFrame == 0) {
                return 0; // No free frames available
            }
            PMwrite(currentFrame * PAGE_SIZE + index, nextFrame);
            clearFrame(nextFrame); // Clear the new frame
        }

        currentFrame = nextFrame;
    }

    uint64_t physicalAddress = currentFrame * PAGE_SIZE + offset;
    if (isWrite) {
        PMwrite(physicalAddress, *value);
    } else {
        PMread(physicalAddress, value);
    }
    return 1;
}

word_t findFreeFrame(uint64_t currentFrame, int depth) {
    bool framesUsed[NUM_FRAMES] = {false};
    markUsedFrames(0, framesUsed);

    for (uint64_t frame = 1; frame < NUM_FRAMES; frame++) {
        if (!framesUsed[frame]) {
            return frame;
        }
    }

    word_t frameToEvict = findFrameToEvict();
    evictFrame(frameToEvict, currentFrame, depth);
    return frameToEvict;
}

void markUsedFrames(uint64_t frame, bool* framesUsed) {
    framesUsed[frame] = true;

    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        word_t value;
        PMread(frame * PAGE_SIZE + i, &value);
        if (value != 0) {
            markUsedFrames(value, framesUsed);
        }
    }
}

word_t findFrameToEvict() {
    // Implementing an eviction policy that uses weights for even and odd frames.
    word_t frameToEvict = 0;
    int maxWeight = -1;

    for (uint64_t frame = 1; frame < NUM_FRAMES; frame++) {
        if (isLeafFrame(frame)) {
            int weight = (frame % 2 == 0) ? WEIGHT_EVEN : WEIGHT_ODD;
            if (weight > maxWeight) {
                maxWeight = weight;
                frameToEvict = frame;
            }
        }
    }

    return frameToEvict;
}

bool isLeafFrame(uint64_t frame) {
    // A leaf frame is a frame that doesn't have any children in the page table hierarchy
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        word_t value;
        PMread(frame * PAGE_SIZE + i, &value);
        if (value != 0) {
            return false;
        }
    }
    return true;
}

void evictFrame(word_t frame, uint64_t currentFrame, int depth) {
    // Implement the logic to evict a frame.
    // This should involve writing the frame's contents back to the "disk"
    // and clearing its entries in the parent table.

    // Clear all children recursively using DFS
    clearFrameDFS(frame);

    // Find the parent frame and index
    uint64_t parentFrame = currentFrame;
    uint64_t address = frame * PAGE_SIZE;
    for (int d = 0; d < depth - 1; d++) {
        uint64_t index = (address >> (OFFSET_WIDTH + (TABLES_DEPTH - d - 1) * OFFSET_WIDTH)) & (PAGE_SIZE - 1);
        PMread(parentFrame * PAGE_SIZE + index, &parentFrame);
    }
    uint64_t index = (address >> OFFSET_WIDTH) & (PAGE_SIZE - 1);
    PMwrite(parentFrame * PAGE_SIZE + index, 0); // Set the parent entry to 0

    // Clear the frame
    PMclear(frame);
}

void clearFrameDFS(uint64_t frame) {
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        word_t value;
        PMread(frame * PAGE_SIZE + i, &value);
        if (value != 0) {
            clearFrameDFS(value);
        }
    }
    PMclear(frame);
}

void PMclear(uint64_t frame) {
    for (uint64_t i = 0; i < PAGE_SIZE; i++) {
        PMwrite(frame * PAGE_SIZE + i, 0);
    }
}
Editor is loading...
Leave a Comment