Critical sections and interrupt disabling in FreeRTOS - Time & Space Complexity
When using critical sections and disabling interrupts in FreeRTOS, it's important to know how the time spent changes as the code inside grows.
We want to see how the execution time grows when protecting code with interrupts disabled.
Analyze the time complexity of the following code snippet.
void exampleFunction(int n) {
taskENTER_CRITICAL(); // Disable interrupts
for (int i = 0; i < n; i++) {
// Critical work here
doSomeWork(i);
}
taskEXIT_CRITICAL(); // Enable interrupts
}
This code disables interrupts, runs a loop n times doing some work, then enables interrupts again.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop running doSomeWork() n times inside the critical section.
- How many times: Exactly n times, where n is the input size.
As n grows, the time spent with interrupts disabled grows directly with n because the loop runs n times inside the critical section.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 times doSomeWork() |
| 100 | 100 times doSomeWork() |
| 1000 | 1000 times doSomeWork() |
Pattern observation: The time grows linearly as n increases.
Time Complexity: O(n)
This means the time spent with interrupts disabled grows directly in proportion to the size of the work inside the critical section.
[X] Wrong: "Disabling interrupts only takes a fixed small time, so the whole function always runs fast regardless of n."
[OK] Correct: The disabling is quick, but the loop inside runs n times while interrupts are off, so the total time with interrupts disabled grows with n.
Understanding how critical sections affect timing helps you write responsive embedded code and shows you can reason about how code changes impact system behavior.
"What if the loop was moved outside the critical section, only disabling interrupts briefly inside the loop? How would the time complexity of the critical section change?"
Practice
taskENTER_CRITICAL() and taskEXIT_CRITICAL() in FreeRTOS?Solution
Step 1: Understand critical sections in FreeRTOS
Critical sections are used to protect code that must not be interrupted to avoid data corruption or race conditions.Step 2: Role of
These functions disable and enable interrupts respectively, marking the start and end of a critical section.taskENTER_CRITICAL()andtaskEXIT_CRITICAL()Final Answer:
To prevent interrupts during a critical section of code -> Option AQuick Check:
Critical sections stop interrupts = A [OK]
- Confusing critical sections with task creation
- Thinking they manage memory
- Assuming they start the scheduler
Solution
Step 1: Identify the function to enter critical section
The correct FreeRTOS API to disable interrupts and enter a critical section istaskENTER_CRITICAL().Step 2: Check other options for correctness
taskEXIT_CRITICAL()exits the critical section, others are not valid FreeRTOS functions.Final Answer:
taskENTER_CRITICAL(); -> Option CQuick Check:
Enter critical section = taskENTER_CRITICAL() [OK]
- Using taskEXIT_CRITICAL() to start critical section
- Inventing non-existent functions
- Confusing function names
taskENTER_CRITICAL(); sharedVariable++; taskEXIT_CRITICAL();What is the effect of this code on
sharedVariable?Solution
Step 1: Analyze the critical section usage
The code disables interrupts before incrementing sharedVariable and re-enables them after, protecting the increment operation.Step 2: Understand the effect on sharedVariable
This ensures the increment is atomic and safe from concurrent access or interrupts.Final Answer:
It increments sharedVariable safely without interruption -> Option AQuick Check:
Critical section protects increment = D [OK]
- Thinking interrupts are allowed during increment
- Assuming syntax errors where none exist
- Believing variable resets to zero
taskENTER_CRITICAL(); sharedCounter++; // Missing taskEXIT_CRITICAL();
Solution
Step 1: Check for matching critical section calls
The code callstaskENTER_CRITICAL()but does not calltaskEXIT_CRITICAL()to re-enable interrupts.Step 2: Understand consequences of missing exit
Interrupts remain disabled indefinitely, which can cause system to freeze or miss important events.Final Answer:
Interrupts remain disabled causing system issues -> Option DQuick Check:
Missing taskEXIT_CRITICAL() disables interrupts forever = A [OK]
- Ignoring missing exit call
- Assuming increment fails
- Thinking code has syntax errors
Solution
Step 1: Understand impact of critical section length
Long critical sections block interrupts for too long, reducing system responsiveness.Step 2: Best practice for protecting shared resources
Short critical sections minimize interrupt blocking while protecting shared data safely.Final Answer:
Use short critical sections only around the minimal code that accesses the resource -> Option BQuick Check:
Short critical sections = better responsiveness [OK]
- Using long critical sections unnecessarily
- Disabling interrupts globally
- Ignoring synchronization needs
Ready to prove it?
Pass the test and this pattern moves unknown
