In an operating system, CPU scheduling is the process of determining which process in the ready queue is to be allocated to the CPU for execution. The goal is to make the system efficient, fast, and fair. This calculator helps you visualize and compare different CPU scheduling algorithms.
Key Concepts
Process: A program in execution.
Arrival Time (AT): The time at which a process enters the ready queue.
Burst Time (BT): The amount of CPU time a process requires for execution.
Completion Time (CT): The time at which a process finishes its execution.
Turnaround Time (TAT): The total time a process spends in the system. Formula: TAT = CT - AT.
Waiting Time (WT): The total time a process spends waiting in the ready queue. Formula: WT = TAT - BT.
Time Quantum: A small, fixed unit of time allocated to a process in Round Robin scheduling.
Scheduling Algorithms Explained
This calculator implements four common non-preemptive and preemptive scheduling algorithms:
First-Come, First-Served (FCFS): The simplest scheduling algorithm. Processes are executed in the order they arrive. It's non-preemptive, meaning once a process starts, it runs to completion.
Shortest Job First (SJF): This non-preemptive algorithm selects the process with the smallest burst time from the ready queue. It's optimal for minimizing the average waiting time but requires knowing burst times in advance.
Priority (Non-Preemptive): Each process is assigned a priority. The process with the highest priority (represented by the lowest priority number) is executed next.
Round Robin (RR): A preemptive algorithm designed for time-sharing systems. Each process is given a small time slice (time quantum) to execute. If it doesn't finish, it's moved to the back of the ready queue.
How to Use the Calculator
1. Enter the Arrival Time and Burst Time for each process in the table below. For Priority scheduling, also enter a priority number (a lower number means higher priority).
2. Use the "Add Process" button to add more processes or the "Remove" button to delete them.
3. Select the desired scheduling algorithm from the dropdown menu.
4. If you choose Round Robin, specify a Time Quantum.
5. Click "Calculate" to see the results, including a Gantt chart visualizing the execution, a detailed results table, and the average turnaround and waiting times.
Process Input
Process ID
Arrival Time
Burst Time
Priority
Action
P1
P2
P3
P4
First-Come, First-Served (FCFS)
Shortest Job First (SJF)
Priority (Non-Preemptive)
Round Robin (RR)
Results
Gantt Chart
Process Details
Process ID
Arrival Time
Burst Time
Priority
Completion Time
Turnaround Time
Waiting Time
var processCounter = 4;
function addProcessRow() {
processCounter++;
var tableBody = document.getElementById('processTbody');
var newRow = tableBody.insertRow();
newRow.innerHTML = '
P' + processCounter + '
' +
'
' +
'
' +
'
' +
'
';
togglePriorityColumn();
}
function removeProcessRow(button) {
var row = button.parentNode.parentNode;
if (document.getElementById('processTbody').rows.length > 1) {
row.parentNode.removeChild(row);
updateProcessIds();
} else {
alert("At least one process is required.");
}
}
function updateProcessIds() {
var tableBody = document.getElementById('processTbody');
var rows = tableBody.rows;
for (var i = 0; i < rows.length; i++) {
rows[i].cells[0].innerText = 'P' + (i + 1);
}
processCounter = rows.length;
}
function togglePriorityColumn() {
var algorithm = document.getElementById('algorithm').value;
var priorityCols = document.getElementsByClassName('priority-col');
var priorityResultCol = document.getElementsByClassName('priority-col-result')[0];
var timeQuantumGroup = document.getElementById('timeQuantumGroup');
var displayStyle = 'none';
if (algorithm === 'priority') {
displayStyle = 'table-cell';
}
for (var i = 0; i < priorityCols.length; i++) {
priorityCols[i].style.display = displayStyle;
}
if(priorityResultCol) priorityResultCol.style.display = displayStyle;
if (algorithm === 'rr') {
timeQuantumGroup.style.display = 'block';
} else {
timeQuantumGroup.style.display = 'none';
}
}
window.onload = function() {
togglePriorityColumn();
};
function getProcesses() {
var processes = [];
var tableBody = document.getElementById('processTbody');
var rows = tableBody.rows;
var errorMsg = document.getElementById('error-message');
errorMsg.innerHTML = '';
for (var i = 0; i < rows.length; i++) {
var cells = rows[i].cells;
var at = parseInt(cells[1].getElementsByTagName('input')[0].value);
var bt = parseInt(cells[2].getElementsByTagName('input')[0].value);
var priority = parseInt(cells[3].getElementsByTagName('input')[0].value);
if (isNaN(at) || at < 0 || isNaN(bt) || bt <= 0 || isNaN(priority) || priority < 0) {
errorMsg.innerHTML = 'Please enter valid, non-negative numbers for all fields. Burst Time must be greater than 0.';
return null;
}
processes.push({
id: 'P' + (i + 1),
at: at,
bt: bt,
priority: priority,
original_bt: bt,
isCompleted: false
});
}
return processes;
}
function calculate() {
var processes = getProcesses();
if (!processes) return;
var algorithm = document.getElementById('algorithm').value;
var results;
// Deep copy processes for each algorithm to not mutate the original
var processesCopy = JSON.parse(JSON.stringify(processes));
switch (algorithm) {
case 'fcfs':
results = calculateFCFS(processesCopy);
break;
case 'sjf':
results = calculateSJF(processesCopy);
break;
case 'priority':
results = calculatePriority(processesCopy);
break;
case 'rr':
var timeQuantum = parseInt(document.getElementById('timeQuantum').value);
if (isNaN(timeQuantum) || timeQuantum 0).';
return;
}
results = calculateRR(processesCopy, timeQuantum);
break;
}
displayResults(results.finalProcesses, results.ganttChart);
}
function calculateFCFS(processes) {
processes.sort(function(a, b) { return a.at – b.at; });
var currentTime = 0;
var ganttChart = [];
for (var i = 0; i < processes.length; i++) {
var p = processes[i];
if (currentTime < p.at) {
ganttChart.push({ id: 'Idle', start: currentTime, end: p.at });
currentTime = p.at;
}
p.ct = currentTime + p.bt;
p.tat = p.ct – p.at;
p.wt = p.tat – p.bt;
ganttChart.push({ id: p.id, start: currentTime, end: p.ct });
currentTime = p.ct;
}
return { finalProcesses: processes, ganttChart: ganttChart };
}
function calculateSJF(processes) {
var n = processes.length;
var completed = 0;
var currentTime = 0;
var ganttChart = [];
while (completed < n) {
var readyQueue = [];
for (var i = 0; i < n; i++) {
if (processes[i].at <= currentTime && !processes[i].isCompleted) {
readyQueue.push(processes[i]);
}
}
if (readyQueue.length === 0) {
var nextArrivalTime = Infinity;
for (var i = 0; i < n; i++) {
if (!processes[i].isCompleted) {
nextArrivalTime = Math.min(nextArrivalTime, processes[i].at);
}
}
if (nextArrivalTime !== Infinity) {
ganttChart.push({ id: 'Idle', start: currentTime, end: nextArrivalTime });
currentTime = nextArrivalTime;
} else {
break; // All processes accounted for
}
continue;
}
readyQueue.sort(function(a, b) { return a.bt – b.bt; });
var currentProcess = readyQueue[0];
currentProcess.ct = currentTime + currentProcess.bt;
currentProcess.tat = currentProcess.ct – currentProcess.at;
currentProcess.wt = currentProcess.tat – currentProcess.bt;
currentProcess.isCompleted = true;
ganttChart.push({ id: currentProcess.id, start: currentTime, end: currentProcess.ct });
currentTime = currentProcess.ct;
completed++;
}
return { finalProcesses: processes, ganttChart: ganttChart };
}
function calculatePriority(processes) {
var n = processes.length;
var completed = 0;
var currentTime = 0;
var ganttChart = [];
while (completed < n) {
var readyQueue = [];
for (var i = 0; i < n; i++) {
if (processes[i].at <= currentTime && !processes[i].isCompleted) {
readyQueue.push(processes[i]);
}
}
if (readyQueue.length === 0) {
var nextArrivalTime = Infinity;
for (var i = 0; i < n; i++) {
if (!processes[i].isCompleted) {
nextArrivalTime = Math.min(nextArrivalTime, processes[i].at);
}
}
if (nextArrivalTime !== Infinity) {
ganttChart.push({ id: 'Idle', start: currentTime, end: nextArrivalTime });
currentTime = nextArrivalTime;
} else {
break;
}
continue;
}
readyQueue.sort(function(a, b) { return a.priority – b.priority; });
var currentProcess = readyQueue[0];
currentProcess.ct = currentTime + currentProcess.bt;
currentProcess.tat = currentProcess.ct – currentProcess.at;
currentProcess.wt = currentProcess.tat – currentProcess.bt;
currentProcess.isCompleted = true;
ganttChart.push({ id: currentProcess.id, start: currentTime, end: currentProcess.ct });
currentTime = currentProcess.ct;
completed++;
}
return { finalProcesses: processes, ganttChart: ganttChart };
}
function calculateRR(processes, timeQuantum) {
processes.sort(function(a, b) { return a.at – b.at; });
var n = processes.length;
var readyQueue = [];
var currentTime = 0;
var completed = 0;
var ganttChart = [];
var processIndex = 0;
for (var i = 0; i < n; i++) {
processes[i].remaining_bt = processes[i].bt;
}
while (completed < n) {
while (processIndex < n && processes[processIndex].at <= currentTime) {
readyQueue.push(processes[processIndex]);
processIndex++;
}
if (readyQueue.length === 0) {
if (processIndex < n) {
ganttChart.push({ id: 'Idle', start: currentTime, end: processes[processIndex].at });
currentTime = processes[processIndex].at;
} else {
break;
}
continue;
}
var currentProcess = readyQueue.shift();
var execTime = Math.min(timeQuantum, currentProcess.remaining_bt);
var startTime = currentTime;
currentTime += execTime;
currentProcess.remaining_bt -= execTime;
ganttChart.push({ id: currentProcess.id, start: startTime, end: currentTime });
while (processIndex < n && processes[processIndex].at 0) {
readyQueue.push(currentProcess);
} else {
currentProcess.ct = currentTime;
currentProcess.tat = currentProcess.ct – currentProcess.at;
currentProcess.wt = currentProcess.tat – currentProcess.original_bt;
currentProcess.isCompleted = true;
completed++;
}
}
return { finalProcesses: processes, ganttChart: ganttChart };
}
function displayResults(finalProcesses, ganttChart) {
document.getElementById('results-section').style.display = 'block';
var resultsTbody = document.getElementById('resultsTbody');
resultsTbody.innerHTML = ";
var totalTAT = 0;
var totalWT = 0;
finalProcesses.sort(function(a, b) {
return parseInt(a.id.substring(1)) – parseInt(b.id.substring(1));
});
for (var i = 0; i < finalProcesses.length; i++) {
var p = finalProcesses[i];
var newRow = resultsTbody.insertRow();
newRow.innerHTML = '