Critical section with taskENTER_CRITICAL in FreeRTOS - Time & Space Complexity
We want to see how the time cost changes when using a critical section in FreeRTOS.
Specifically, how does the program time grow when entering and exiting a critical section?
Analyze the time complexity of the following code snippet.
void updateSharedData(int *data, int value) {
taskENTER_CRITICAL();
*data = value; // update shared variable
taskEXIT_CRITICAL();
}
This code updates a shared variable safely by disabling interrupts during the update.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Entering and exiting the critical section (disabling and enabling interrupts).
- How many times: Each time the function is called, these operations happen once.
The time to enter and exit the critical section stays the same no matter the input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 times entering and exiting critical section |
| 100 | 100 times entering and exiting critical section |
| 1000 | 1000 times entering and exiting critical section |
Pattern observation: The cost grows linearly with the number of calls, but each call's critical section cost is constant.
Time Complexity: O(1)
This means entering and exiting the critical section takes the same time regardless of input size.
[X] Wrong: "Entering a critical section takes longer if the shared data is bigger or more complex."
[OK] Correct: The critical section disables interrupts and runs a fixed set of instructions, so its time does not depend on data size.
Understanding how critical sections affect timing helps you write safe and efficient multitasking code.
"What if the critical section included a loop over an array? How would the time complexity change?"
Practice
taskENTER_CRITICAL() in FreeRTOS?Solution
Step 1: Understand what
This function disables interrupts to prevent context switches and protect shared resources.taskENTER_CRITICAL()doesStep 2: Identify the purpose in multitasking
Disabling interrupts ensures that the critical section code runs without interruption, avoiding data corruption.Final Answer:
To disable interrupts and protect shared data during a critical section -> Option BQuick Check:
Critical section protection = disable interrupts [OK]
- Confusing task creation with critical section
- Thinking it allocates memory
- Assuming it sends messages
Solution
Step 1: Recall the exact function name and syntax
The correct FreeRTOS API function to enter a critical section istaskENTER_CRITICAL()with parentheses.Step 2: Check the options for correct spelling and syntax
Only taskENTER_CRITICAL(); uses the exact function name with parentheses, which is required to call the function.Final Answer:
taskENTER_CRITICAL(); -> Option CQuick Check:
Function call syntax = parentheses needed [OK]
- Omitting parentheses when calling functions
- Using incorrect function names
- Confusing with similar sounding functions
int sharedCounter = 0;
void incrementCounter() {
taskENTER_CRITICAL();
sharedCounter++;
taskEXIT_CRITICAL();
}
incrementCounter();
printf("%d", sharedCounter);
What will be the output after running this code once?Solution
Step 1: Analyze the increment inside the critical section
The function incrementssharedCounterby 1 while interrupts are disabled, ensuring safe update.Step 2: Check the output after one call
After callingincrementCounter()once,sharedCounterbecomes 1, so printing it outputs 1.Final Answer:
1 -> Option AQuick Check:
Increment once = 1 [OK]
- Assuming no increment due to critical section
- Thinking code won't compile
- Confusing output with initial value
void updateData() {
taskENTER_CRITICAL();
sharedData = 42;
// Missing taskEXIT_CRITICAL();
}Solution
Step 1: Check for matching critical section calls
The code callstaskENTER_CRITICAL()but does not calltaskEXIT_CRITICAL(), so interrupts remain disabled.Step 2: Understand consequences of missing exit
Interrupts staying disabled can freeze the system or cause missed interrupts, which is a serious error.Final Answer:
MissingtaskEXIT_CRITICAL()causes interrupts to stay disabled -> Option AQuick Check:
Always pair enter and exit critical [OK]
- Forgetting to call taskEXIT_CRITICAL()
- Thinking enter critical is invalid in functions
- Assuming volatile fixes missing exit
counter. To avoid race conditions, you use a critical section:
void increment() {
taskENTER_CRITICAL();
counter++;
taskEXIT_CRITICAL();
}
However, the system becomes unresponsive when interrupts are disabled for too long. What is the best way to improve this?Solution
Step 1: Understand impact of long critical sections
Disabling interrupts for too long blocks other important system activities, causing unresponsiveness.Step 2: Optimize critical section length
Keeping the critical section short, only around the shared variable update, minimizes interrupt blocking and improves responsiveness.Final Answer:
Keep the critical section as short as possible, only around the increment -> Option DQuick Check:
Short critical section = better responsiveness [OK]
- Removing critical section causing race conditions
- Disabling interrupts too long
- Using busy-wait inside critical section
Ready to prove it?
Pass the test and this pattern moves unknown
