Multiple tasks running concurrently in FreeRTOS - Time & Space Complexity
When multiple tasks run at the same time in FreeRTOS, it's important to understand how the total work grows as we add more tasks.
We want to know how the time to manage all tasks changes when the number of tasks increases.
Analyze the time complexity of the following code snippet.
void vTask1(void *pvParameters) {
while(1) {
// Task 1 work
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
void vTask2(void *pvParameters) {
while(1) {
// Task 2 work
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
int main() {
xTaskCreate(vTask1, "Task1", 1000, NULL, 1, NULL);
xTaskCreate(vTask2, "Task2", 1000, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}
This code creates two tasks that run repeatedly and share CPU time managed by FreeRTOS.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Each task runs an infinite loop doing work and then delaying.
- How many times: Each task repeats its loop forever, switching happens many times.
As we add more tasks, the scheduler must switch between them more often, increasing the total management work.
| Number of Tasks (n) | Approx. Scheduler Operations |
|---|---|
| 2 | Low switching overhead |
| 10 | More frequent context switches |
| 100 | Much more switching and management |
Pattern observation: The scheduler's work grows roughly in proportion to the number of tasks.
Time Complexity: O(n)
This means the time to manage all tasks grows linearly as we add more tasks.
[X] Wrong: "Adding more tasks won't affect performance because tasks run independently."
[OK] Correct: The scheduler must switch between all tasks, so more tasks mean more switching and overhead.
Understanding how task management scales helps you design efficient multitasking systems and shows you grasp real-time system behavior.
"What if tasks had different priorities? How would that affect the time complexity of scheduling?"
Practice
Solution
Step 1: Understand task concurrency
Multiple tasks let the program handle different jobs at once, improving efficiency.Step 2: Identify the purpose in FreeRTOS
FreeRTOS switches between tasks automatically, enabling multitasking.Final Answer:
To allow the program to perform several operations at the same time -> Option AQuick Check:
Multiple tasks = multitasking = To allow the program to perform several operations at the same time [OK]
- Thinking tasks slow down the program
- Believing tasks waste memory
- Ignoring the role of delays
Solution
Step 1: Recall FreeRTOS task creation function
The correct function to create a task is xTaskCreate.Step 2: Match the exact syntax
xTaskCreate(TaskFunction, "TaskName", stackSize, NULL, priority, NULL); matches the correct function name and parameters.Final Answer:
xTaskCreate(TaskFunction, "TaskName", stackSize, NULL, priority, NULL); -> Option CQuick Check:
Task creation function = xTaskCreate = xTaskCreate(TaskFunction, "TaskName", stackSize, NULL, priority, NULL); [OK]
- Using incorrect function names like createTask
- Mixing up parameter order
- Missing the 'x' prefix in function name
void Task1(void *pvParameters) {
for (;;) {
printf("Task1 running\n");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void Task2(void *pvParameters) {
for (;;) {
printf("Task2 running\n");
vTaskDelay(pdMS_TO_TICKS(500));
}
}
What will be the output pattern when both tasks run concurrently?Solution
Step 1: Analyze vTaskDelay timing for Task1
Task1 delays 1000 ms (1 second) between prints.Step 2: Analyze vTaskDelay timing for Task2
Task2 delays 500 ms (0.5 seconds) between prints.Step 3: Understand concurrent execution
Both tasks run independently, so Task2 prints twice as often as Task1.Final Answer:
Task1 prints every 1 second; Task2 prints every 0.5 seconds -> Option AQuick Check:
Delays control print rate = Task1 prints every 1 second; Task2 prints every 0.5 seconds [OK]
- Assuming tasks print simultaneously
- Mixing up delay times
- Thinking one task blocks the other
void TaskA(void *pvParameters) {
while(1) {
// Do something
vTaskDelay(1000);
}
}
xTaskCreate(TaskA, "TaskA", 1000, NULL, 1, NULL);Solution
Step 1: Check vTaskDelay parameter
vTaskDelay expects delay in ticks, not milliseconds.Step 2: Identify correct delay usage
Use pdMS_TO_TICKS(1000) to convert 1000 ms to ticks.Final Answer:
vTaskDelay requires delay in ticks, not milliseconds -> Option BQuick Check:
Delay unit must be ticks = vTaskDelay requires delay in ticks, not milliseconds [OK]
- Passing milliseconds directly to vTaskDelay
- Wrong return type for task function
- Incorrect stack size assumptions
Solution
Step 1: Understand the need for synchronization
To avoid overlapping prints, tasks must coordinate access to the printing resource.Step 2: Identify synchronization method
A binary semaphore allows one task to print while the other waits, alternating access.Step 3: Evaluate other options
Different delays or same priority without sync can cause overlapping prints; global variables alone don't prevent conflicts.Final Answer:
Use a binary semaphore to synchronize tasks before printing -> Option DQuick Check:
Synchronization via semaphore = Use a binary semaphore to synchronize tasks before printing [OK]
- Relying only on delays for synchronization
- Ignoring task priority effects
- Not using any synchronization mechanism
Ready to prove it?
Pass the test and this pattern moves unknown
