Consider the following FreeRTOS code snippet using a binary semaphore. What will be the output printed?
SemaphoreHandle_t xSemaphore;
void task1(void *params) {
if (xSemaphoreTake(xSemaphore, 100 / portTICK_PERIOD_MS) == pdTRUE) {
printf("Semaphore taken by task1\n");
vTaskDelay(200 / portTICK_PERIOD_MS);
xSemaphoreGive(xSemaphore);
} else {
printf("Task1 failed to take semaphore\n");
}
vTaskDelete(NULL);
}
void task2(void *params) {
if (xSemaphoreTake(xSemaphore, 300 / portTICK_PERIOD_MS) == pdTRUE) {
printf("Semaphore taken by task2\n");
xSemaphoreGive(xSemaphore);
} else {
printf("Task2 failed to take semaphore\n");
}
vTaskDelete(NULL);
}
int main() {
xSemaphore = xSemaphoreCreateBinary();
xSemaphoreGive(xSemaphore); // Initial give to make semaphore available
xTaskCreate(task1, "Task1", 1000, NULL, 1, NULL);
xTaskCreate(task2, "Task2", 1000, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}Remember that the semaphore is initially given before tasks start, so the first task to take it will succeed.
The semaphore is initially given, so task1 can take it immediately. It holds it for 200ms, then gives it back. Task2 waits up to 300ms, so it can take the semaphore after task1 gives it back.
Given this code snippet, what will be printed?
SemaphoreHandle_t xSemaphore;
void task(void *params) {
if (xSemaphoreTake(xSemaphore, 50 / portTICK_PERIOD_MS) == pdTRUE) {
printf("Semaphore acquired\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
xSemaphoreGive(xSemaphore);
} else {
printf("Timeout waiting for semaphore\n");
}
vTaskDelete(NULL);
}
int main() {
xSemaphore = xSemaphoreCreateBinary();
// Note: semaphore is NOT given initially
xTaskCreate(task, "Task", 1000, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}The semaphore is created but never given before the task tries to take it.
The semaphore is created but never given, so the task waits 50ms and times out, printing the timeout message.
What error will this code cause when run?
SemaphoreHandle_t xSemaphore;
void task(void *params) {
xSemaphoreGive(xSemaphore);
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
printf("Semaphore taken\n");
}
vTaskDelete(NULL);
}
int main() {
// Semaphore is NOT created
xTaskCreate(task, "Task", 1000, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}Check if the semaphore is created before use.
The semaphore handle is never initialized by xSemaphoreCreateBinary(), so calling xSemaphoreGive() or xSemaphoreTake() on it causes undefined behavior, likely a crash.
In FreeRTOS, if you call xSemaphoreGive() multiple times on a binary semaphore without taking it, what happens?
Think about the nature of a binary semaphore as a flag.
A binary semaphore can only be 'given' once; extra calls to xSemaphoreGive() when it is already given do not increase the count beyond 1.
Two tasks increment a shared counter protected by a binary semaphore. What is the final value of sharedCounter after both tasks finish?
SemaphoreHandle_t xSemaphore; volatile int sharedCounter = 0; void task1(void *params) { for (int i = 0; i < 5; i++) { if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { sharedCounter++; xSemaphoreGive(xSemaphore); } vTaskDelay(10 / portTICK_PERIOD_MS); } vTaskDelete(NULL); } void task2(void *params) { for (int i = 0; i < 5; i++) { if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { sharedCounter++; xSemaphoreGive(xSemaphore); } vTaskDelay(15 / portTICK_PERIOD_MS); } vTaskDelete(NULL); } int main() { xSemaphore = xSemaphoreCreateBinary(); xSemaphoreGive(xSemaphore); // Make semaphore available xTaskCreate(task1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(task2, "Task2", 1000, NULL, 1, NULL); vTaskStartScheduler(); // After scheduler ends (in real system it won't), print value printf("Final sharedCounter: %d\n", sharedCounter); return 0; }
Each task increments 5 times, semaphore protects increments from race conditions.
Both tasks increment sharedCounter 5 times each, protected by the semaphore, so increments do not overlap or get lost. Total increments = 10.
