Counting semaphores are synchronization primitives used to manage access to a shared resource. They allow a specified number of tasks to access the resource concurrently.
The osCreateCountSem function creates a counting semaphore object. A counting semaphore can be initialized before the system starts, within an interrupt handler, or by a task. During creation, an optional object name may be specified, allowing tasks to open the semaphore using the osOpenCountSem function. Both creation and opening return a handle assigned by the system to identify the object. All subsequent operations on the counting semaphore require this handle. When a semaphore is no longer needed, it should be closed with osCloseHandle. The counting semaphore is deleted only after it has been closed by all tasks that held an open handle. For more information, refer to the system objects management section.
If counting semaphores are not required, the OS_USE_CNT_SEM constant may be set to 0 to reduce the final binary size.
A counting semaphore maintains an internal counter that is decremented each time a task acquires the semaphore and incremented when the task releases it. The semaphore enters a non-signaled state when the counter reaches zero. Both the maximum and initial counter values are defined during creation, with the initial value not exceeding the maximum. To acquire a counting semaphore, a task must execute a wait operation, such as osWaitForObject or osWaitForObjects. A task can release the semaphore at any time using the osReleaseSemaphore function.
Counting semaphores are not intended for protecting critical sections, as they do not provide priority inversion avoidance mechanisms. Use a standard semaphore if priority inheritance is required.
If multiple tasks are waiting for a semaphore, the task with the highest priority will be the first to acquire it. If all waiting tasks have a lower priority than the task that just released the semaphore, they will proceed when they become ready to run. If a task with a higher priority (including the task that just released the semaphore) starts waiting, it will acquire the semaphore immediately due to its priority. Tasks with equal or lower priority are appended to the end of the pending queue.