Real-Time OS (RTOS)

[!NOTE] This module explores the core principles of Real-Time OS (RTOS), deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.

1. Determinism Over Throughput

In a standard OS (Windows, Linux), the goal is Throughput: Get as much work done as possible. If a video frame drops, it’s annoying, but nobody dies.

In an RTOS (VxWorks, FreeRTOS), the goal is Determinism: Guarantee a response within a strict deadline. If an airbag deploys 10ms late, the driver dies.

Hard vs Soft Real-Time

  1. Hard Real-Time: Missing a deadline is a system failure.
    • Examples: Anti-lock brakes, Pacemakers, Nuclear Reactor control.
  2. Soft Real-Time: Missing a deadline degrades quality but the system survives.
    • Examples: VoIP calls, Video streaming, Online gaming.

2. Real-Time Scheduling Algorithms

How do we guarantee deadlines?

Rate Monotonic Scheduling (RMS)

  • Static Priority: Assign fixed priorities based on period (frequency).
  • Shorter Period = Higher Priority.
  • Optimal: For fixed-priority algorithms. If a set of tasks cannot be scheduled by RMS, no other fixed-priority algorithm can schedule them.

Earliest Deadline First (EDF)

  • Dynamic Priority: Assign priority based on absolute deadline.
  • Closest Deadline = Highest Priority.
  • Optimal: Can achieve 100% CPU utilization (RMS is limited to ~69%).
  • Risk: If overloaded, it fails unpredictably (Domino Effect).

3. Interactive: Scheduler Arena (RMS)

See how fixed priorities work. Task A runs every 4s (High Prio). Task B runs every 8s (Low Prio).

0s
4s
8s
12s
16s
Waiting...

4. The Priority Inversion Problem

This is the most famous bug in RTOS history (Mars Pathfinder, 1997).

Scenario:

  1. Low Priority Task (L) grabs a mutex (Lock M).
  2. High Priority Task (H) wakes up and needs Lock M. It blocks.
  3. Medium Priority Task (M) wakes up. Since Prio(M) > Prio(L), M preempts L.
  4. Result: L cannot run (preempted by M), so it cannot release the lock. H is blocked waiting for L. effectively, Medium Priority M is blocking High Priority H!

Solution: Priority Inheritance Protocol

When H blocks on a lock held by L, L temporarily inherits H’s high priority. This prevents M from preempting L. L finishes, releases the lock, and drops back to low priority. H grabs the lock and runs.


5. Code Example: Real-Time Threads

Standard OS threads are not real-time. But we can simulate the priority logic.

Go
Java
package main

import (
    "fmt"
    "time"
)

// Simulating a Periodic Task Loop
func periodicTask(name string, period time.Duration, cost time.Duration) {
    ticker := time.NewTicker(period)

    for t := range ticker.C {
        start := t
        deadline := start.Add(period)

        fmt.Printf("[%s] Start at %s (Deadline: %s)\n", name,
            start.Format("05.000"), deadline.Format("05.000"))

        // Simulate CPU Work
        time.Sleep(cost)

        now := time.Now()
        if now.After(deadline) {
            fmt.Printf("⚠️ [%s] MISSED DEADLINE by %s!\n", name, now.Sub(deadline))
        } else {
            fmt.Printf("✅ [%s] Finished. Slack: %s\n", name, deadline.Sub(now))
        }
    }
}

func main() {
    // Task A: Period 1s, Cost 200ms
    go periodicTask("Safety", 1*time.Second, 200*time.Millisecond)

    // Task B: Period 3s, Cost 1s
    go periodicTask("Logger", 3*time.Second, 1*time.Second)

    select {} // Block forever
}
// Java has a Real-Time Specification (RTSJ)
// But standard Java threads rely on the OS scheduler.
// We can set priorities, but they are just "hints" to Linux.

public class RealTimeSim {
    public static void main(String[] args) {
        Thread high = new Thread(new Task(200), "SafetyCheck");
        Thread low = new Thread(new Task(1000), "DataLogging");

        // 10 is Max, 1 is Min
        high.setPriority(Thread.MAX_PRIORITY); // 10
        low.setPriority(Thread.MIN_PRIORITY);  // 1

        low.start();
        high.start();
    }

    static class Task implements Runnable {
        int costMs;
        public Task(int c) { this.costMs = c; }

        public void run() {
            while(true) {
                long start = System.currentTimeMillis();
                // Simulate work
                while(System.currentTimeMillis() - start < costMs) {
                    // spin
                }
                System.out.println(Thread.currentThread().getName() + " Done");
                try { Thread.sleep(1000); } catch (Exception e) {}
            }
        }
    }
}

6. Summary

  • Determinism: The guarantee that X will happen by time T.
  • RMS: Optimal fixed-priority (Rate Monotonic).
  • Priority Inversion: A lower priority task blocking a higher priority one. Solved by Inheritance.