Find the Order of Execution of given N Processes in Round Robin Scheduling


In this article, you will learn about how to find the order of execution for the given N processes in the Round Robin Scheduling algorithm. But before starting with the code, let’s understand a bit about how this algorithm works.

Round Robin Scheduling is a popular CPU scheduling algorithm used in operating systems to allocate CPU time to multiple processes in a fair and efficient manner. In this blog, we will explore how round−robin scheduling works, its advantages and disadvantages, and provide an example to help you understand the concept better.

What is Round Robin Scheduling?

Round Robin Scheduling is a preemptive scheduling algorithm where each process is given a fixed time slice or quantum to execute. The CPU scheduler allocates the CPU time to the processes in a circular order, hence the name 'round robin.' Once a process has used up its time slice, it is preempted and added to the end of the ready queue. The next process in the queue is then allocated the CPU for its time slice.

The time slice or quantum for each process is generally small, typically between 10 to 100 milliseconds. The advantage of a small time slice is that each process gets a fair amount of CPU time, and the CPU is utilized efficiently by switching between processes frequently.

Scenario

To understand how Round Robin Scheduling works, let's consider an example. Suppose we have four processes that need to be executed:

  • Process 1: Requires 6 units of CPU time

  • Process 2: Requires 4 units of CPU time

  • Process 3: Requires 2 units of CPU time

  • Process 4: Requires 8 units of CPU time

We'll assume that the time quantum for the Round Robin Scheduling algorithm is set to 3 units of time. At the start of the scheduling process, all four processes are added to the ready queue in the order they arrived:

Ready queue: [Process 1, Process 2, Process 3, Process 4]

The scheduling algorithm then begins executing the processes in a cyclic manner, giving each process a time quantum of 3 units:

  • Time 0: Process 1 starts executing (requires 3 units of CPU time)

  • Time 3: Process 2 starts executing (requires 3 units of CPU time)

  • Time 6: Process 3 starts executing (requires 2 units of CPU time)

  • Time 8: Process 1 resumes execution (requires 3 units of CPU time)

  • Time 11: Process 4 starts executing (requires 3 units of CPU time)

  • Time 14: Process 2 resumes execution (requires 1 unit of CPU time)

  • Time 15: Process 1 finishes executing

  • Time 15: Process 3 resumes execution (requires 1 unit of CPU time)

  • Time 16: Process 2 finishes executing

  • Time 16: Process 4 resumes execution (requires 3 units of CPU time)

  • Time 19: Process 3 finishes executing

  • Time 19: Process 4 resumes execution (requires 2 units of CPU time)

  • Time 21: Process 4 finishes executing

Process Queue: P1 P2 P3 P1 P4 P2 P1 P3 P2 P4 P3 P4 P4

As you can see from the example, each process is given a time quantum of 3 units, regardless of how much CPU time it requires to complete. Once a process has completed its time quantum, it is pre−empted and moved to the end of the ready queue, where it waits until it is its turn to execute again.

Pseudocode

Let’s have a look into the pseudocode for implementing round−robin scheduling. Here we have created a function named round_robin() and variables like "waiting_time," "turnaround_time," "remaining," "current," "order_of_execution," and "ready_queue" are initialized by the function. Once all of the operations have been carried out, a loop is then started.

  • The function adds all of the processes that have arrived as of the current time to the ready queue throughout each iteration of the loop. The first process in the ready queue is then executed for the time quantum or until it is complete, whichever comes first.

  • If the process does not finish within the time quantum, it is added back to the ready queue. If it finishes, its waiting time and turnaround time are calculated.

  • After all the processes have been executed, the function calculates the average waiting time and turnaround time and returns the order of execution as an array.

function round_robin(processes, quantum):
   //Initialize variables
   n = length of processes
   waiting_time = an array of n elements, initialized to 0
   turnaround_time = an array of n elements, initialized to 0
   remaining_time = an array of n elements, initialized to the CPU burst time of each process
   current_time = 0
   order_of_execution = an empty array
   ready_queue = an empty array
   index = 0
   //Loop until all processes are executed
  while true:
   //Add all processes that have arrived at the current time to the ready queue
   for i from index to n-1:
      if processes[i].arrival_time <= current_time:
         add i to ready_queue
            increment index
        
      //Break the loop if all processes have been executed
        if the ready_queue is empty and the sum of remaining_time is 0:
            break
        
        // Execute the first process in the ready queue
        if the ready_queue is not empty:
            process_index = the first element in ready_queue
            remove the first element from ready_queue
            add process_index to order_of_execution
            if remaining_time[process_index] > quantum:
                increment current_time by quantum
                decrement remaining_time[process_index] by quantum
                add process_index to ready_queue
            else:
                increment current_time by remaining_time[process_index]
                set waiting_time[process_index] to current_time - processes[process_index].burst_time
                set remaining_time[process_index] to 0
                set turnaround_time[process_index] to current_time - processes[process_index].arrival_time
        else:
            increment current_time by 1
    
    // Calculate average waiting time and turnaround time
    avg_waiting_time = sum of waiting_time divided by n
    avg_turnaround_time = sum of turnaround_time divided by n
    
    // Return the order of execution and average waiting/turnaround time
    return order_of_execution, avg_waiting_time, avg_turnaround_time

Implementation

Here you can find the implementation of the above pseudocode in Python and Java

Python Example

def round_robin(processes, quantum):
    # Initialize variables
    n = len(processes)
    waiting_time = [0] * n
    turnaround_time = [0] * n
    remaining_time = [processes[i][1] for i in range(n)]
    current_time = 0
    order_of_execution = []
    ready_queue = []
    index = 0
   
    # Loop until all processes are executed
    while True:
        # Add all processes that have arrived at the current time to the ready queue
        for i in range(index, n):
            if processes[i][0] <= current_time:
                ready_queue.append(i)
                index += 1
       
        # Break the loop if all processes have been executed
        if not ready_queue and sum(remaining_time) == 0:
            break
       
        # Execute the first process in the ready queue
        if ready_queue:
            process_index = ready_queue.pop(0)
            order_of_execution.append(process_index)
            if remaining_time[process_index] > quantum:
                current_time += quantum
                remaining_time[process_index] -= quantum
                ready_queue.append(process_index)
            else:
                current_time += remaining_time[process_index]
                waiting_time[process_index] = current_time - processes[process_index][1]
                remaining_time[process_index] = 0
                turnaround_time[process_index] = current_time - processes[process_index][0]
        else:
            current_time += 1
   
    # Calculate average waiting time and turnaround time
    avg_waiting_time = sum(waiting_time) / n
    avg_turnaround_time = sum(turnaround_time) / n
   
    return order_of_execution, avg_waiting_time, avg_turnaround_time
processes = [(0, 5), (1, 3), (2, 8), (3, 6)]
time_quantum = 2
order_of_execution, avg_waiting_time, avg_turnaround_time = round_robin(processes, time_quantum)
print("Order of execution:", order_of_execution)
print("Average waiting time:", avg_waiting_time)
print("Average turnaround time:", avg_turnaround_time)

Output

This code will output the order of execution of the processes, along with the average waiting time and average turnaround time for the Round Robin Scheduling algorithm with the given time quantum. Note that this is just an example implementation and may need to be modified for different use cases or requirements.

Order of execution: [0, 0, 1, 2, 0, 3, 1, 2, 3, 2, 3, 2]
Average waiting time: 10.25
Average turnaround time: 14.25

Java Example

import java.util.*;
class Process {
    int pid; // process ID
    int arrival_time; // arrival time of process
    int burst_time; // CPU burst time of process
   
    Process(int pid, int arrival_time, int burst_time) {
        this.pid = pid;
        this.arrival_time = arrival_time;
        this.burst_time = burst_time;
    }
}
public class RoundRobinScheduling {
   //Driver method
    public static void main(String[] args) {
        Process[] processes = new Process[] {
            new Process(1, 0, 10),
            new Process(2, 3, 5),
            new Process(3, 5, 8),
            new Process(4, 6, 3),
            new Process(5, 8, 6)
        };       
        // Time quantum
        int quantum = 2;
       
        // Run Round Robin Scheduling algorithm
        int[] order_of_execution = round_robin(processes, quantum);
       
        // Print order of execution
        System.out.println("Order of Execution: " + Arrays.toString(order_of_execution));
    }
   //method to implement round-robin cpu scheduling
    public static int[] round_robin(Process[] processes, int quantum) {
        // Initialize variables
        int n = processes.length;
        int[] waiting_time = new int[n];
        int[] turnaround_time = new int[n];
        int[] remaining_time = new int[n];
        for (int i = 0; i < n; i++) {
            remaining_time[i] = processes[i].burst_time;
        }
        int current_time = 0;
        List<Integer> order_of_execution = new ArrayList<Integer>();
        Queue<Integer> ready_queue = new LinkedList<Integer>();
        int index = 0;
       
        // Loop until all processes are executed
        while (true) {
            // Add all processes that have arrived at the current time to the ready queue
            for (int i = index; i < n; i++) {
                if (processes[i].arrival_time <= current_time) {
                    ready_queue.add(i);
                    index++;
                }
            }
           
            // Break the loop if all processes have been executed
            if (ready_queue.isEmpty() && Arrays.stream(remaining_time).sum() == 0) {
                break;
            }
           
            // Execute the first process in the ready queue
            if (!ready_queue.isEmpty()) {
                int process_index = ready_queue.remove();
                order_of_execution.add(process_index);
                if (remaining_time[process_index] > quantum) {
                    current_time += quantum;
                    remaining_time[process_index] -= quantum;
                    ready_queue.add(process_index);
                } else {
                    current_time += remaining_time[process_index];
                    waiting_time[process_index] = current_time - processes[process_index].burst_time - processes[process_index].arrival_time;
                    remaining_time[process_index] = 0;
                    turnaround_time[process_index] = current_time - processes[process_index].arrival_time;
                }
            } else {
                current_time++;
            }
        }
       
        // Convert order of execution from list to array
        int[] order_of_execution_arr = new int[order_of_execution.size()];
        for (int i = 0; i < order_of_execution.size(); i++) {
            order_of_execution_arr[i] = order_of_execution.get(i);
        }
       
        // Print average waiting time and turnaround time
        float avg_waiting_time = Arrays.stream(waiting_time).sum() / (float) n;
        float avg_turnaround_time = Arrays.stream(turnaround_time).sum() / (float) n;
        System.out.println("Average Waiting Time: " + avg_waiting_time);
        System.out.println("Average Turnaround Time: " + avg_turnaround_time);
        // Return order of execution
        return order_of_execution_arr;
    }
}

Output

Average Waiting Time: 15.0
Average Turnaround Time: 21.4
Order of Execution: [0, 0, 0, 1, 0, 2, 3, 1, 4, 0, 2, 3, 1, 4, 2, 4, 2]

Conclusion

Round Robin Scheduling is a popular CPU scheduling algorithm used in operating systems to allocate CPU time to multiple processes in a fair and efficient manner. It is a preemptive scheduling algorithm where each process is given a fixed time slice or quantum to execute.

Round Robin Scheduling ensures that each process gets a fair share of CPU time and that the CPU is utilized efficiently by switching between processes frequently. However, Round Robin Scheduling can cause some overhead due to the frequent context switching between processes and may result in longer waiting times for some processes.

Updated on: 22-Aug-2023

213 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements