Virtual Memory Simulation

profileyar969
my_attempt.docx

// ECET360 - iLab 6 Skeleton

#include <ctime>

#include <iomanip>

#include <iostream>

#include <fstream>

#include <pthread.h>

#include <sched.h>

#include <cstdlib>

#include <stdio.h>

#include <ctype.h>

#include <time.h>

#include <vector>

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

int translateAddress;

// 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.

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 numberOfFrames = 0;

voidFIFO(vector<int> virtualPageVector, int numberOfFrames)

{

int FIFOarray[numberOfFrames];

int pageFaults=0;

int firstIn = 1;

int pf= 0;

int round =0;

for(unsigned int i = 0; i < virtualPageVector.PAGE_SIZE(); i++)

{

if (numberOfFrames > i)

{

FIFOarray[i] = virtualPageVector[i];

cout << FIFOarray[i] << endl;

pageFaults++;

}

if (i >= numberOfFrames)

{

for (int j = 0; j < = numberOfFrames; j++)

{

if(FIFOarray[j] == virtualPageVector[i])

{

pf = -1;

round ++

}

}

if (pf == 0)

{

FIFOarray[firstIn] = virtualPageVector[i];

cout << FIFOarray[firstIn] << endl;

pageFaults++;

round= 0;

}

if(round > 1)

{

firstIn++;

}

pf = 0;

if(firstIn > numberOfFrames)

{

firstIn = 1;

}

}

}

cout << "Page Faults: "<< pageFaults << endl;

}

// 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.

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;

}

*pOutput << "Virtual -> Physical" << 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(0));

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;

}