In GeMRTOS on Altera FPGA platforms with Nios V processors, a semaphore is a resource for preventing concurrent execution of code sections. GeMRTOS supports binary semaphores, counting semaphores, and (built on the same underlying resource) mutexes — see the companion article on Mutex and Critical Sections for mutex-specific creation and usage. When a task requests a semaphore, access is granted only if the current count is greater than 0 — granting decrements the count; releasing increments it. Requests can be configured as blocking (with an optional timeout) or non-blocking.
Semaphore API Reference #
Creating a Semaphore #
GeMRTOS provides a dedicated creation function per semaphore kind, rather than a single generic constructor:
GS_RCB *gu_SemaphoreCreateCounting(int max_count, int initial_count);
GS_RCB *gu_SemaphoreCreateBinary(int initial_count);gu_SemaphoreCreateCounting allocates a counting semaphore, letting up to max_count tasks hold it concurrently, starting at initial_count. gu_SemaphoreCreateBinary allocates a binary semaphore (0 = empty, 1 = available) — equivalent to a counting semaphore with max_count = 1, exposed as its own function for clarity at the call site. Both build on the same GS_RCB structure, with T_SEMAPHORE_RESOURCE fields appended, and both must be called before any gu_SemaphoreTake/gu_SemaphoreGive call on that resource.
| Parameter | Description |
|---|---|
max_count | (Counting only) The maximum count value the semaphore can reach — once at this value, it can no longer be given. |
initial_count | The count assigned to the semaphore when created. |
Returns: a handle (GS_RCB *) to the newly created semaphore, used in all subsequent calls, or NULL if creation failed.
Requesting (Taking) a Semaphore #
G_UINT32 gu_SemaphoreTake(GS_RCB *presource, G_UINT64 ticks_to_wait);gu_SemaphoreTake requests a semaphore. If the current count is greater than 0, it is granted and the count is decremented. If the count is 0, the calling task is suspended until the semaphore becomes available or ticks_to_wait elapses.
| Parameter | Description |
|---|---|
presource | Handle returned by a gu_SemaphoreCreate* function. |
ticks_to_wait | Time to wait, in system ticks. Pass 0 to return immediately without blocking; pass G_LATEST_TIME to wait indefinitely. |
Returns: G_TRUE if the semaphore was granted, G_FALSE if it was unavailable and the timeout elapsed.
Releasing (Giving) a Semaphore #
G_UINT32 gu_SemaphoreGive(GS_RCB *presource);gu_SemaphoreGive releases a held semaphore. If one or more tasks are waiting, the highest-priority waiting task is granted it directly; otherwise the count is simply incremented.
| Parameter | Description |
|---|---|
presource | Handle returned by a gu_SemaphoreCreate* function. |
Returns: G_TRUE on success, G_FALSE otherwise.
Destroying a Semaphore #
G_UINT32 gu_SemaphoreDestroy(GS_RCB *psemaphore);gu_SemaphoreDestroy returns a semaphore’s GS_RCB to the free pool. It fails (returns G_FALSE) if any task currently holds or is waiting on it — a semaphore must be idle before it can be destroyed.
T_SEMAPHORE_RESOURCE Structure #
The T_SEMAPHORE_RESOURCE structure is embedded as the semaphore field within a GS_RCB resource. Access its fields using: (GS_RCB *)->semaphore.<field>
Structure Fields #
| Type | Field | Description |
|---|---|---|
TIMEPRIORITY | SEM_GrantedPriority | Priority assigned to the task the semaphore is granted to. |
G_UINT32 | SEM_Current_Count | Current count. When 0, no more grants are allowed. Initialized to SEM_Maximum_Count at creation. |
G_UINT32 | SEM_Maximum_Count | Maximum number of times the semaphore can be taken. |
G_UINT32 | SEM_Recurrence | For a recursive mutex, the number of times it has been taken by its current holder. |
Key Takeaways #
- Each semaphore kind has its own creation function — gu_SemaphoreCreateCounting, gu_SemaphoreCreateBinary, and (for mutexes) gu_SemaphoreCreateMutex / gu_SemaphoreCreateRecursiveMutex — rather than one generic constructor with a mode flag.
- gu_SemaphoreTake blocks the calling task, at its own priority, for up to
ticks_to_waitsystem ticks; pass0for a non-blocking attempt orG_LATEST_TIMEto wait indefinitely. - gu_SemaphoreGive always grants the highest-priority waiting task first; if none is waiting, it just increments the count.
- A semaphore must be created before any
gu_SemaphoreTake/gu_SemaphoreGivecall on it — creating one from inside a task is fine as long as it happens before any task’s first use of it. - gu_SemaphoreDestroy returns a semaphore to the free pool, but only once it’s idle (no holder, no waiters).
- The T_SEMAPHORE_RESOURCE structure (via
(GS_RCB *)->semaphore.field) exposesSEM_Current_Count,SEM_GrantedPriority, and — for recursive mutexes —SEM_Recurrencefor runtime inspection.