Course contentsShow
← Embedded Systems & Computer Architecture
Lesson 528 of 9367. Real-Time Operating Systems (RTOS)Free lesson

Managing Resource Availability With Counting Semaphores

Utilize counting semaphores to regulate access to a pool of multiple identical resources shared among several real-time tasks.

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.

  1. Initialization: You initialize the semaphore with the total count of available resources (e.g., 5).
  2. Acquisition (wait): When a task needs a resource, it performs a wait operation. 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.
  3. Release (signal): When the task finishes, it performs a signal operation, 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.