This repository has been archived by the owner on Nov 19, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
307 lines (260 loc) · 9.63 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/*
Name: Nicklaus Settoon
Project: PA-2 (Page Replacement Algorithm)
File: main.c
Instructor: Feng Chen
Class: cs4103-sp20
LogonID: cs410361
*/
#include <stdio.h>
#include <stdlib.h>
int __totalmemaccesstime = 0;
struct page{
int data;
int pagenum;
};
typedef struct page pg;
pg* makePage(int _data, int _pagenum)
{//creates a new page object with the give parameters
pg* newpage = malloc(sizeof *newpage);
newpage->data = _data;
newpage->pagenum = _pagenum;
return newpage;
}
struct page_table_entry{
struct page* pgaddr;
unsigned int dirty : 1;
unsigned int ref : 1;
struct page_table_entry* prventry;
struct page_table_entry* nxtentry;
};
typedef struct page_table_entry pgentry;
struct page_table{
int currlength;
int maxlength;
unsigned int full : 1;
pgentry* head;
pgentry* tail;
};
typedef struct page_table table;
pgentry* insertPage(table* _tabletarget, pg* _pagetarget, pgentry* _prventry)
{//creates an page table entry for the target page and inserts it after the target entry
if (_tabletarget->full == 1) {//if page table is full
printf("Cannot insert page: %d. Table is full.\n", _pagetarget->pagenum);
return NULL;
}
//printf("Inserting page: %d", _pagetarget->pagenum);
//make new page entry object
pgentry* newentry = malloc(sizeof *newentry);
newentry->pgaddr = _pagetarget;
newentry->dirty = 0;
newentry->ref = 0;
if (_tabletarget->head == NULL){//if table is empty
_tabletarget->head = newentry;
newentry->prventry = NULL;
newentry->nxtentry = NULL;
}
else if (_tabletarget->tail == NULL)
{//if table only has a head
_tabletarget->tail = newentry;
newentry->prventry = _tabletarget->head;
newentry->nxtentry = _tabletarget->head;
_tabletarget->head->prventry = newentry;
_tabletarget->head->nxtentry = newentry;
}
else
{
//fix newentry's pointers
newentry->prventry = _prventry;
newentry->nxtentry = _prventry->nxtentry;
//fix entries to left and right of newentry
_prventry->nxtentry = newentry;
newentry->nxtentry->prventry = newentry;
}
//update table metadata
_tabletarget->currlength++;
if (_tabletarget->currlength == _tabletarget->maxlength)
_tabletarget->full = 1;
return newentry;
}
void deletePageEntry(table* _tabletarget, pgentry* _entrytarget)
{
//temp store appropriate pointers
pg* page = _entrytarget->pgaddr;
pgentry* prv = _entrytarget->prventry;
pgentry* nxt = _entrytarget->nxtentry;
//stitch linked list together
prv->nxtentry = nxt;
nxt->prventry = prv;
_tabletarget->currlength--;
_tabletarget->full = 0;
//if deleting the head of the linked list
if(_tabletarget->head = _entrytarget)
_tabletarget->head = nxt;
//if deleting the tail of the linked list
if(_tabletarget->tail = _entrytarget)
_tabletarget->tail = prv;
//free memory for page and its entry
free(page);
free(_entrytarget);
}
pgentry* findPage(table* _tabletarget, int _pagetarget, int _memaccesscost)
{//searches page table and returns page entry if found, NULL if not found.
pgentry* currentry = _tabletarget->head;
unsigned int found = 0;
do{
__totalmemaccesstime += _memaccesscost;
if(currentry == NULL)
return NULL;
if (currentry->pgaddr->pagenum == _pagetarget) {//if find page entry with correct page number
found = 1;
break;
}
else //move to next entry
currentry = currentry->nxtentry;
} while (currentry != _tabletarget->head);
if (found == 1)
return currentry;
else
return NULL;
}
pgentry* findVictimPage(table* _tabletarget, pgentry* _clockstart, int _memaccesscost)
{//CLOCK algorithm implementation for finding least recently used page for eviction from memory.
pgentry* clockhand;
if (_clockstart == NULL)
clockhand = _tabletarget->head;
else
clockhand = _clockstart;
unsigned int found = 0;
do{
__totalmemaccesstime += _memaccesscost;
if (clockhand->ref == 0) {//if find page entry with correct page number
found = 1;
break;
}
else
{
clockhand->ref = 0; //set ref bit to 0
clockhand = clockhand->nxtentry;
}
} while(1);
if (found == 1)
return clockhand;
else
return NULL;
}
pgentry* swapIn(table* _tabletarget, pgentry* _entrytarget, int _pagetarget)
{//swaps the page frame from disk to memory, returning the entry pointer.
//make new page
pg* newpage = makePage(0,_pagetarget);
//make new page table entry
pgentry* newentry = insertPage(_tabletarget, newpage, _entrytarget);
return newentry;
}
void swapOut(table* _tabletarget, pgentry* _entrytarget)
{//swaps the page frame from memory to disk if it is dirty, just frees page otherwise.
deletePageEntry(_tabletarget, _entrytarget);
}
int main(int argcount, char* argv[])
{//main is where the heart is.
//get page frame count and create page table
const int PAGE_FRAMES = atoi(argv[1]);
table pages;
pages.full = 0;
pages.currlength = 0;
pages.maxlength = PAGE_FRAMES;
pages.head = NULL;
pages.tail = NULL;
//open page reference file
FILE* pagerefs = fopen(argv[2],"r");
//set memory access cost and init cost counter
const int MEM_ACCESS_COST = atoi(argv[3]);
//set disk read cost and init cost counter
const int SWAP_IN_COST = atoi(argv[4]);
int __totalswapintime = 0;
//set disk write cost and init cost counter
const int SWAP_OUT_COST = atoi(argv[5]);
int __totalswapouttime = 0;
//counter for page references read from file
int __totalrefcount = 0;
//counter for page faults on read
int __readfaults = 0;
//counter for page faults on write
int __writefaults = 0;
if (pagerefs == NULL){//file isn't open
printf("Couldn't open page references file.\n");
return 0;
}
else//file is open
printf("Page references file opened.\n");
char currreadref[10];//need to set readline width = page frame digits + 2
char operation; //page operation read from file
int pagenum; //page number read from file
pgentry* clockhand = NULL;
while (fgets(currreadref, 10, pagerefs) != NULL)
{//grab each page reference line in the text file
__totalrefcount++;
printf("\n%d: %s", __totalrefcount, currreadref); //print the line
sscanf(currreadref,"%s %d", &operation, &pagenum); //parse line
pgentry* currpage = findPage(&pages, pagenum, MEM_ACCESS_COST);
pgentry* newentry;
pgentry* swapintarget;
if (currpage != NULL) {//page is found in memory (page hit)
printf("PAGE HIT! Page#: %d\n", currpage->pgaddr->pagenum);
__totalmemaccesstime += MEM_ACCESS_COST; //increment counter
currpage->ref = 1; //touch the page
//if reference is a write
if (operation == 'w' || operation == 'W')
currpage->dirty = 1; //write to page
}
else { //if page isn't in memory (page miss)
printf("PAGE MISS! Page#: %d\n", pagenum);
if (pages.full == 1) {//if page table is full
printf("Page table full. Table count: %d\n", pages.currlength);
//find victim page
clockhand = findVictimPage(&pages, clockhand, MEM_ACCESS_COST);
//prep for swapin after removal of clockhand's page
swapintarget = clockhand->prventry;
//swap the victim page out
if(clockhand->dirty == 1) //if page has been written to
__totalswapouttime += SWAP_OUT_COST; //increment counter
swapOut(&pages, clockhand);
//swap new page in to memory at clockhand's old position
newentry = swapIn(&pages, swapintarget, pagenum);
__totalswapintime += SWAP_IN_COST;
//move clockhand forward one entry
clockhand = newentry->nxtentry;
}
else {//page table has space
swapintarget = pages.tail;
//swap new page in to target location
newentry = swapIn(&pages, swapintarget, pagenum);
__totalswapintime += SWAP_IN_COST;
}
newentry->ref = 1; //touch the page
__totalmemaccesstime += MEM_ACCESS_COST; //increment counter
//if reference is a read
if (operation == 'r' || operation == 'R')
__readfaults++; //increment counter
//printf("%d: read page %d\n", __totalrefcount, pagenum);
else if (operation == 'w' || operation == 'W')
{//if reference is a write
// printf("%d: write page %d\n", __totalrefcount, pagenum);
__writefaults++; //increment counter
newentry->dirty = 1; //write to page
}
else {
printf("Did not understand reference #%d.\n", __totalrefcount);
}
}
printf("\n");
}
fclose(pagerefs);
printf("\nTotal Page References: %d", __totalrefcount);
printf("\nTotal Page Faults on Reads: %d", __readfaults);
printf("\nTotal Page Faults on Writes: %d", __writefaults);
printf("\nTotal Memory Access Times: %d", __totalmemaccesstime);
printf("\nTotal Time Spent Swapping Pages In: %d", __totalswapintime);
printf("\nTotal Time Spent Swapping Pages Out: %d", __totalswapouttime);
return 0;
}