The Rendezvous pattern helps two tasks meet at the same point and wait for each other before continuing. It makes sure both tasks are ready before moving on.
Rendezvous (sync) pattern in FreeRTOS
/* Use two binary semaphores for synchronization */ SemaphoreHandle_t semTask1, semTask2; void Task1(void *params) { // Do some work xSemaphoreGive(semTask1); // Signal Task1 is ready xSemaphoreTake(semTask2, portMAX_DELAY); // Wait for Task2 // Continue after rendezvous } void Task2(void *params) { // Do some work xSemaphoreGive(semTask2); // Signal Task2 is ready xSemaphoreTake(semTask1, portMAX_DELAY); // Wait for Task1 // Continue after rendezvous }
Two binary semaphores are used to signal readiness between tasks.
Each task signals it is ready and waits for the other task's signal.
SemaphoreHandle_t semTask1 = xSemaphoreCreateBinary();
SemaphoreHandle_t semTask2 = xSemaphoreCreateBinary();
void Task1(void *params) {
// Work before rendezvous
xSemaphoreGive(semTask1);
xSemaphoreTake(semTask2, portMAX_DELAY);
// Work after rendezvous
}
void Task2(void *params) {
// Work before rendezvous
xSemaphoreGive(semTask2);
xSemaphoreTake(semTask1, portMAX_DELAY);
// Work after rendezvous
}/* Using counting semaphores for multiple rendezvous */ SemaphoreHandle_t semTask1 = xSemaphoreCreateCounting(1, 0); SemaphoreHandle_t semTask2 = xSemaphoreCreateCounting(1, 0); void Task1(void *params) { xSemaphoreGive(semTask1); xSemaphoreTake(semTask2, portMAX_DELAY); } void Task2(void *params) { xSemaphoreGive(semTask2); xSemaphoreTake(semTask1, portMAX_DELAY); }
This program creates two tasks that do some work, then wait for each other using semaphores. They print messages before and after the rendezvous to show synchronization.
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> SemaphoreHandle_t semTask1, semTask2; void Task1(void *params) { printf("Task1: Starting work before rendezvous\n"); vTaskDelay(pdMS_TO_TICKS(1000)); // Simulate work printf("Task1: Ready, signaling Task2\n"); xSemaphoreGive(semTask1); xSemaphoreTake(semTask2, portMAX_DELAY); printf("Task1: Rendezvous complete, continuing work\n"); vTaskDelete(NULL); } void Task2(void *params) { printf("Task2: Starting work before rendezvous\n"); vTaskDelay(pdMS_TO_TICKS(2000)); // Simulate longer work printf("Task2: Ready, signaling Task1\n"); xSemaphoreGive(semTask2); xSemaphoreTake(semTask1, portMAX_DELAY); printf("Task2: Rendezvous complete, continuing work\n"); vTaskDelete(NULL); } int main(void) { semTask1 = xSemaphoreCreateBinary(); semTask2 = xSemaphoreCreateBinary(); xTaskCreate(Task1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(Task2, "Task2", 1000, NULL, 1, NULL); vTaskStartScheduler(); for(;;); return 0; }
Make sure semaphores are created before starting tasks.
Use portMAX_DELAY to wait indefinitely for the other task.
Rendezvous ensures both tasks reach the point before continuing.
The Rendezvous pattern uses semaphores to synchronize two tasks.
Each task signals readiness and waits for the other.
This avoids race conditions and coordinates task progress.
Practice
Solution
Step 1: Understand the Rendezvous pattern concept
The Rendezvous pattern is designed to synchronize two tasks so that each waits for the other to reach a certain point before continuing.Step 2: Identify the purpose in FreeRTOS context
In FreeRTOS, this synchronization is often done using semaphores to signal readiness and wait for the other task.Final Answer:
To synchronize two tasks so they wait for each other before proceeding -> Option AQuick Check:
Rendezvous = Synchronize tasks [OK]
- Thinking it creates independent tasks without coordination
- Confusing with task prioritization
- Assuming it manages memory allocation
Solution
Step 1: Recall synchronization primitives in FreeRTOS
FreeRTOS provides mutexes, semaphores, queues, and event groups for task synchronization and communication.Step 2: Identify which primitive signals readiness and waits
The Rendezvous pattern requires signaling and waiting between two tasks, which is best done using semaphores.Final Answer:
Semaphore -> Option CQuick Check:
Rendezvous uses semaphores [OK]
- Choosing mutex which is for mutual exclusion, not sync
- Confusing queues with direct signaling
- Using event groups which are for multiple event flags
Solution
Step 1: Understand semaphore signaling and waiting
If Task A signals semaphore S1 before Task B waits on it, the semaphore count becomes available.Step 2: Analyze Task B's wait on S1
When Task B waits on S1, it finds the semaphore already signaled and unblocks immediately without waiting.Final Answer:
Task B will unblock immediately when it waits on S1 -> Option DQuick Check:
Signaled semaphore unblocks waiting task immediately [OK]
- Assuming tasks must wait even if semaphore is signaled
- Thinking Task A blocks waiting on S2 first
- Believing both tasks run without blocking always
void TaskA(void *pvParameters) {
xSemaphoreGive(SemA);
xSemaphoreTake(SemB, portMAX_DELAY);
// Continue...
}
void TaskB(void *pvParameters) {
xSemaphoreTake(SemA, portMAX_DELAY);
xSemaphoreGive(SemB);
// Continue...
}Solution
Step 1: Check semaphore initialization
Before using semaphores, they must be created with xSemaphoreCreateBinary or similar functions.Step 2: Identify missing creation
The code snippet does not show creation of SemA and SemB, which will cause runtime errors or undefined behavior.Final Answer:
Semaphores SemA and SemB are not created before use -> Option BQuick Check:
Semaphores must be created before giving or taking [OK]
- Thinking order of give/take is wrong here
- Believing semaphores are not for synchronization
- Misunderstanding portMAX_DELAY usage
Solution
Step 1: Understand semaphore types and their behavior
Binary semaphores can only hold one signal at a time, so signaling twice before waiting can cause lost signals and deadlock.Step 2: Identify solution to handle multiple signals
Counting semaphores can hold multiple signals, allowing tasks to signal multiple times without losing signals, preventing deadlock.Final Answer:
Use counting semaphores instead of binary semaphores -> Option AQuick Check:
Counting semaphores handle multiple signals safely [OK]
- Using mutexes which do not count signals
- Using queues which add complexity
- Using event groups with single bits only
Ready to prove it?
Pass the test and this pattern moves unknown
