2023-11-23 16:51:18 -04:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdbool.h>
|
2023-11-25 22:32:34 -04:00
|
|
|
|
|
2023-11-23 16:51:18 -04:00
|
|
|
|
#define OFFSETBITS 12
|
|
|
|
|
#define PAGESIZE (1 << OFFSETBITS)
|
|
|
|
|
#define PAGETABLEBITS 10
|
|
|
|
|
#define ARCH 32
|
|
|
|
|
int framesSize;
|
2023-11-25 22:32:34 -04:00
|
|
|
|
unsigned int pageFault = 0;
|
2023-11-23 16:51:18 -04:00
|
|
|
|
unsigned int pageHits = 0;
|
|
|
|
|
unsigned int pagesSwapped = 0;
|
2023-11-25 22:12:41 -04:00
|
|
|
|
int time = 0;
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
typedef struct frameEntry {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
unsigned int pageNumber;
|
|
|
|
|
int lastUsed;
|
|
|
|
|
bool dirty;
|
|
|
|
|
} frameEntry;
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
frameEntry *frames;
|
2023-11-25 22:12:41 -04:00
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
int getPageOffsetAddress(unsigned long logicalAddress) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
// Last 12 bits of logical address
|
|
|
|
|
// Page size is 4096 bytes, and we bitwise AND with 4095 (111111111111) to get the last 12 bits
|
2023-11-25 22:32:34 -04:00
|
|
|
|
return logicalAddress & (PAGESIZE - 1);
|
2023-11-25 22:12:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
int getPageNumber(unsigned long logicalAddress) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
// First 20 bits of logical address
|
|
|
|
|
// Bitwise shift right 12 bits to get the first 20 bits, as the last 12 bits are discarded
|
|
|
|
|
return logicalAddress >> OFFSETBITS;
|
|
|
|
|
|
|
|
|
|
}
|
2023-11-23 16:51:18 -04:00
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
void printPhysicalAddress(int frameID, unsigned long logicalAddress) {
|
|
|
|
|
printf("%lu -> %i\n", logicalAddress, frameID * PAGESIZE + getPageOffsetAddress(logicalAddress));
|
2023-11-23 16:51:18 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
double computeFormula() {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
// probabilityOfNoPageFault ∗ 10 + probabilityOfMajorPageFaultWithOneCopy ∗ 1000 + probabilityOfMajorPageFaultWithTwoCopyOperations ∗ 3000
|
2023-11-25 22:32:34 -04:00
|
|
|
|
double probabilityOfNoPageFault = 1 - (double) pageFault / (pageFault + pageHits);
|
|
|
|
|
double probabilityOfMajorPageFaultWithOneCopy = (double) pageFault / (pageFault + pageHits) * (1 - (double) pagesSwapped / pageFault);
|
|
|
|
|
double probabilityOfMajorPageFaultWithTwoCopyOperations = (double) pageFault / (pageFault + pageHits) * (double) pagesSwapped / pageFault;
|
|
|
|
|
return probabilityOfNoPageFault * 10 + probabilityOfMajorPageFaultWithOneCopy * 1000 + probabilityOfMajorPageFaultWithTwoCopyOperations * 3000;
|
2023-11-25 22:12:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Int so we can return the index of the frame if it is in the frames array
|
2023-11-25 22:32:34 -04:00
|
|
|
|
int isInFrames(int pageNumber) {
|
|
|
|
|
for (int i = 0; i < framesSize; i++) {
|
|
|
|
|
if (frames[i].pageNumber == pageNumber) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
// Swap out the least recently used frame
|
|
|
|
|
// Returns the index of the frame that was swapped out
|
|
|
|
|
int swapOut() {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
// Find the least recently used frame
|
|
|
|
|
int leastRecentlyUsed = 0x7FFFFFFF;
|
|
|
|
|
int leastRecentlyUsedIndex = -1;
|
2023-11-25 22:32:34 -04:00
|
|
|
|
for (int i = 0; i < framesSize; i++) {
|
|
|
|
|
if (frames[i].lastUsed < leastRecentlyUsed) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
leastRecentlyUsed = frames[i].lastUsed;
|
|
|
|
|
leastRecentlyUsedIndex = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Swap out is implied, so we increment pageSwapped
|
2023-11-25 22:32:34 -04:00
|
|
|
|
// If the frame is dirty, we need to write it to disk, so we increment pagesSwapped
|
2023-11-25 22:12:41 -04:00
|
|
|
|
if (frames[leastRecentlyUsedIndex].dirty) {
|
|
|
|
|
pagesSwapped++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return leastRecentlyUsedIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
// Swap in a page
|
|
|
|
|
// Returns the index of the frame that was swapped in
|
|
|
|
|
int swapIn(int pageNumber) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
// Find the first empty frame
|
2023-11-25 22:32:34 -04:00
|
|
|
|
for (int i = 0; i < framesSize; i++) {
|
|
|
|
|
if (frames[i].pageNumber == -1) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
pageFault++;
|
|
|
|
|
frames[i].pageNumber = pageNumber;
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If no empty frames, swap out a frame
|
|
|
|
|
int frameID = swapOut();
|
|
|
|
|
frames[frameID].pageNumber = pageNumber;
|
|
|
|
|
pageFault++;
|
|
|
|
|
return frameID;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
// Read from an address
|
|
|
|
|
void readFromAddress(unsigned long logicalAddress) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
unsigned int pageNumber = getPageNumber(logicalAddress);
|
|
|
|
|
int frameID = isInFrames(pageNumber);
|
2023-11-25 22:32:34 -04:00
|
|
|
|
if (isInFrames(pageNumber) == -1) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
frameID = swapIn(pageNumber);
|
2023-11-25 22:32:34 -04:00
|
|
|
|
} else {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
pageHits++;
|
|
|
|
|
}
|
|
|
|
|
frames[frameID].lastUsed = time;
|
2023-11-25 22:32:34 -04:00
|
|
|
|
printPhysicalAddress(frameID, logicalAddress);
|
2023-11-25 22:12:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
// Write to an address, only difference is that we set the dirty bit to true
|
|
|
|
|
void writeToAddress(unsigned long logicalAddress) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
unsigned int pageNumber = getPageNumber(logicalAddress);
|
|
|
|
|
int frameID = isInFrames(pageNumber);
|
2023-11-25 22:32:34 -04:00
|
|
|
|
if (isInFrames(pageNumber) == -1) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
frameID = swapIn(pageNumber);
|
2023-11-25 22:32:34 -04:00
|
|
|
|
} else {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
pageHits++;
|
|
|
|
|
}
|
|
|
|
|
frames[frameID].dirty = true;
|
|
|
|
|
frames[frameID].lastUsed = time;
|
2023-11-25 22:32:34 -04:00
|
|
|
|
printPhysicalAddress(frameID, logicalAddress);
|
2023-11-23 16:51:18 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
|
//Disable printf buffering for easier debugging
|
2023-11-25 22:12:41 -04:00
|
|
|
|
setbuf(stdout, NULL);
|
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
framesSize = atoi(argv[1]);
|
|
|
|
|
frames = calloc(framesSize, sizeof(frameEntry));
|
2023-11-25 22:12:41 -04:00
|
|
|
|
// Initialize frames to -1, so we can check if a frame is empty
|
2023-11-25 22:32:34 -04:00
|
|
|
|
for (int i = 0; i < framesSize; i++) {
|
2023-11-25 22:12:41 -04:00
|
|
|
|
frames[i].pageNumber = -1;
|
|
|
|
|
frames[i].lastUsed = -1;
|
|
|
|
|
frames[i].dirty = false;
|
|
|
|
|
}
|
2023-11-25 22:32:34 -04:00
|
|
|
|
unsigned long logicalAddress;
|
|
|
|
|
char operation;
|
|
|
|
|
printf("Logical addresses -> Physical addresses:\n");
|
|
|
|
|
while (EOF != scanf("%c %lu\n", &operation, &logicalAddress)) {
|
|
|
|
|
if (operation == 'r') {
|
|
|
|
|
readFromAddress(logicalAddress);
|
|
|
|
|
} else {
|
|
|
|
|
writeToAddress(logicalAddress);
|
|
|
|
|
}
|
2023-11-25 22:12:41 -04:00
|
|
|
|
time++;
|
2023-11-25 22:32:34 -04:00
|
|
|
|
}
|
2023-11-23 16:51:18 -04:00
|
|
|
|
|
2023-11-25 22:32:34 -04:00
|
|
|
|
printf("\nStats:\nmajor page faults = %u\npage hits = %u\npages swapped out = %u\nEffective Access Time = %.3lf\n",
|
|
|
|
|
pageFault,
|
|
|
|
|
pageHits,
|
|
|
|
|
pagesSwapped,
|
|
|
|
|
computeFormula()
|
|
|
|
|
);
|
|
|
|
|
return EXIT_SUCCESS;
|
2023-11-23 16:51:18 -04:00
|
|
|
|
}
|