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 }