CMSIS-RTOS2  Version 2.1.0
Real-Time Operating System: API and RTX Reference Implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Semaphores

Access shared resources simultaneously from different threads. More...

Data Structures

struct  osSemaphoreAttr_t
 Attributes structure for semaphore. More...
 

Typedefs

typedef void * osSemaphoreId_t
 

Functions

osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
 Create and Initialize a Semaphore object. More...
 
const char * osSemaphoreGetName (osSemaphoreId_t semaphore_id)
 Get name of a Semaphore object. More...
 
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout)
 Acquire a Semaphore token or timeout if no tokens are available. More...
 
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id)
 Release a Semaphore token that was acquired by osSemaphoreAcquire. More...
 
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id)
 Get current Semaphore token count. More...
 
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id)
 Delete a Semaphore object. More...
 

Description

Semaphores are used to manage and protect access to shared resources. Semaphores are very similar to Mutexes. Whereas a Mutex permits just one thread to access a shared resource at a time, a semaphore can be used to permit a fixed number of threads/ISRs to access a pool of shared resources. Using semaphores, access to a group of identical peripherals can be managed (for example multiple DMA channels).

Semaphore.png
CMSIS-RTOS Semaphore

A semaphore object should be initialized to the maximum number of available tokens. This number of available resources is specified as parameter of the osSemaphoreNew function. Each time a semaphore token is obtained with osSemaphoreAcquire, the semaphore count is decremented. When the semaphore count is 0, no semaphore token can be obtained. The thread/ISR that tries to obtain the semaphore token needs to wait until the next token is free. Semaphores are released with osSemaphoreRelease incrementing the semaphore count.

Note
The functions osSemaphoreAcquire, osSemaphoreGetCount, and osSemaphoreRelease can be called from Interrupt Service Routines.
Refer to Semaphore Configuration for RTX5 configuration options.

Semaphore Use Cases

Due to their flexibility, semaphores cover a wide range of synchronizing applications. At the same time, they are perhaps the most challenging RTOS object to understand. The following explains a use case for semaphores, taken from the book The Little Book Of Semaphores by Allen B. Downey which is available for free download.

Non-binary Semaphore (Multiplex)

A multiplex limits the number of threads that can access a critical section of code. For example, this could be a function accessing DMA resources which can only support a limited number of calls.

To allow multiple threads to run the function, initialize a semaphore to the maximum number of threads that can be allowed. The number of tokens in the semaphore represents the number of additional threads that may enter. If this number is zero, then the next thread trying to access the function will have to wait until one of the other threads exits and releases its token. When all threads have exited the token number is back to n. The following example shows the code for one of the threads that might access the resource:

osSemaphoreId_t multiplex_id;
void thread_n (void)
{
multiplex_id = osSemaphoreNew(3, 3, NULL);
while(1)
{
// do something
osSemaphoreRelease(multiplex_id);
}
}

Data Structure Documentation

struct osSemaphoreAttr_t
Data Fields
const char * name name of the semaphore
uint32_t attr_bits attribute bits
void * cb_mem memory for control block
uint32_t cb_size size of provided memory for control block

Typedef Documentation

Semaphore ID identifies the semaphore.

Function Documentation

osSemaphoreId_t osSemaphoreNew ( uint32_t  max_count,
uint32_t  initial_count,
const osSemaphoreAttr_t attr 
)
Parameters
[in]max_countmaximum number of available tokens.
[in]initial_countinitial number of available tokens.
[in]attrsemaphore attributes; NULL: default values.
Returns
semaphore ID for reference by other functions or NULL in case of error.

The function osSemaphoreNew creates and initializes a semaphore object that is used to manage access to shared resources and returns the pointer to the semaphore object identifier or NULL in case of an error.

The parameter max_count specifies the maximum number of available tokens. A max_count value of 1 creates a binary semaphore.

The parameter initial_count sets the initial number of available tokens.

The parameter attr specifies additional semaphore attributes. Default attributes will be used if set to NULL.

Note
This function cannot be called from Interrupt Service Routines.

Code Example

#include "cmsis_os2.h" // CMSIS RTOS header file
void Thread_Semaphore (void *argument); // thread function
osThreadId_t tid_Thread_Semaphore; // thread id
osSemaphoreId_t sid_Thread_Semaphore; // semaphore id
int Init_Semaphore (void)
{
sid_Thread_Semaphore = osSemaphoreNew(2, 2, NULL);
if (!sid_Thread_Semaphore) {
; // Semaphore object not created, handle failure
}
tid_Thread_Semaphore = osThreadNew (Thread_Semaphore, NULL, NULL);
if (!tid_Thread_Semaphore) {
return(-1);
}
return(0);
}
void Thread_Semaphore (void *argument)
{
while (1) {
; // Insert thread code here...
val = osSemaphoreAcquire (sid_Thread_Semaphore, 10); // wait 10 mSec
switch (val) {
case osOK:
; // Use protected code here...
osSemaphoreRelease (sid_Thread_Semaphore); // Return a token back to a semaphore
break;
break;
break;
default:
break;
}
osThreadYield (); // suspend thread
}
}
const char * osSemaphoreGetName ( osSemaphoreId_t  semaphore_id)
Parameters
[in]semaphore_idsemaphore ID obtained by osSemaphoreNew.
Returns
name as NULL terminated string.

The function osSemaphoreGetName returns the pointer to the name string of the semaphore identified by parameter semaphore_id or NULL in case of an error.

Note
This function cannot be called from Interrupt Service Routines.
osStatus_t osSemaphoreAcquire ( osSemaphoreId_t  semaphore_id,
uint32_t  timeout 
)
Parameters
[in]semaphore_idsemaphore ID obtained by osSemaphoreNew.
[in]timeoutTimeout Value or 0 in case of no time-out.
Returns
status code that indicates the execution status of the function.

The blocking function osSemaphoreAcquire waits until a token of the semaphore object specified by parameter semaphore_id becomes available. If a token is available, the function instantly returns and decrements the token count.

The parameter timeout specifies how long the system waits to acquire the token. While the system waits, the thread/ISR that is calling this function is put into the BLOCKED state. The parameter timeout can have the following values:

  • when timeout is 0, the function returns instantly.
  • when timeout is set to osWaitForever the function will wait for an infinite time until the semaphore becomes available.
  • all other values specify a time in kernel ticks for a timeout.

Possible osStatus_t return values:

  • osOK: the token has been obtained.
  • osErrorTimeout: the token could not be obtained in the given time.
  • osErrorResource: the token could not be obtained when no timeout was specified.
  • osErrorParameter: the parameter semaphore_id is incorrect.
Note
May be called from Interrupt Service Routines if the parameter timeout is set to 0.

Code Example

Refer to osSemaphoreNew.

osStatus_t osSemaphoreRelease ( osSemaphoreId_t  semaphore_id)
Parameters
[in]semaphore_idsemaphore ID obtained by osSemaphoreNew.
Returns
status code that indicates the execution status of the function.

The function osSemaphoreRelease releases a token of the semaphore object specified by parameter semaphore_id. Other threads/ISRs that currently wait for a token of this semaphore object will be put into the READY state.

Possible osStatus_t return values:

  • osOK: the token has been correctly released and the count increased.
  • osErrorResource: the maximum token count has been reached.
  • osErrorParameter: the parameter semaphore_id is incorrect.
Note
This function may be called from Interrupt Service Routines.

Code Example

Refer to osSemaphoreNew.

uint32_t osSemaphoreGetCount ( osSemaphoreId_t  semaphore_id)
Parameters
[in]semaphore_idsemaphore ID obtained by osSemaphoreNew.
Returns
number of tokens available.

The function osSemaphoreGetCount returns the count of available semaphores of the semaphore object specified by parameter semaphore_id. In case of an error, it returns 0.

Note
This function may be called from Interrupt Service Routines.
osStatus_t osSemaphoreDelete ( osSemaphoreId_t  semaphore_id)
Parameters
[in]semaphore_idsemaphore ID obtained by osSemaphoreNew.
Returns
status code that indicates the execution status of the function.

The function osSemaphoreDelete deletes a semaphore object specified by parameter semaphore_id. It releases internal memory obtained for semaphore handling. After this call, the semaphore_id is no longer valid and cannot be used. The semaphore may be created again using the function osSemaphoreNew.

Possible osStatus_t return values:

  • osOK: the semaphore object has been deleted.
  • osErrorParameter: the parameter semaphore_id is NULL or invalid.
  • osErrorResource: the semaphore specified by parameter semaphore_id is in an invalid semaphore state.
  • osErrorISR: osSemaphoreDelete cannot be called from interrupt service routines.
Note
This function cannot be called from Interrupt Service Routines.