-
Notifications
You must be signed in to change notification settings - Fork 3
/
Scheduler.java
140 lines (123 loc) · 4.04 KB
/
Scheduler.java
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
/**
* @author Mark Dunne
*/
public class Scheduler {
public static final int PRIORITY_LEVELS = 3;
private final Queue blockedQueue;
private final Queue[] runningQueues;
private long clock;
/**
* The types of interrupt that can happen
*/
public static enum Interrupt {
PROCESS_BLOCKED,
PROCESS_READY,
LOWER_PRIORITY
}
public Scheduler() {
//create new blocked queue
blockedQueue = new Queue(this, 50, 0, Queue.QueueType.BLOCKED_QUEUE);
//create the cpu queues
runningQueues = new Queue[PRIORITY_LEVELS];
for (int i = 0; i < PRIORITY_LEVELS; i++) {
runningQueues[i] = new Queue(this, 10 + i * 20, i, Queue.QueueType.CPU_QUEUE);
}
clock = System.currentTimeMillis();
}
/**
* The main loop of the scheduler
* Each process is worked on for a time based on
* the time between loops to be more realistic
*/
public void run() {
while (true) {
long time = System.currentTimeMillis();
long workTime = time - clock;
clock = time;
//work through blocked and cpu processes in parallel
//pass some time on the blocked processes
if (!blockedQueue.isEmpty()) {
blockedQueue.doBlockedWork(workTime);
}
//do cpu work
for (int i = 0; i < PRIORITY_LEVELS; i++) {
Queue queue = runningQueues[i];
if (!queue.isEmpty()) {
queue.doCPUWork(workTime);
break;
}
}
//if no processes left, simulate idle mode
if (allEmpty()) {
System.out.println("Idle mode");
break;
} else {
System.out.println(this);
}
//slow the program down for output to be more readable
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Determine if any processes left
*
* @return returns true if there isn't anything left to do
*/
public boolean allEmpty() {
for (Queue queue : runningQueues) {
if (!queue.isEmpty()) {
return false;
}
}
return blockedQueue.isEmpty();
}
/**
* Add new process to be scheduled
*
* @param process The process to be added
*/
public void add(Process process) {
runningQueues[0].add(process);
}
/**
* Notify the scheduler of an Interrupt that needs its attention
* Used to move processes between different queses and priority levels
*
* @param queue The source queue
* @param process The source process
* @param interrupt The interrupt type that happened
*/
public void event(Queue queue, Process process, Interrupt interrupt) {
switch (interrupt) {
case PROCESS_BLOCKED:
blockedQueue.add(process);
break;
case PROCESS_READY:
add(process);
break;
case LOWER_PRIORITY:
if (queue.getType() == Queue.QueueType.CPU_QUEUE) {
//move process to back of next lowest priority queue
//if it is already in the lowest, just add it to the back
int priorityLevel = Math.min(PRIORITY_LEVELS - 1, queue.getPriorityLevel() + 1);
runningQueues[priorityLevel].add(process);
} else {
//just add process to back of blocking queue
blockedQueue.add(process);
}
break;
}
}
@Override
public String toString() {
String result = "[BlockedQueue Size:" + blockedQueue.size() + "]";
for (Queue runningQueue : runningQueues) {
result += "[CPUQueue Size: " + runningQueue.size() + "]";
}
return result;
}
}