jsos
college code for operating system fundamentals in js
git clone https://9o.is/git/jsos.git
scheduler.js
(7049B)
1 /*
2 * CPU scheduler module in the client OS using Round Robin
3 * (RR) scheduling with the user specified
4 * (or default) quantum.
5 */
6 function scheduler() {
7
8 /*
9 * Keeps count of the current running process's quantum.
10 */
11 this.quantumCount = 0;
12
13 /*
14 * Process currently running.
15 */
16 this.running = undefined;
17
18 /*
19 * History of all the processes that have been scheduled.
20 */
21 this.history = [];
22
23 /* The amount of clock pulses when the CPU was executing. */
24 this.busyTime = 0;
25
26 this.run = function() {
27 this.busyTime++;
28
29 // if ready queue is not empty, dequeue
30 if(this.processTerminated()) {
31
32 if(this.running != undefined)
33 this.addHistory(this.running);
34
35 var p = _KernelReadyQueue.pop();
36 while(p.state == PCB_STATE_TERMINATED) {
37 this.addHistory(p);
38 p = _KernelReadyQueue.pop();
39 }
40
41 // is it in disk & not memory
42 if(p.tsb != undefined) {
43 krnTrace("Rolling in "+p.PID+" by swapping.");
44 _KernelMemoryManager.rollIn(p);
45 }
46
47 this.setRunningProcess(p);
48 krnTrace("Adding PID "+p.PID+" by context switch.");
49 }
50
51 _CPU.cycle();
52
53 // update current changes in the PCB registry
54 this.running.updateRegisters(
55 _CPU.PC, _CPU.ACC, _CPU.X, _CPU.Y, _CPU.Z);
56
57 if(CPU_STATE_RR.name == CPU_STATE)
58 this.updateQuantumCount();
59 }
60
61 /*
62 * Sets a process as the currently executing process
63 * transfers PCB registers to the CPU.
64 */
65 this.setRunningProcess = function(process) {
66 this.running = process;
67 process.setState(PCB_STATE_RUNNING);
68 _CPU.PC = process.PC;
69 _CPU.ACC = process.ACC;
70 _CPU.X = process.X;
71 _CPU.Y = process.Y;
72 _CPU.Z = process.Z;
73 }
74
75 /*
76 * Checks if the running process is done or empty.
77 */
78 this.processTerminated = function() {
79 return this.running == undefined ||
80 this.running.state == PCB_STATE_TERMINATED;
81 }
82
83 /*
84 * Whether the scheduler is ready to run.
85 */
86 this.ready = function() {
87 this.output();
88 return (!this.processTerminated() || _KernelReadyQueue.size() > 0);
89 }
90
91 /*
92 * Updates quantum count and does a context switch system
93 * call if time is over.
94 */
95 this.updateQuantumCount = function() {
96 if(++this.quantumCount % RR_QUANTUM == 0) {
97 this.quantumCount = 0;
98 krnInterrupt(SYSCALL_IRQ, 0xFFFF);
99 }
100 }
101
102 /*
103 * CPU Utilization
104 */
105 this.utilization = function() {
106 var n = this.busyTime / _OSclock;
107 return Math.round(n*100);
108 }
109
110 /*
111 * CPU Throughput
112 */
113 this.throughput = function() {
114 var n = 0;
115 if(this.busyTime > 0)
116 n = this.history.length / this.busyTime;
117 return Math.round(n*100);
118 }
119
120 /*
121 * Avg Turnaround
122 * TODO
123 */
124 this.turnAround = function() {
125 var total = 0;
126 var length = this.history.length;
127 for(i=0; i<length; i++) {
128 var p = this.history[i];
129 total += (p.end - p.arrival);
130 }
131
132 if(length > 0)
133 return Math.round(total / length);
134 return 0;
135 }
136
137 /*
138 * Avg Wait
139 * TODO
140 */
141 this.wait = function() {
142 var total = 0;
143 var length = this.history.length;
144 for(i=0; i<length; i++) {
145 var p = this.history[i];
146 total += (p.end - p.arrival - p.bursts);
147 }
148
149 if(length > 0)
150 return Math.round(total / length);
151 return 0;
152 }
153
154 this.addHistory = function(p) {
155 this.history.push({
156 pid: p.PID,
157 arrival: p.arrival,
158 end: p.end,
159 bursts: p.bursts
160 });
161 }
162
163 //TODO: would prefer to measure portion of performance
164 // instead of the whole OSclock since the OS is mostly
165 // always idle.
166 this.output = function() {
167 var utilization = this.utilization();
168 var throughput = this.throughput();
169 var turnAround = this.turnAround();
170 var wait = this.wait();
171
172
173 /*---------------------------
174 Display CPU Numbers
175 -------------------------*/
176 document.getElementById("cpuUtilization").innerHTML =
177 "Utilization: "+utilization+"%";
178
179 document.getElementById("cpuThroughput").innerHTML =
180 "Throughput: "+throughput+"%";
181
182 document.getElementById("cpuTurnaround").innerHTML =
183 "Turn Around: "+turnAround;
184
185 document.getElementById("cpuWait").innerHTML =
186 "Wait: "+wait;
187
188
189 /* A live monitor graph.*/
190 function graph(id, color, value, valueSign, highestValue) {
191 var canvas = document.getElementById(id);
192 var context = canvas.getContext('2d');
193
194 var beginX = 20;
195 var marginY = 12;
196 var height = canvas.height - marginY;
197 var width = canvas.width - beginX;
198
199 // vertical axis line
200 context.beginPath();
201 context.strokeStyle = "#000";
202 context.moveTo(beginX, 0);
203 context.lineTo(beginX, height);
204 context.stroke();
205 // horizontal axis line
206 context.moveTo(beginX, height);
207 context.lineTo(canvas.width, height);
208 context.stroke();
209
210 // draw x & y axis text
211 var fontSize = 12;
212 context.font= fontSize+"px Times";
213 context.fillText(highestValue.toString(), 1, fontSize);
214 context.fillText(valueSign, 1, canvas.height/2);
215 context.fillText("0", 1, canvas.height - marginY);
216 context.fillText("0", beginX, canvas.height);
217 context.fillText("ticks", canvas.width/2, canvas.height);
218
219 // highest tick is width (10 ticks per pixels)
220 context.fillText(width, canvas.width - beginX, canvas.height);
221
222 // new line height for this tick
223 var h = (height * (highestValue-value))/highestValue;
224
225 // shift graph to the right by a little
226 context.strokeStyle = color;
227 var saved_rect = context.getImageData(beginX+1, 0, width, height-1);
228 context.clearRect(beginX+1, 0, width, height-1);
229 context.putImageData(saved_rect, beginX+2, 0);
230
231 // add the new line
232 context.moveTo(beginX+2, height-1);
233 context.lineTo(beginX+2, h);
234 context.stroke();
235 }
236
237
238
239
240 /*----------------------------
241 CPU Utilization Bar
242 ----------------------------*/
243 var canvas = document.getElementById('cpuUtilizationBar');
244 var context = canvas.getContext('2d');
245
246 context.fillStyle = '#8ED6FF';
247 context.fillRect(0, 0, canvas.width, canvas.height);
248
249 context.fillStyle = '#ffb78e';
250 context.fillRect(0, 0, (canvas.width * utilization)/100, canvas.height);
251
252
253 /*----------------------------
254 CPU Throughput Bar
255 ----------------------------*/
256 canvas = document.getElementById('cpuThroughputBar');
257 context = canvas.getContext('2d');
258
259 context.fillStyle = '#8ED6FF';
260 context.fillRect(0, 0, canvas.width, canvas.height);
261
262 context.fillStyle = '#ffb78e';
263 context.fillRect(0, 0, (canvas.width * throughput)/100, canvas.height);
264
265
266 graph("cpuUtilizationGraph", "red", utilization, "%", 100);
267 graph("cpuThroughputGraph", "green", throughput, "%", 100);
268 graph("cpuWaitGraph", "orange", wait, "", 200);
269 graph("cpuTurnaroundGraph", "blue", turnAround, "", 300);
270 }
271 }