(a) Blocked — it is waiting for an event/resource and is not eligible to run.
(b) Running — only one task per core can be here.
(c) Ready — able to run, just waiting its turn for the CPU.
(d) Suspended — parked on purpose, not by an event.
Why: the states are distinguished by why a task is not running — waiting for CPU (Ready) vs waiting for an event (Blocked) vs deliberately parked (Suspended).
Recall Solution 1.2
False. The PC is only where the code was; the data it was working on lives in the general registers (r0–r12) and the status flags, plus the private stack via the stack pointer (SP). Losing any of those means the task resumes computing garbage. A switch saves the full register set + SP, anchored in the task's TCB (Task Control Block). See Stack memory and TCB.
What we do: plug into the overhead model.
η=Tcs⋅ftick=(3×10−6s)(500Hz)=1.5×10−3=0.15%.Why: in 1 second there are 500 ticks; each wastes 3μs, so 500×3μs=1500μs=1.5 ms lost out of 1000 ms, i.e. 0.15%. Cheap — a healthy design.
Recall Solution 2.2
What we do: use the response-time bound.
Tresp≤Tisr+Tcs=4μs+3μs=7μs.Why: being the highest priority, nothing can delay it except (a) the triggering ISR finishing and (b) exactly one context switch into it. Lower tasks cannot block the top task. This is the seed idea behind Rate Monotonic Scheduling.
Recall Solution 2.3
At 1 kHz: η=(5×10−6)(1000)=0.005=0.5%.
At 10 kHz: η=(5×10−6)(10000)=0.05=5%.
Verdict: unwise. The tick only drives time-based delays; event-driven preemption is already instant via interrupts. Raising the tick 10× multiplied wasted CPU 10× for no responsiveness gain. See Interrupts and ISR latency.
[0,2) ms: A Running; B does not exist / not Ready.
At t=2: B becomes Ready and outranks A → preemption → context switch → B takes the CPU.
[2,5) ms: B Running; A Ready (able to run, but outranked — not Blocked; it was never waiting for an event).
At t=5: B blocks on the queue → B Blocked → A is now the highest-priority Ready task → switch back → A Running.
[5,∞) ms: A Running; B Blocked.
Why the t=2 step matters: the preemptive rule forces B to run immediately, not after A finishes. Without preemption (cooperative scheduling), B waits until A voluntarily yields — possibly missing a deadline.
Recall Solution 3.2
No preemption. Preemption is strictly priority-driven — it only happens when a higher-priority task becomes Ready. Equal-priority tasks share via time-slicing (round-robin): at each tick boundary the scheduler rotates to the next equal-priority Ready task. So Y gets the CPU at the next tick, not the instant it became Ready.
Why the distinction: preemption answers "urgency"; round-robin answers "fairness." They are different questions.
Priorities (higher number = more urgent): Motor = 3, Sensor = 2, WiFi = 1.
Motor (prio 3): driven by an interrupt (encoder pulse). Response bound Tresp≤Tisr+Tcs — well under 1 ms for typical μs-scale switches. It is highest priority so nothing blocks it.
Sensor (prio 2): must block during the 5 ms ADC wait (e.g. xQueueReceive / a semaphore given by the ADC-done ISR). A busy-wait while(!ready); would keep it Running, stealing 5 ms from WiFi and wasting CPU. Blocking releases the CPU so WiFi runs meanwhile.
WiFi (prio 1): lowest — runs only in the gaps. That is exactly what a background task should do.
Why this ordering: hard-deadline, event-driven work gets top priority so preemption serves it instantly; the slow poll blocks so it never hogs the core; housekeeping soaks up idle time. See Semaphores and Queues for the blocking primitives.
Recall Solution 4.2
Danger: priority inversion. If low-priority WiFi holds the mutex when Sensor (higher) needs it, Sensor is stuck waiting on WiFi. Worse, if the Motor task never touches the mutex but a medium task keeps preempting WiFi, WiFi cannot finish and release it — so Sensor is blocked indirectly by a lower-priority task. Fix: priority inheritance — WiFi temporarily inherits Sensor's priority while holding the mutex. Full treatment in Priority Inversion and Mutexes.
What we do: the overhead model counts switches per second, whatever their cause. Total switches per second =ftick+fevent=1000+3000=4000.
η=Tcs⋅(ftick+fevent)=(2×10−6)(4000)=8×10−3=0.8%.Verdict: healthy — well under 5%. Why the sum:η=Tcs⋅ftick generalises to Tcs⋅(total switch rate); ticks and events both trigger switches, so add their rates.
Recall Solution 5.2
Zero-tick limit: with ftick=0 and no events, η=Tcs⋅0=0 — no switching, no waste. This is exactly the point of tickless idle: stop the periodic tick when nothing is scheduled, saving power.
Maximum meaningful η:η=1 (100%). It occurs when the switch rate reaches f=1/Tcs — the CPU spends every second switching and gets zero real work done. Beyond that the model breaks (you cannot switch more often than each switch takes). Physically, η→1 is total collapse: pure overhead, no throughput.
Recall Solution 5.3
η=Tcs⋅ftick is a straight line through the origin with slope Tcs — overhead rises linearly with tick rate. There is no "free smoothness": doubling the tick doubles the waste.
5% crossing with Tcs=5μs:
0.05=(5×10−6)ftick⇒ftick=5×10−60.05=10000 Hz=10 kHz.
So at 10 kHz you hit the smell line; stay well below it. This is why real systems keep the tick at 100–1000 Hz and rely on event-driven blocking instead of a fast tick.