-
Notifications
You must be signed in to change notification settings - Fork 0
/
mqp.c
165 lines (148 loc) · 3.84 KB
/
mqp.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
/*
* Multilevel Queue Process implementation.
*
* Pedro Moreno Silva.
* Date: 14/03/2023
* contact: [email protected]
*/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include "main.h"
#include "mqp.h"
#include "pdeque.h"
#include "process.h"
#define AGING_INTERVAL 10 // as required in the
// project's description
/*
* Simulates the cpu function.
* It is used to pass processes to it as if
* the scheduler is assigning processes to the cpu
*/
Process in_cpu;
/*
* MQP implementation.
* Should not be modified directly to preserve the
* simulational aspects. Can be passed as parameter.
*/
Pdeque mqp[NUMBER_OF_PRIORITY_LEVELS];
/*
* Prints the current process stored in in_cpu variable.
*
* Params: None
* Return: None
*/
void print_running_now() {
printf("Running in cpu: ");
print_proc(in_cpu);
}
/*
* Prints the internal state of MQP. Param should ideally be the
* global variable mqp.
*
* Params: a MQP
* Return: None
*/
void print_mqp(Pdeque mqp[]) {
for (int i = 0; i < NUMBER_OF_PRIORITY_LEVELS; i++)
{
print_pdeque(mqp[i]);
printf("\n");
}
}
/*
* Checks if all the queues in the MQP are empty.
* Param should ideally be the global variable mqp.
*
* Params: a MQP
* Return: 1 if MQP all MQP queues are empty, 0 otherwise
*/
int is_all_empty(Pdeque mqp[]) {
int is_all_empty = 1;
for (int i = 0; i < NUMBER_OF_PRIORITY_LEVELS; i++)
{
is_all_empty = is_all_empty && is_empty(mqp[i]);
}
return is_all_empty;
}
/*
* Process reception part of pipeline.
* Distributes the processes in the MQP based on their
* priorities. Uses SJF as tie breaker.
*
* Params: an array of Process, the array length, the MQP to
* distribute the processes
* Return: None
*/
void receive_procs(Process procs[], int procs_len, Pdeque mqp[]) {
// SJF policy
insertion_sort_by_cpu_burst(procs, procs_len); // overkill solution
for (int i = 0; i < procs_len; i++)
{
add_to_end(mqp[procs[i].priority], procs[i]);
}
}
/*
* Dinamically allocates the Pqueue for each level in the
* mqp global variable.
*
* Params: None
* Return: None
*/
void initialize_mqp() {
for (int i = 0; i < NUMBER_OF_PRIORITY_LEVELS; i++)
{
mqp[i] = create_empty_pdeque(i);
}
}
/*
* Frees the dinamically allocated Pqueue in each level in the
* mqp global variable.
*
* Params: None
* Return: None
*/
void free_mqp() {
for (int i = 0; i < NUMBER_OF_PRIORITY_LEVELS; i++)
{
free_pdeque(mqp[i]);
}
}
/*
* Threaded function to implement the aging policy in the MQP.
* Every 10 seconds, the lowest priority processes is assigned
* to the queue one level higher.
*
* Params: None
* Return: None
*/
void *aging() {
int is_mqp_empty;
while (1) {
// Every operation over mqp is a critical section
// thus it needs to be locked and unlock by mutex
pthread_mutex_lock(m);
is_mqp_empty = is_all_empty(mqp);
pthread_mutex_unlock(m);
if (is_mqp_empty) { break; }
sleep(AGING_INTERVAL);
for (int i = NUMBER_OF_PRIORITY_LEVELS - 1; i > 0; i--) {
pthread_mutex_lock(m);
if (!(is_empty(mqp[i])))
{
Process p = remove_from_end(mqp[i]); // lowest priority process
printf("\n*******\nPromoted ");
print_proc(p);
printf("*******\n");
p.priority--; // decrements priority = ups a level in mqp
add_to_end(mqp[i - 1], p); // sent to corresponding queue
pthread_mutex_unlock(m);
break; // start again from the lowest priority queue
} else {
pthread_mutex_unlock(m);
}
}
}
printf("exited thread\n");
pthread_exit(NULL);
}