ECET iLab 6

ECET iLab 6

Thus lab needs to simulate virtual memory. It should show a fixed value of pages and faults while also being able to translate a virtual address to physical. Here is the source code I have so far:

 

#include <ctime>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <pthread.h>
#include <sched.h>
#include <cstdlib>

using namespace std;

#define NUM_ADDRESSES_TO_GENERATE 10000
#define IN_BUFFER_SIZE 10
#define PAGE_SIZE 2048
#define MAIN_MEMORY_SIZE 16384
#define VIRTUAL_MEMORY_SIZE 65536
#define NUM_PAGES MAIN_MEMORY_SIZE / PAGE_SIZE

// Shared buffer to write/read virtual addresses.
int inBuffer[IN_BUFFER_SIZE];

// Number of virtual addresses in the shared buffer.
int inBufferCount;

// Mutex used to synchronize access to the inBuffer.
pthread_mutex_t inBufferMutex;

// Counter for the number of page faults.
int numberOfPageFaults;

// Flag used to indicate the address generation is done.
bool addressGenerationDone;

// TODO: You’ll probably need some structures and variables to store information
// needed for page replacement and address translation.

int getNextVirtualAddress(int addr)
{
    // TODO: Replace below with your own method of generating virtual addresses.
    // You can just generate a random address if you want, which is probably the
    // easiest thing to do.
     srand(time(NULL));
    addr = rand() % VIRTUAL_MEMORY_SIZE +1;
    return 0;
}

void* doAddressGeneration(void* pArg)
{
    int addr = -1;
    int addressCount = NUM_ADDRESSES_TO_GENERATE;

    while (addressCount != 0) {
        if (inBufferCount < IN_BUFFER_SIZE) {
            addr = getNextVirtualAddress(addr);
          
            // Write the next virtual address. Be careful to synchronize
            // appropriately with the address translation thread.

            pthread_mutex_lock(&inBufferMutex);
            inBuffer[inBufferCount] = addr;
            inBufferCount++;
            pthread_mutex_unlock(&inBufferMutex);

            addressCount–;
        } else {
            // The buffer is full. Yield to wait for it to empty.
            sched_yield();
        }
    }

    // Mark that address generation is done.
    addressGenerationDone = true;

    pthread_exit(NULL);
}

int translateAddress(int addr)
{
    int pageNumber = VIRTUAL_MEMORY_SIZE / PAGE_SIZE;
    int baseVirtualAddress = pageNumber * PAGE_SIZE;
    int pageOffset = VIRTUAL_MEMORY_SIZE % PAGE_SIZE;
   
    int physAddr = MAIN_MEMORY_SIZE / PAGE_SIZE;
    int basePhysicalAddress = physAddr * PAGE_SIZE;
    int finalPhysicalAddress = basePhysicalAddress + 4;
   
     
 
    // TODO: See page 189 in the text for info about paging. You will need a page
    // table. I found Figure 3-10 useful. This figure shows how to translate a
    // virtual address to a physical address.

    // TODO: If the page table does not contain a mapping for to a page frame, a
    // page fault occurs. In this case, you will have to choose a page frame
    // (and possibly evict an old page if all page frames are in use). I would
    // recommend FIFO as the easiest to implement (see page 204). FIFO would
    // require a queue of page frames.

    return 0;
}

void* doAddressTranslation(void* pArg)
{
    int addr;
    int physAddr;
    ofstream outputFile;
    ostream* pOutput;
    outputFile.open(“ilab6_output.txt”);

    if (outputFile.is_open()) {
        pOutput = &outputFile;
    } else {
        cout << “Error opening ilab6_output.txt, using standard output”
             << endl;
        outputFile.close();
        pOutput = &cout;
    }

    cout << “Virtual:  ” << VIRTUAL_MEMORY_SIZE  << “Physical:  ” << MAIN_MEMORY_SIZE  << endl
             << “——————–” << endl;

    // Keep translating addresses until none are left.

    while (!addressGenerationDone) {
        if (inBufferCount <= 0) {
            // There are no addresses to read. Yield to wait for more.
            sched_yield();
        }

        while (inBufferCount > 0) {
            // Read the next virtual address. Be careful to synchronize
            // appropriately with the address generation thread.

            pthread_mutex_lock(&inBufferMutex);
            inBufferCount–;
            addr = inBuffer[inBufferCount];
            pthread_mutex_unlock(&inBufferMutex);

            // Translate the virtual address.

            physAddr = translateAddress(addr);
            *pOutput << “0x” << hex << setfill(‘0’) << setw(4) << addr
                     << ”  ->  0x” << hex << setfill(‘0’) << setw(4) << physAddr
                     << endl;
        }
    }

    if (outputFile.is_open()) {
        outputFile.close();
    }

    pthread_exit(NULL);
}

void* doStatistics(void* pArg)
{
    pthread_t* pAddrTranThread = (pthread_t*)pArg;

    // Wait until address translation thread exits.
    pthread_join(*pAddrTranThread, NULL);

    cout << “Total Number of Page Faults = ” << numberOfPageFaults << endl;

    pthread_exit(NULL);
}

int main(int argc, char* argv[])
{
    pthread_attr_t attrs;
    pthread_t addrGenThread;
    pthread_t addrTranThread;
    pthread_t statsThread;

    // TODO: Seed random number generator. If your getNextVirtualAddress
    // function does not generate random numbers, the following line can be
    // removed.
    srand(time(NULL));

    pthread_mutex_init(&inBufferMutex, NULL);

    pthread_attr_init(&attrs);
    pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_JOINABLE);

    // Create three joinable threads, one for each component of the iLab.

    pthread_create(&addrGenThread, &attrs, doAddressGeneration, NULL);
    pthread_create(&addrTranThread, &attrs, doAddressTranslation, NULL);
    pthread_create(&statsThread, &attrs, doStatistics, &addrTranThread);

    pthread_attr_destroy(&attrs);

    pthread_join(addrGenThread, NULL);
    pthread_join(addrTranThread, NULL);

    pthread_mutex_destroy(&inBufferMutex);

    pthread_join(statsThread, NULL);

    // Once all the component threads have exited, the program can exit.

    return 0;
}

"Is this question part of your assignment? We can help"

ORDER NOW