RTOS, demystified
RTOS = Real-Time Operating System
Linux tries to be fair. An RTOS tries to be on time. That is the whole idea.
Fair is your laptop. Chrome, Spotify, Slack — everyone gets a turn. If the music waits an extra blink, you never notice. On time is different. Some work has a deadline. Miss it, and the failure is not “the app felt slow.” The failure is a car that does not brake, a monitor that does not beep, a network that stays dark because the alarm was still waiting its turn.
Who cares — and why
You, me, and anyone whose life is not a laptop. Most computers you never think about are not trying to be nice. They are trying not to be late.
A laptop is a restaurant
The operating system is a waiter. Every program orders food. The waiter shares the kitchen fairly so nobody starves. That is Linux. That is Windows. That is xv6.
An RTOS is an emergency room
ER = emergency room. A heart attack does not take a number behind a sprained ankle. The urgent patient goes first, even if someone was already being seen. Late here means someone gets hurt.
The internet has ERs too
Under the street, a little computer sits on a fiber-optic cable. If the light dies, that box must scream now — not after it finishes taking notes. Cars, planes, factory robots, hospital gear: same rule.
Below is a tiny C++ kernel that plays by ER rules. Nothing to install.
The C++ compiles with g++. Poke it.
Fair vs on time
A general-purpose OS (the Linux on your laptop, or xv6) is that fair waiter: everyone gets a turn. A Real-Time Operating System is the emergency room. The heart attack goes first, even if someone was already being seen.
Same three jobs. Same arrival times. Left side is the restaurant: round-robin, everyone gets a slice of the CPU. Right side is the ER: always run whichever job is most urgent. Watch ALARM — it walks in at tick 4, needs 2 ticks of work, and must be done by tick 7. If it waits in line, it is late. Late is the whole problem.
General-purpose OS
ALARM waits its turn. Slice = 2 ticks.
Real-Time OS (the ER)
ALARM jumps the line. Most urgent wins.
The alarm did not get faster. The policy changed. That is every real-time system in one picture.
Cut the fiber
Now put the emergency room on a real cable. A fiber-optic cable is a glass line that carries internet traffic as light. An optical network element is the little computer that sits on that cable: it turns light into packets, takes notes (telemetry), and answers the human operator. Then the cable is cut.
The fiber
Think of it as a garden hose, except the water is light, and the light is the internet — video, calls, everything on that path.
A cut
A backhoe hits the hose. The light stops. Until something notices, that path is dead, and nobody upstream knows why.
Loss of Signal (LOS)
LOS is the box saying “the light is gone.” That is the emergency. The alarm has to take the CPU now, not after telemetry finishes its notes.
Hardware raises a Loss-of-Signal interrupt.
ISR = Interrupt Service Routine — a tiny bit of code that runs
the instant the hardware yells. It does almost nothing: it wakes the
LOS task, then gets out of the way. Then pick() must run that
alarm immediately. A dark fiber that waits its turn is a network outage.
Deadline: finish within 4 ticks of the interrupt.
Highest-priority ready task always wins. LOS (prio 0) will steal the CPU.
Flip the toggle to round-robin and cut the fiber again. Same interrupt. Same tasks. The alarm now waits its turn — and misses. That is why Network Element firmware is an RTOS, not a fair scheduler.
The bug that looks like a scheduler bug
High-priority is blocked. Medium-priority is running. You stare at pick()
and it looks broken. It isn't. LOW grabbed a mutex, HIGH
needs it, and MED — who doesn't even touch the lock — keeps getting the CPU
because LOW is stuck at low priority. HIGH is waiting on LOW. LOW cannot run because MED is
"more important" than LOW. That knot is priority inversion.
It grounded Mars Pathfinder in 1997. The fix is almost embarrassing: priority inheritance — while HIGH waits on LOW, LOW temporarily becomes HIGH. MED can no longer sneak in. Toggle it.
Interview translation: “The scheduler was correct. The lock protocol wasn't.” Inheritance is how FreeRTOS mutexes and Linux rt-mutexes keep a high-priority alarm from dying behind a low-priority holder.
Here's the actual C++.
Everything above is a visualization of one file:
kernel.cpp. It compiles on Linux with nothing but g++.
The playground and the binary implement the same policy —
pick(), notify() from an ISR, mutexes, inheritance.
g++ -std=c++17 -Wall kernel.cpp -o tinyr-tos && ./tinyr-tos ./tinyr-tos invert ./tinyr-tos inherit
Download kernel.cpp · same file the playground is running in your head.
pick() — highest effective priority wins. 0 = highest.
pthread_setschedparam(t, SCHED_FIFO, {99 - prio}) — same policy, real threads.
Tasks + ISRs + mutexes. The alarm is a high-priority task notified from the line interrupt.
Loading kernel.cpp…
You made it.
A general-purpose OS shares the CPU fairly. An RTOS shares it by urgency. You watched a fiber-cut ISR notify a C++ task, watched that task preempt telemetry, met a deadline, and saw priority inversion lie to you — then vanish when the lock inherited priority. That is the kernel of every Network Element, robot, and car.
Already poked the Unix side? xv6, demystified →
Run it back ↑