#include <ctime>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <pthread.h>
#include <sched.h>
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 inBuffer[IN_BUFFER_SIZE]; // buffer to write/read virtual addresses
int inBufferCount; // Number of virtual addresses in the shared buffer
pthread_mutex_t inBufferMutex; // Mutex used to synchronize access to the inBuffer
int numberOfPageFaults; // Counter for the number of page faults
bool addressGenerationDone; // Flag used to indicate the address generation is done
// 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 translateAddress(int addr)
{
// 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"
...
2. int inBufferCount; // Number of virtual addresses in
the shared buffer
pthread_mutex_t inBufferMutex; // Mutex used to
synchronize access to the inBuffer
int numberOfPageFaults; // Counter for the number of
page faults
bool addressGenerationDone; // Flag used to indicate the
address generation is done
// 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.
3. // 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.
5. int translateAddress(int addr)
{
// 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;
}
6. 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;
}
7. *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--;
10. 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,
11. 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;
}