Watchdog task pattern in FreeRTOS - Time & Space Complexity
We want to understand how the time cost changes when running a watchdog task in FreeRTOS.
Specifically, how the task checks other tasks and how this scales as more tasks are added.
Analyze the time complexity of the following code snippet.
void WatchdogTask(void *pvParameters) {
for (;;) {
for (int i = 0; i < numTasks; i++) {
if (!IsTaskResponsive(i)) {
HandleUnresponsiveTask(i);
}
}
vTaskDelay(WATCHDOG_DELAY);
}
}
This code runs forever, checking each task once per cycle to see if it is responsive.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The inner for-loop that checks each task's responsiveness.
- How many times: It runs once every watchdog cycle, iterating over all tasks (numTasks times).
As the number of tasks increases, the watchdog checks more tasks each cycle.
| Input Size (numTasks) | Approx. Operations per Cycle |
|---|---|
| 10 | 10 checks |
| 100 | 100 checks |
| 1000 | 1000 checks |
Pattern observation: The number of checks grows directly with the number of tasks.
Time Complexity: O(n)
This means the time to complete one watchdog cycle grows linearly as the number of tasks increases.
[X] Wrong: "The watchdog task runs in constant time no matter how many tasks there are."
[OK] Correct: Because the watchdog checks each task one by one, more tasks mean more checks, so time grows with the number of tasks.
Understanding how a watchdog task scales helps you design reliable systems and shows you can reason about task monitoring in real-time software.
"What if the watchdog only checked a fixed number of tasks each cycle instead of all tasks? How would the time complexity change?"
Practice
Solution
Step 1: Understand the watchdog task role
The watchdog task monitors the health of other tasks to ensure they are running correctly.Step 2: Identify the action taken on failure
If a task fails or stops responding, the watchdog task can reset the system or take corrective action.Final Answer:
To monitor other tasks and reset the system if a task fails -> Option BQuick Check:
Watchdog monitors and resets = A [OK]
- Confusing watchdog with task creation
- Thinking watchdog handles user input
- Assuming watchdog manages memory
Solution
Step 1: Identify how watchdog timers are reset
Monitored tasks must periodically signal the watchdog by calling a reset function likewatchdog_reset().Step 2: Eliminate incorrect options
vTaskDelay()delays a task but does not reset the watchdog timer.xTaskCreate()creates tasks, not reset timers.vTaskDelete()deletes tasks, not reset timers.Final Answer:
Callwatchdog_reset()periodically from monitored tasks -> Option AQuick Check:
Reset watchdog by calling reset function = C [OK]
- Using delay functions to reset watchdog
- Trying to reset watchdog by creating or deleting tasks
- Confusing task management functions with watchdog reset
void WatchdogTask(void *pvParameters) {
for (;;) {
if (xSemaphoreTake(watchdogSemaphore, pdMS_TO_TICKS(1000)) == pdFALSE) {
// No reset signal received
vTaskDelay(pdMS_TO_TICKS(500));
// Take recovery action
} else {
// Reset signal received
vTaskDelay(pdMS_TO_TICKS(100));
}
}
}What happens if the monitored task never calls
xSemaphoreGive(watchdogSemaphore)?Solution
Step 1: Analyze semaphore wait behavior
The watchdog task waits 1000 ms for a semaphore signal. If none arrives,xSemaphoreTakereturnspdFALSE.Step 2: Understand the consequence of no signal
When no signal is received, the watchdog delays 500 ms and then takes recovery action repeatedly in the loop.Final Answer:
The watchdog task will detect no reset signal and take recovery action repeatedly -> Option AQuick Check:
No semaphore signal triggers recovery = A [OK]
- Assuming watchdog waits forever without action
- Thinking semaphore misuse causes crash here
- Believing semaphore resets automatically
void WatchdogTask(void *pvParameters) {
for (;;) {
if (xSemaphoreTake(watchdogSemaphore, 0) == pdTRUE) {
// Reset received
} else {
// No reset, take action
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}What is the main problem with this code?
Solution
Step 1: Examine semaphore wait time parameter
The callxSemaphoreTake(watchdogSemaphore, 0)means it does not wait and returns immediately.Step 2: Understand impact on watchdog behavior
Because it never blocks, the watchdog may miss reset signals if they arrive after the check, causing false recovery actions.Final Answer:
The semaphore wait time is zero, so it never blocks to wait for reset signals -> Option CQuick Check:
Zero wait means no blocking = D [OK]
- Thinking delay length is the problem
- Assuming semaphore is given incorrectly without evidence
- Believing task deletes itself here
Solution
Step 1: Understand heartbeat timing requirements
Each task sends a heartbeat every 500 ms. The watchdog must detect failure within 2 seconds.Step 2: Evaluate semaphore usage options
Using separate semaphores allows independent monitoring. Checking each with a 700 ms timeout ensures missing any heartbeat triggers failure detection quickly.Step 3: Compare with other options
One shared semaphore (Use one binary semaphore shared by all tasks; each task gives it every 500 ms) cannot distinguish which task failed. Waiting 2 seconds per semaphore (Use three separate semaphores; watchdog waits up to 2 seconds for each semaphore in sequence) delays detection. Counting semaphore (Use a single counting semaphore incremented by all tasks; watchdog resets counter every 2 seconds) loses individual task info.Final Answer:
Use three separate semaphores; watchdog checks each semaphore with a 700 ms timeout and flags failure if any miss -> Option DQuick Check:
Separate semaphores + short timeout = fast failure detection = B [OK]
- Using one semaphore for all tasks losing failure detail
- Waiting too long per semaphore delaying detection
- Using counting semaphore losing individual task info
Ready to prove it?
Pass the test and this pattern moves unknown
