-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpriority_queue.c
231 lines (196 loc) · 5.22 KB
/
priority_queue.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
/*
12/6/2017
Authors: Connor Lundberg, Jacob Ackerman, Jasmine Dacones
*/
#include "priority_queue.h"
#define ADDITIONAL_ROOM_FOR_TOSTR 4
#define PRIORITY_JUMP_EXTRA 10
#define MIN_PRIORITY_JUMP 1
/*
* Creates a priority queue.
*
* Return: A new priority queue on success, NULL on failure.
*/
PriorityQueue pq_create() {
int i, failed = -1;
PriorityQueue new_pq = (PriorityQueue) malloc(sizeof(struct priority_queue));
if (new_pq != NULL) {
for (i = 0; i < NUM_PRIORITIES; i++) {
new_pq->queues[i] = q_create();
if (new_pq->queues[i] == NULL) {
failed = i;
break;
}
if (!i) { //i == 0
setQuantumSize(new_pq->queues[i], MIN_PRIORITY_JUMP);
} else {
setQuantumSize(new_pq->queues[i], i * PRIORITY_JUMP_EXTRA);
}
}
/* If failed is non-zero, we need to free up everything else. */
for (i = 0; i <= failed; i++) {
q_destroy(new_pq->queues[i]);
}
/* Simlarly, if it is true, we need to free the priority queue. */
if (failed != -1) {
free(new_pq);
new_pq = NULL;
}
}
return new_pq;
}
/*
Returns the quantum size of the next non-empty ReadyQueue.
*/
int getNextQuantumSize (PriorityQueue PQ) {
int qSize = 0;
for (int i = 0; i < NUM_PRIORITIES; i++) {
ReadyQueue curr = PQ->queues[i];
if (!q_is_empty(curr)) {
qSize = curr->quantum_size;
break;
}
}
return qSize;
}
/*
* Destroys the provided priority queue, freeing all contents.
*
* Arguments: PQ: The Priority Queue to destroy.
*/
void pq_destroy(PriorityQueue PQ) {
int i;
/* Free all our inner FIFO queues. */
for (i = 0; i < NUM_PRIORITIES; i++) {
//printf("destroying queues[%d]\n", i);
q_destroy(PQ->queues[i]);
//printf("finished\n");
PQ->queues[i] = NULL;
}
free(PQ);
PQ = NULL;
}
/*
* Enqueues a PCB to the provided priority queue, into the correct priority bin.
*
* Arguments: PQ: The Priority Queue to enqueue to.
* pcb: the PCB to enqueue.
*/
void pq_enqueue(PriorityQueue PQ, PCB pcb) {
if(PQ && pcb) {
q_enqueue(PQ->queues[pcb->priority], pcb);
} else {
if (!PQ) {
printf("\t\t\tPRIORITY QUEUE IS NULL\t\t\t\r\n");
} else {
printf("\t\t\tPCB IS NULL\t\t\t\r\n");
}
}
}
/*
* Dequeues a PCB from the provided priority queue.
*
* Arguments: PQ: The Priority Queue to dequeue from.
* Return: The highest priority proccess in the queue, NULL if none exists.
*/
PCB pq_dequeue(PriorityQueue PQ) {
int i;
PCB ret_pcb = NULL;
for (i = 0; i < NUM_PRIORITIES; i++) {
if (!q_is_empty(PQ->queues[i])) {
ret_pcb = q_dequeue(PQ->queues[i]);
//printf("ret_pcb pid: %d\n", ret_pcb->pid);
break;
}
}
return ret_pcb;
}
/*
Finds the matching PCB in the PriorityQueue and removes it. This is used when
trying to kill PAIR or SHARED processes and their shared Mutex.
*/
PCB pq_remove_matching_pcb(PriorityQueue PQ, PCB toFind) {
ReadyQueueNode curr;
ReadyQueueNode last;
PCB found = NULL;
for (int i = 0; i < NUM_PRIORITIES; i++) {
curr = PQ->queues[i]->first_node;
last = NULL;
while (curr) { //searches through the linked list
if (curr->pcb == toFind) {
if (curr == PQ->queues[i]->first_node) { //if the PCB is the first node in the list
printf("found at start of queue\n");
//toStringPriorityQueue(PQ);
PQ->queues[i]->first_node = curr->next;
if (PQ->queues[i]->last_node == curr) { //if the PCB is the first and last node in the list
PQ->queues[i]->last_node = NULL;
}
} else { //otherwise
printf("not found at start of queue\n");
//toStringPriorityQueue(PQ);
last->next = curr->next;
}
//toStringPriorityQueue(PQ);
found = curr->pcb;
free(curr);
break;
}
last = curr;
curr = curr->next;
}
}
return found;
}
/*
* Checks if the provided priority queue is empty.
*
* Arguments: PQ: The Priority Queue to test.
* Return: 1 if the queue is empty, 0 otherwise.
*/
char pq_is_empty(PriorityQueue PQ) {
int i;
char ret_val = 1;
for (i = 0; i < NUM_PRIORITIES; i++) {
/* If a single queue isn't empty, the priority queue isn't empty. */
if (q_is_empty(PQ->queues[i]) == 0) {
ret_val = 0;
break;
}
}
return ret_val;
}
/*
* Peeks at the top value from the provided priority queue.
*
* Arguments: PQ: The Priority Queue to peek at.
* Return: The highest priority proccess in the queue, NULL if none exists.
*/
PCB pq_peek(PriorityQueue PQ) {
PCB pcb = NULL;
int i = 0;
if (!pq_is_empty(PQ)) {
while (i < NUM_PRIORITIES) {
if (!q_is_empty(PQ->queues[i])) {
pcb = q_peek(PQ->queues[i]);
break;
} else {
i++;
}
}
}
return pcb;
}
/*
* Creates a string representation of the provided priority queue, and returns it.
*
* Arguments: PQ: the Priority Queue to create a string representation of.
*/
void toStringPriorityQueue(PriorityQueue PQ) {
printf("\r\n");
for (int i = 0; i < NUM_PRIORITIES; i++) {
//printf("Q%2d: Count=%d, QuantumSize=%d\r\n", i, PQ->queues[i]->size, PQ->queues[i]->quantum_size);
printf("Q%2d: ", i);
toStringReadyQueue(PQ->queues[i]);
}
printf("\r\n");
}