In this lesson, you will learn how to use counting semaphores to manage a fixed pool of identical shared resources among multiple competing real-time tasks.
The Problem: Managing Resource Pools
While a Mutex (which you learned about in lesson 25) is designed for mutual exclusion—ensuring only one task accesses a unique resource at a time—it fails when you have a pool of identical resources. For example, consider an embedded system with five identical UART ports or a buffer pool containing ten memory blocks. If you use a mutex, you artificially limit throughput by forcing tasks to wait for one specific resource, even if others are available.
The Counting Semaphore Solution
A counting semaphore acts like a digital "token bucket." Instead of a binary state (locked/unlocked), it maintains an integer value representing the number of available resources.
- Initialization: You initialize the semaphore with the total count of available resources (e.g.,
5). - Acquisition (
wait): When a task needs a resource, it performs awaitoperation. If the semaphore count is greater than zero, the task decrements the count and proceeds. If the count is zero, the task blocks until another task releases a resource. - Release (
signal): When the task finishes, it performs asignaloperation, incrementing the semaphore count and waking any tasks waiting in the queue.
Practical Implementation
Imagine managing a buffer of three hardware DMA channels:
// Initialize with 3 available DMA channels
SemaphoreHandle_t dmaSemaphore = xSemaphoreCreateCounting(3, 3);
void Task_UseDMA(void *pvParameters) {
while(1) {
// Attempt to acquire one of the 3 channels
if (xSemaphoreTake(dmaSemaphore, portMAX_DELAY) == pdTRUE) {
// Success: Access the DMA hardware
PerformTransfer();
// Release back to the pool
xSemaphoreGive(dmaSemaphore);
}
}
}
By using the counting semaphore, you allow up to three tasks to operate concurrently. Once the pool is exhausted, the RTOS scheduler efficiently puts subsequent tasks into a "Blocked" state, preventing them from consuming CPU cycles while waiting for an available channel.
Key Takeaway: Counting semaphores track the quantity of available resources, allowing multiple tasks to share a pool of identical hardware or software objects efficiently without bottlenecking at a single gate.