computer-science4 min read

Real-Time Systems Tutorial: Learn RT Systems from Scratch (2026)

Real-Time Systems Tutorial: Learn RT Systems from Scratch (2026)

Published:  |  Category: Computer Science  |  Reading time: ~15 min
Real-Time Systems Tutorial: Learn RT Systems from Scratch (2026)

Real-time systems are those where correctness depends not only on the logical result but also on the time at which results are produced. Having developed safety-critical avionics software, I have learned that real-time design requires rigorous analysis of task scheduling, resource sharing, and deadline satisfaction. This tutorial covers periodic task scheduling, Rate Monotonic scheduling, Earliest Deadline First, priority inversion, and response-time analysis.

We will explore both fixed-priority and dynamic-priority scheduling algorithms, analyze their schedulability, and implement a simple real-time kernel.

Hard vs Soft Real-Time Systems

A hard real-time system must meet every deadline — a single missed deadline constitutes system failure. Examples include airbag deployment and pacemakers. Soft real-time systems tolerate occasional missed deadlines with degraded quality — video streaming and audio processing. Firm real-time systems are between the two: late results are discarded but reduce value.

from enum import Enum
class RTType(Enum): HARD=1; FIRM=2; SOFT=3
class Task:
    def __init__(self,n,p,w,d,t):
        self.name=n; self.period=p; self.wcet=w; self.deadline=d; self.type=t
    def util(self): return self.wcet/self.period
tasks=[Task("BrakeCtrl",10,3,10,RTType.HARD),Task("Poll",20,2,20,RTType.HARD),
       Task("Display",50,5,50,RTType.SOFT),Task("Log",100,1,100,RTType.SOFT)]
for t in tasks: print(f"{t.name}: U={t.util():.2f}")

Rate Monotonic Scheduling (RMS)

Rate Monotonic Scheduling assigns priorities inversely proportional to task periods — the shortest period gets the highest priority. RMS is optimal among fixed-priority scheduling algorithms. The Liu-Layland sufficient condition states that for N tasks, total utilization must not exceed N*(2^(1/N)-1). For large N, this bound approaches 69.3%.

import math
def bound(n): return n*(2.0**(1.0/n)-1.0)
def is_sched(tasks):
    U = sum(t.wcet/t.period for t in tasks)
    return U <= bound(len(tasks)), U

def rta(task, tasks):
    R = task.wcet
    for _ in range(100):
        I = sum(t.wcet*((R+t.period-1)//t.period) for t in tasks if t.period < task.period)
        new = task.wcet + I
        if new == R: return R <= task.deadline, R
        if new > task.deadline: return False, new
        R = new
    return False, R

Earliest Deadline First (EDF)

Earliest Deadline First is a dynamic-priority scheduling algorithm: the task with the earliest absolute deadline runs. EDF is optimal on a single processor — if any algorithm can schedule a task set, EDF can. EDF can schedule any task set with total utilization of 100% or less. During overload, EDF may experience a scheduling avalanche where many tasks miss deadlines.

import heapq
class EDFScheduler:
    def __init__(self): self.q=[]; self.t=0
    def add(self, tid, dl, ex): heapq.heappush(self.q, (dl, tid, ex))
    def run(self, sim):
        while self.q and self.t < sim:
            dl, tid, rem = heapq.heappop(self.q)
            if self.t + rem <= dl:
                self.t += rem; print(f"Task {tid} done at t={self.t}")
            else:
                print(f"Task {tid} MISSED dl={dl}")

Response Time Analysis

Response time analysis computes the worst-case completion time of a task under fixed-priority scheduling. The response time R is the sum of WCET and interference from higher-priority tasks. The critical instant occurs when all tasks release simultaneously. Release jitter adds complexity to the analysis.

def wcrt(tasks, idx):
    task = tasks[idx]
    hp = [t for t in tasks if t.period < task.period]
    R = task.wcet
    for _ in range(100):
        I = sum(t.wcet*((R+t.period-1)//t.period) for t in hp)
        new = task.wcet + I
        if new == R: return R <= task.deadline, R
        if new > task.deadline: return False, new
        R = new
    return False, R

Priority Inversion and the Mars Pathfinder Bug

Priority inversion occurs when a high-priority task is blocked by a low-priority task holding a shared resource, while a medium-priority task preempts the low-priority task. The Mars Pathfinder bug in 1997 was caused by priority inversion. Priority inheritance solves this: the low-priority task temporarily inherits the high priority.

class PIMutex:
    def __init__(self): self.holder=None; self.inherited=None; self.wq=[]
    def lock(self, task, prio):
        if self.holder is None:
            self.holder=task; self.inherited=prio; return True
        else:
            self.inherited = max(self.inherited, prio)
            self.wq.append((task,prio)); return False
    def unlock(self, task):
        if self.holder==task and self.wq:
            self.wq.sort(key=lambda x:-x[1])
            self.holder, self.inherited = self.wq.pop(0)
        else: self.holder=None

Real-Time Operating System Kernel Design

Building a minimal real-time kernel involves implementing context switching, a scheduler, and synchronization primitives. The PendSV exception on ARM Cortex-M is the standard mechanism for context switching. The kernel maintains a ready queue (bitmap-based for O(1) scheduling), a system tick counter, and task control blocks.

typedef struct { uint32_t* sp; uint32_t prio; uint32_t rem; uint32_t state; } TCB;
TCB tasks[MAX]; uint32_t current; uint32_t num_tasks;
void scheduler(void) {
    uint32_t bm = 0;
    for (int i=0; iICSR |= SCB_ICSR_PENDSVSET_Msk; }
}
void SysTick_Handler(void) {
    if (tasks[current].rem > 0) tasks[current].rem--;
    if (tasks[current].rem == 0) { tasks[current].state=0; scheduler(); }
}

Frequently Asked Questions

What is the critical instant?

The critical instant occurs when all tasks are released simultaneously at time 0, leading to maximum interference. RTA assumes the critical instant to guarantee schedulability.

What is the difference between preemptive and cooperative scheduling?

In preemptive scheduling, the OS can interrupt a running task to run a higher-priority task. In cooperative scheduling, tasks voluntarily yield. Preemptive scheduling provides better responsiveness.

How does SRP prevent deadlocks?

SRP assigns each task a preemption level based on its priority. A task cannot preempt if its level is not higher than the ceiling of locked resources, preventing nested lock chains.

Why is WCET analysis hard?

Modern processor features — caches, branch prediction, pipelining, out-of-order execution — make worst-case timing unpredictable. Static analysis must overapproximate.

Originally published on Ayodhyyya. Last updated June 1, 2026.