-
Notifications
You must be signed in to change notification settings - Fork 0
/
definitions.c
231 lines (195 loc) · 6.73 KB
/
definitions.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
#include <stdio.h>
#include <stdlib.h>
#include "definitions.h"
#include "binutils.h"
mem_slot_t real_memory[N_SLOTS_RM];
sw_mem_slot_t swap[N_SLOTS_SWAP];
// process table stores the mapping between VM and RM
page_table_entry_t page_table[N_SLOTS_VM];
static int8_t get_free_real_address() {
for(int8_t i = 0; i < N_SLOTS_RM; i++) {
if(real_memory[i].page.is_free) {
//printf("Page %d is free\n", i);
return i;
}
//printf("Page %d isn't free\n", i);
}
return -1;
}
static int8_t get_free_swap_address() {
for(int8_t i = 0; i < N_SLOTS_SWAP; i++) {
if(swap[i].page.is_free) {
return i;
}
}
printf("[Warning] Swap is full\n");
return -1;
}
// set all pages as free
void init_pages_as_free() {
// literally max(N_SLOTS_RM, N_SLOTS_SWAP)
int8_t max_rm_sw = N_SLOTS_RM;
if(max_rm_sw < N_SLOTS_SWAP){
max_rm_sw = N_SLOTS_SWAP;
}
for(int8_t i = 0; i < max_rm_sw; i++) {
if(i < N_SLOTS_RM){
real_memory[i].page.is_free = 1;
}
swap[i].page.is_free = 1;
}
}
// set referenced bit of all pages as 0
void unreference_all_pages() {
for(int8_t i = 0; i < N_SLOTS_RM; i++) {
real_memory[i].page.R = 0;
}
}
// set the virtual address that was mapped on the lru as unmapped
void unmap_address(int8_t real_addr){
int i;
for(i = 0; i < N_SLOTS_VM; i++){
if(page_table[i].real_addr == real_addr && page_table[i].is_mapped == 1){
printf("Successfully unmapped virtual addr %d\n", i);
page_table[i].is_mapped = 0;
break;
}
}
}
// returns the address on swap of an old real memory address
int8_t get_swap_address(int8_t v_addr, int8_t r_addr){
int i;
printf("Searching on swap... ");
for (i = 0; i < N_SLOTS_SWAP; i++){
if(swap[i].old_vm_addr == v_addr && swap[i].old_rm_addr == r_addr && swap[i].page.is_free == 0){
GREEN()
printf("found!\n");
BLACK()
return i;
}
}
RED()
printf("not found!\n");
BLACK()
return -1;
}
// remove a page from swap and returns it
page_t remove_from_swap(int8_t swap_addr){
swap[swap_addr].page.is_free = 1; // set position as free
return swap[swap_addr].page;
}
// update counters based on the referenced bit (R)
void update_counters(){
printf("\n");
int i;
char * terminator;
for (i = 0; i < N_SLOTS_RM; i++){
terminator = i % 2 == 0 ? " | " : "\n";
// update counter
printf("RM[%d].page.R = %d%s", i, real_memory[i].page.R, terminator);
if(real_memory[i].page.referenced_counter != 0){
real_memory[i].page.referenced_counter /=2 ; // update counter;
}
if(real_memory[i].page.R == 1){
// Updating the counter: setting the first bit, from left to right, to 1
// The first bit is actually the eight one in memory (in x86-64),
// so the argument to set_bit is 7 (index starts at 0).
set_bit(&real_memory[i].page.referenced_counter, 7, true);
}
}
printf("\n");
}
int deal_with_page_miss(int8_t addr, page_table_entry_t * pte) {
// page miss
RED()
printf(" missed!\n");
BLACK()
int8_t real_addr = get_free_real_address();// -1 if didn't found
if(real_addr == -1){//real memory is full
int8_t swap_addr = get_swap_address(addr, pte->real_addr);
page_t swap_page;
bool from_swap = 0;
if(swap_addr != -1){ // is on swap
printf("Given address was on swap !\n");
swap_page = remove_from_swap(swap_addr);
from_swap = 1;
}else{
printf("Given address wasn't on swap !\n");
// get a new swap address to recieve the oldest page
swap_addr = get_free_swap_address();
}
// find lru page and puts it into swap
int8_t liberated_adrr; //liberated address
swap[swap_addr].page = lru_page(&liberated_adrr);
swap[swap_addr].page.is_free = 0;// sets the swap slot as busy
// store information for possible recovery
swap[swap_addr].old_rm_addr = liberated_adrr;
swap[swap_addr].old_vm_addr = addr;
printf("LRU was on RM[%02d]\n", liberated_adrr);
printf("VM[%02d] mapped to RM[%02d]\n", addr, liberated_adrr);
printf("obs:The removed page went to SW[%d]\n", swap_addr);
// set the virtual address that was mapped on the lru as unmapped
unmap_address(liberated_adrr);
// the freed address will recieve the new page
real_memory[liberated_adrr].page.referenced_counter = 0 ; // update counter to 0;
real_memory[liberated_adrr].page.R = 1; // was recently referenced ! (in the last cycle)
if(from_swap == 1){
real_memory[liberated_adrr].page.content = swap_page.content;
}else{
real_memory[liberated_adrr].page.content = rand()%MAX_CONTENT_VAL;
}
pte->real_addr = liberated_adrr; // store it in the page table
pte->is_mapped = 1;
page_table[addr] = *pte;
}else{
pte->real_addr = real_addr;
pte->is_mapped = 1;
real_memory[pte->real_addr].page.content = rand()%MAX_CONTENT_VAL;
real_memory[pte->real_addr].page.R = 1; // was recently referenced ! (in the last cycle)
real_memory[pte->real_addr].page.is_free = false; // set the page as linked to a virtual address
page_table[addr] = *pte;//update page table entry
printf("Page mapped to %d\n", real_addr);
}
return 0;
}
int reference_page(int8_t addr) {
if(addr >= N_SLOTS_VM) {
// invalid virtual address
return -1;
}
// lookup page table entry of given address
page_table_entry_t pte = page_table[addr];
if(pte.is_mapped){
// reference page
// assuming it's on the real memory
real_memory[pte.real_addr].page.R = 1; // was recently referenced ! (in the last cycle)
GREEN()
printf(" ok!\n");
BLACK()
}else {
return deal_with_page_miss(addr, &pte);
}
return 0;
}
// returns the last recently used page
// and changes lib_addr to the freed address
// on the real memory
page_t lru_page(int8_t *lib_addr){
int i, pi_counter = 0, n_zeros_page = 0, i_lru = 0, greatest = 0;
page_t lru;
for (i = 0; i < N_SLOTS_RM; i++){
pi_counter = real_memory[i].page.referenced_counter;
n_zeros_page = count_zeroes(pi_counter);
if(i == 0){
greatest = n_zeros_page;
}else{
if(n_zeros_page > greatest){
greatest = n_zeros_page;
i_lru = i;
}
}
}
*lib_addr = i_lru;
lru = real_memory[i_lru].page;
return lru;
}