-
Notifications
You must be signed in to change notification settings - Fork 0
/
swap.c
145 lines (140 loc) · 5.78 KB
/
swap.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
#include "main_memory.h"
#include "../global_variables.h"
disk_map_entry* init_disk_map_entry(int pid, uint32_t* page_table_entry, int loc){
disk_map_entry* new = malloc(sizeof(disk_map_entry));
new->pid = pid;
new->page_table_entry = page_table_entry;
new->location_in_sec_mem = loc;
return new;
}
/*
Swap in a page into frame pointed to by frame_number from page_table_entry
Returns: Success - 0, Failure - 1
*/
bool swap_in(main_memory* main_mem, task_struct* task, uint32_t* page_table_entry){
if (isEmpty(main_mem->disk_map))
return 1; /* Page not in disk */
q_node* curr = main_mem->disk_map->front;
q_node* prev = NULL;
/* Iterate through disk map */
while( (((disk_map_entry*)(curr->data_ptr))->page_table_entry != page_table_entry) && (((disk_map_entry*)(curr->data_ptr))->pid != task->pid) ) {
if(curr->next == NULL)
return 1; /* Page not in disk */
prev = curr;
curr = curr->next;
}
/* Remove the entry */
if(curr == main_mem->disk_map->front){
main_mem->disk_map->front = main_mem->disk_map->front->next;
}
else{
prev->next = curr->next;
}
if(curr==main_mem->disk_map->rear){
main_mem->disk_map->rear = prev;
}
main_mem->disk_map->node_count--;
uint64_t sec_base_address = ((disk_map_entry*)(curr->data_ptr))->location_in_sec_mem;
/* Can Iterate and get the data from secondary memory using this address */
return 0;
}
/*
Swap a page indicated by frame_entry out of main memory.
Global and clean pages are not swapped out
Resets the DIRTY bit
*/
void swap_out(main_memory* main_mem, task_struct* task, uint32_t* page_table_entry){
if((*(page_table_entry))&GLOBAL_MASK){ /* If Global, Don't swap out */
return;
}
if((*(page_table_entry))&DIRTY_MASK){ /* If Dirty, only then swap out */
uint64_t sec_free_blk_base_address; /*Get a free block in secondary memory */
push(main_mem->disk_map,init_disk_map_entry(task->pid, page_table_entry, sec_free_blk_base_address));
/* Can move the frame to the block */
/* Mark clean */
*(page_table_entry) = reset_bit_pgtbl_entry((*(page_table_entry)),DIRTY_MASK);
}
}
/*
Suspend or Shut a process down.
If suspend, then removes all the pages from main memory, invalidates entries in page tables and deallocates the frames.
Shudown does all this and also deallocates all page tables.
Changes status of task to SWAPPED_OUT or FINISHED based on the suspend argument
*/
void unload_task(main_memory* main_mem, task_struct* task, bool suspend){
if(suspend){
/* Visit and swap out all pages */
for(uint32_t pgd_offset=0;pgd_offset<task->ptlr;pgd_offset++){
uint32_t* pgd_ent = pgd_entry_from_offset(task, pgd_offset);
if(!is_valid_entry(*pgd_ent)){
continue;
}
for(uint32_t pmd_offset=0;pmd_offset<ENTRY_PER_PG;pmd_offset++){
uint32_t* pmd_ent = pmd_entry_from_offset(main_mem->mem_arr, *pgd_ent, pmd_offset);
if(!is_valid_entry(*pmd_ent)){
continue;
}
for(uint32_t pld_offset=0;pld_offset<ENTRY_PER_PG;pld_offset++){
uint32_t* pld_ent = pld_entry_from_offset(main_mem->mem_arr, *pmd_ent, pld_offset);
if(!is_valid_entry(*pld_ent)){
continue;
}
for(uint32_t pt_offset=0;pt_offset<ENTRY_PER_PG;pt_offset++){
uint32_t* pt_ent = pt_entry_from_offset(main_mem->mem_arr, *pld_ent, pt_offset);
if(!is_valid_entry(*pt_ent)){
continue;
}
*pt_ent = reset_bit_pgtbl_entry(*pt_ent,VALID_MASK);
frame_table_entry* frame_entry = page_table_entry_to_frame_table_entry_ptr(main_mem->frame_tbl->table,*pt_ent);
/* If frame not global (handled by the functions), swap unallocate corresponding frames */
swap_out(main_mem, task, frame_entry->page_table_entry);
deallocate_frame(main_mem, frame_entry);
}
}
}
}
}
else{
/* If finishing, unallocate every frame allocated, including page tables */
for(int i=0;i<NUM_FRAMES;i++){
if(main_mem->frame_tbl->table[i].pid==task->pid && main_mem->frame_tbl->table[i].valid==1){
deallocate_frame(main_mem, main_mem->frame_tbl->table+i);
}
}
}
/* Flush TLB */
tlb_invalidate(gm_subsys->tlb,task);
if(suspend){
task->stat.swapped_out++;
task->status = SWAPPED_OUT;
}
else{
/* Clear disk map from entries of the process if it is finished */
if (!isEmpty(main_mem->disk_map)){
q_node* curr = main_mem->disk_map->front;
q_node* prev = NULL;
while(true) {
if(curr->next == NULL)
break;
if(((disk_map_entry*)(curr->data_ptr))->pid == task->pid){
if(curr == main_mem->disk_map->front){
main_mem->disk_map->front = main_mem->disk_map->front->next;
}
else{
prev->next = curr->next;
}
if(curr==main_mem->disk_map->rear){
main_mem->disk_map->rear = prev;
}
main_mem->disk_map->node_count--;
curr = curr->next;
}
else{
prev = curr;
curr = curr->next;
}
}
}
task->status = FINISHED;
}
}