IPC@CHIP® RTOS-PPC – API Documentation
Semaphores are used to guarantee a task mutually exclusive access to a critical resource. Semaphores synchronize asynchronous occurring activities. They are an essential part of a multitasking system. A good description of multitasking systems and semaphores is available in the book "Operating systems" from Andrew Tanenbaum.
The IPC@CHIP® API provides two types of semaphores:
The counting and resource semaphores provide automatic timeout. Tasks can specify the maximum time for waiting on a semaphore. The tasks wait at specified priorities. Two task waiting at the same priority wait in FIFO order for a resource.
(For some cases, a third semaphore mechanism which is built into the PowerPC may be adequate for protecting access to 32 bit objects. See the set of atomic functions.)
A semaphore is created with the RTX_NewSem() API. This API on success returns a new semaphore ID (or handle) to the caller. This handle is needed for the other semaphore services.
A counting semaphore is created by specifying an initial count greater or equal to zero in the call to RTX_NewSem(). If a semaphore is initialized with a value n, it can be used to control access to n resources, e.g. a counting semaphore with the initial value three assures that no more than three tasks can own a resource at any one time. Access to a resource controlled by a counting semaphore is acquired with a call to RTX_Get_Sem(), RTX_Sem_Wait(), RTX_Sem_Timeout() RTX_Wait_Sem_Priority() API. If the resource is available the @CHIP-RTOS-PPC gives it to the task immediately. When the task is finished using the resource, it may signal its release by calling RTX_Signal_Sem().
The system provides two types of resource semaphores:
priorityparameter passed to the wait procedure. A task priority inversions may result if a high priority task is waiting in the queue for a resource semaphore owned by some very low priority task.
While the priority inheritance type resource semaphore may sound like the type you would always want to use, this is not the case due to rather severe restrictions on its use. When a task owns such a semaphore, the system will not allow it to sleep. It cannot block awaiting any object except for another priority inheritance type resource semaphore. The system will not permit (error code RTX_EC_SMUV returned) a task to block on a normal semaphore, Message Exchange or Event Group while the task owns a priority inheritance semaphore. So calling API such as serial ports or printf(), which result in normal semaphore accesses down inside the @CHIP-RTOS-PPC, would not be permitted while a task owns a priority inheritance semaphore.
Use of the priority inheritance type resource semaphore makes sense when the work done while owning the semaphore is very focused. For example, the malloc() function provided by the Beck C-Library uses a priority inheritance type resource semaphore around the heap accesses when the grow heap option is not selected.
A priority inheritance type semaphore must be used with extreme care. No @CHIP-RTOS-PPC API should be called when a task owns such a semaphore other than RTX_Release_Sem() or RTX_Free_Sem() API. To violate this rule can lead to undefined behavior.
A normal resource type semaphore is created with a -1 (RTX_RESOURCE_SEM_TYPE) and a priority inheritance type resource semaphore is created with a -2 (RTX_RESOURCE_SEM_PI_TYPE) for the initial count in the call of RTX_NewSem(). The API creates a resource semaphore and automatically gives it an initial value of one indicating that the resource is free. A resource is reserved by calling RTX_Get_Sem(), RTX_Sem_Wait(), RTX_Sem_Timeout() RTX_Wait_Sem_Priority() API with the semaphore ID returned by RTX_NewSem(). The resource is released with a call to either RTX_Release_Sem() or RTX_Free_Sem().
--- Resource Semaphore API ----
--- Counting Semaphore API ----