Contents

Round Robin in OS

Introduction

Round Robin (RR) is a preemptive CPU scheduling algorithm that gives each process a fixed time slice (time quantum) in a cyclic order. It ensures fair CPU allocation and is ideal for time-sharing systems. Think of it like a multiplayer board game – every player (process) gets an equal turn, no matter how long their task takes!

Key Characteristics

  • Preemptive: The CPU can be taken away from a process.
  • Time Quantum (TQ): Fixed time each process can run before being rotated.
  • Circular Ready Queue: Processes are requeued if unfinished.
  • No Starvation: All processes eventually get their turn.

Problem Statement

Calculate the Average Waiting Time and Average Turnaround Time using Round Robin for the following processes with time quantum = 2 units.

ProcessArrival TimeBurst Time
P106
P203
P304

Time Quantum = 2

Step-by-Step Simulation

We’ll simulate each time unit, tracking:

  • The ready queue
  • The currently running process
  • Updates to burst time and completed processes

Initial Setup

  • Time = 0
  • Ready Queue = [P1, P2, P3] (All arrived at time 0 and we will push based on Arrival Time)

Cycle 1: Time 0 to 2

  • P1 is dequeued and runs for 2 units
  • Remaining Burst Time: P1 = 4
  • P1 is requeued
  • 🔁 Queue = [P2, P3, P1]

Cycle 2: Time 2 to 4

  • P2 runs for 2 units → Remaining = 1
  • P2 is requeued
  • 🔁 Queue = [P3, P1, P2]

Cycle 3: Time 4 to 6

  • P3 runs for 2 units → Remaining = 2
  • P3 is requeued
  • 🔁 Queue = [P1, P2, P3]

Cycle 4: Time 6 to 8

  • P1 runs again → Remaining = 2
  • P1 is requeued
  • 🔁 Queue = [P2, P3, P1]

Cycle 5: Time 8 to 9

  • P2 runs for 1 unit and finishes!
  • Completion Time of P2 = 9
  • ✅ P2 exits
  • 🔁 Queue = [P3, P1]

Cycle 6: Time 9 to 11

  • P3 runs for 2 units and finishes!
  • Completion Time of P3 = 11
  • ✅ P3 exits
  • 🔁 Queue = [P1]

Cycle 7: Time 11 to 13

  • P1 runs final 2 units and finishes!
  • Completion Time of P1 = 13
  • ✅ P1 exits
  • 🔁 Queue = []

Final Completion Times

ProcessCompletion Time
P113
P29
P311

Turnaround Time = Completion - Arrival

ProcessTurnaround Time
P113 - 0 = 13
P29 - 0 = 9
P311 - 0 = 11

Average Turnaround Time = (13 + 9 + 11) / 3 = 11.0

Waiting Time = Turnaround - Burst

ProcessWaiting Time
P113 - 6 = 7
P29 - 3 = 6
P311 - 4 = 7

Average Waiting Time = (7 + 6 + 7) / 3 = 6.67

Gantt Chart Representation

0──2──4──6──8──9──11──13
|P1|P2|P3|P1|P2|P3 |P1 |

C Implementation of Round Robin Algorithm

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

struct Process {
    int pid;
    int arrival;
    int burst;
    int remaining;
    int completion;
    int turnaround;
    int waiting;
    int started;
};

void enqueue(int queue[], int *rear, int value) {
    queue[++(*rear)] = value;
}

int dequeue(int queue[], int *front, int *rear) {
    if (*front > *rear) return -1;
    return queue[(*front)++];
}

int isInQueue(int queue[], int front, int rear, int pid) {
    for (int i = front; i <= rear; i++) {
        if (queue[i] == pid) return 1;
    }
    return 0;
}

int main() {
    int n, timeQuantum;
    printf("Enter number of processes: ");
    scanf("%d", &n);

    struct Process p[n];
    for (int i = 0; i < n; i++) {
        p[i].pid = i + 1;
        printf("Enter Arrival Time and Burst Time for P%d: ", p[i].pid);
        scanf("%d %d", &p[i].arrival, &p[i].burst);
        p[i].remaining = p[i].burst;
        p[i].started = 0;
    }

    printf("Enter Time Quantum: ");
    scanf("%d", &timeQuantum);

    int queue[MAX], front = 0, rear = -1;
    int time = 0, completed = 0;
    int gantt[100], ganttCount = 0;

    // Enqueue initially available processes
    for (int i = 0; i < n; i++) {
        if (p[i].arrival == time) {
            enqueue(queue, &rear, i);
            p[i].started = 1;
        }
    }

    while (completed < n) {
        if (front > rear) {
            time++;
            // Check for new arrivals
            for (int i = 0; i < n; i++) {
                if (p[i].arrival <= time && !p[i].started) {
                    enqueue(queue, &rear, i);
                    p[i].started = 1;
                }
            }
            continue;
        }

        int i = dequeue(queue, &front, &rear);

        int runTime = (p[i].remaining < timeQuantum) ? p[i].remaining : timeQuantum;
        printf("\n🟢 Time %d-%d: P%d running", time, time + runTime, p[i].pid);
        gantt[ganttCount++] = p[i].pid;

        time += runTime;
        p[i].remaining -= runTime;

        // Check for new arrivals during this time slice
        for (int j = 0; j < n; j++) {
            if (p[j].arrival > (time - runTime) && p[j].arrival <= time && !p[j].started) {
                enqueue(queue, &rear, j);
                p[j].started = 1;
            }
        }

        if (p[i].remaining == 0) {
            p[i].completion = time;
            p[i].turnaround = p[i].completion - p[i].arrival;
            p[i].waiting = p[i].turnaround - p[i].burst;
            completed++;
            printf(" (Completed ✅)");
        } else {
            enqueue(queue, &rear, i);  // not done, requeue
            printf(" (Requeued 🔁)");
        }

        // Print Ready Queue state
        printf("\n📥 Ready Queue: [");
        for (int k = front; k <= rear; k++) {
            printf("P%d", p[queue[k]].pid);
            if (k != rear) printf(" ");
        }
        printf("]");
    }

    // Final process table
    float totalTAT = 0, totalWT = 0;
    printf("\n\n📊 Final Table:\n");
    printf("PID  Arrival  Burst  Completion  Turnaround  Waiting\n");
    for (int i = 0; i < n; i++) {
        printf("P%-4d%-9d%-7d%-12d%-11d%-7d\n", p[i].pid, p[i].arrival, p[i].burst,
               p[i].completion, p[i].turnaround, p[i].waiting);
        totalTAT += p[i].turnaround;
        totalWT += p[i].waiting;
    }

    printf("\n🔁 Gantt Chart (Timeline):\n| ");
    for (int i = 0; i < ganttCount; i++) {
        printf("P%d | ", gantt[i]);
    }
    printf("\n");

    printf("\n📈 Average Turnaround Time: %.2f", totalTAT / n);
    printf("\n📉 Average Waiting Time   : %.2f\n", totalWT / n);

    return 0;
}

Sample Output

Enter number of processes: 3
Enter Arrival Time and Burst Time for P1: 0 6
Enter Arrival Time and Burst Time for P2: 0 3
Enter Arrival Time and Burst Time for P3: 0 4
Enter Time Quantum: 2

🟢 Time 0-2: P1 running (Requeued 🔁)
📥 Ready Queue: [P2 P3 P1]
🟢 Time 2-4: P2 running (Requeued 🔁)
📥 Ready Queue: [P3 P1 P2]
🟢 Time 4-6: P3 running (Requeued 🔁)
📥 Ready Queue: [P1 P2 P3]
🟢 Time 6-8: P1 running (Requeued 🔁)
📥 Ready Queue: [P2 P3 P1]
🟢 Time 8-9: P2 running (Completed ✅)
📥 Ready Queue: [P3 P1]
🟢 Time 9-11: P3 running (Completed ✅)
📥 Ready Queue: [P1]
🟢 Time 11-13: P1 running (Completed ✅)
📥 Ready Queue: []

📊 Final Table:
PID  Arrival  Burst  Completion  Turnaround  Waiting
P1   0        6      13          13         7
P2   0        3      9           9          6
P3   0        4      11          11         7

🔁 Gantt Chart (Timeline):
| P1 | P2 | P3 | P1 | P2 | P3 | P1 |

📈 Average Turnaround Time: 11.00
📉 Average Waiting Time   : 6.67
  0.00s user 0.00s system 0% cpu 7.176 total

Pros & Cons of Round Robin

Advantages

  • Equal CPU sharing → prevents starvation
  • Great for time-sharing systems
  • More responsive than FCFS

Disadvantages

  • Context switching overhead
  • Poor average turnaround for short jobs if quantum is large

When to Use Round Robin

  • OS-level CPU scheduling in multi-user systems
  • Interactive applications where fairness matters

FAQ

Q: Can I tune the time quantum?

Yes! Choose 10–100ms depending on the system load and context switch cost.

Q: What if new processes arrive during execution?

They’re placed at the end of the queue and get CPU in future rounds.

Q: Is Round Robin optimal?

No. It prioritizes fairness over turnaround or waiting time.