Advertisement

Semaphores: utility services and data structures

May 14, 2018

Colin Walls-May 14, 2018

This article continues the look at semaphores.

Semaphore Utility Services

Nucleus RTOS has four API calls which provide utility functions associated with semaphores: reset semaphore, return information about a semaphore, return number of semaphores in the application and return pointers to all semaphores in the application. The first three of these are implemented in Nucleus SE.

Resetting a Semaphore

This API call restores the semaphore to its initial, unused state. This API function is unusual, compared with that available for other kernel objects, as, although it is a reset, it does not simply initialize its counter to the start-up value; a new initial count is provided in the call. Any tasks which were suspended on the semaphore are resumed and receive a return code of NUSE_SEMAPHORE_WAS_RESET (in Nucleus SE, or NU_SEMAPHORE_RESET with Nucleus RTOS).

Nucleus RTOS API Call for Resetting a Semaphore

Service call prototype:

STATUS NU_Reset_Semaphore(NU_SEMAPHORE  *semaphore,
UNSIGNED initial_count);

Parameters:

semaphore – pointer to user-supplied semaphore control block

initial_count – the value to which the semaphore’s counter is to be set

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_SEMAPHORE – the semaphore pointer is not valid

Nucleus SE API Call for Resetting a Semaphore

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

STATUS NUSE_Semaphore_Reset(NUSE_SEMAPHORE semaphore,
U8 initial_count);

Parameters:

semaphore – the index (ID) of the semaphore to be reset

initial_count – the value to which the semaphore’s counter is to be set

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_SEMAPHORE – the semaphore index is not valid

Nucleus SE Implementation of Semaphore Reset

The main job of the NUSE_Semaphore_Reset() API function – after parameter checking – is to simply set the appropriate entry in NUSE_Semaphore_Counter[] to the provided initial value.

When blocking is enabled, further code is required to unblock tasks:

while (NUSE_Semaphore_Blocking_Count[semaphore] != 0)
{
    U8 index;           /* check whether any tasks are blocked */
                        /* on this semaphore */
 
    for (index=0; index<NUSE_TASK_NUMBER; index++)
    {
        if ((LONIB(NUSE_Task_Status[index]) ==
              NUSE_SEMAPHORE_SUSPEND)
             && (HINIB(NUSE_Task_Status[index]) == semaphore))
        {
            NUSE_Task_Blocking_Return[index] =
             NUSE_SEMAPHORE_WAS_RESET;
            NUSE_Task_Status[index] = NUSE_READY;
            break;
        }
    }
    NUSE_Semaphore_Blocking_Count[semaphore]--;
}
 
#if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER
    NUSE_Reschedule(NUSE_NO_TASK);
#endif


Each task suspended on the semaphore is marked as “ready” with a suspend return code of NUSE_SEMAPHORE_WAS_RESET. After this process is complete, if the Priority scheduler is in use, a call is made to NUSE_Reschedule(), as one or more higher priority tasks may have been readied and needs to be allowed to run.

Semaphore Information

This service call obtains a selection of information about a semaphore. The Nucleus SE implementation differs from Nucleus RTOS in that it returns less information, as object naming and suspend ordering are not supported and task suspend may not be enabled.

Nucleus RTOS API Call for Semaphore Information

Service call prototype:

STATUS NU_Semaphore_Information(NU_SEMAPHORE *semaphore,
CHAR *name, UNSIGNED *current_count, OPTION *suspend_type,
UNSIGNED *tasks_waiting, NU_TASK **first_task);

Parameters:

semaphore – pointer top the control block of the semaphore about which information is being requested

name - pointer to an 8-character destination area for the semaphore’s name; this includes space for the null terminator

current_count – a pointer to a variable, which will receive the current value of the semaphore counter

suspend_type - pointer to a variable that holds the task’s suspend type; valid task suspend types are NU_FIFO and NU_PRIORITY

tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this semaphore

first_task – a pointer to a variable of type NU_TASK which will receive a pointer to the control block of the first suspended task

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_SEMAPHORE – the semaphore pointer is not valid

Nucleus SE API Call for Semaphore Information

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

STATUS NUSE_Semaphore_Information(NUSE_SEMAPHORE semaphore,
U8 *current_count, U8 *tasks_waiting, NUSE_TASK *first_task);

Parameters:

semaphore – the index of the semaphore about which information is being requested

current_count – a pointer to a variable, which will receive the current value of the semaphore counter

tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this semaphore (nothing returned if task suspend is disabled)

first_task – a pointer to a variable of type NUSE_TASK which will receive the index of the first suspended task (nothing returned if task suspend is disabled)

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_SEMAPHORE – the semaphore index is not valid

NUSE_INVALID_POINTER – one or more of the pointer parameters is invalid

Nucleus SE Implementation of Semaphore Information

The implementation of this API call is quite straightforward:

NUSE_CS_Enter();
 
*current_count = NUSE_Semaphore_Counter[semaphore];
#if NUSE_BLOCKING_ENABLE
 
    *tasks_waiting = NUSE_Semaphore_Blocking_Count[semaphore];
    if (NUSE_Semaphore_Blocking_Count[semaphore] != 0)
    {
        U8 index;
 
        for (index=0; index<NUSE_TASK_NUMBER; index++)
        {
            if ((LONIB(NUSE_Task_Status[index]) ==
                  NUSE_SEMAPHORE_SUSPEND) &&
                 (HINIB(NUSE_Task_Status[index]) == semaphore))
            {
                *first_task = index;
                break;
            }
        }
    }
    else
    {
        *first_task = 0;
    }
 
#else
 
    *tasks_waiting = 0;
    *first_task = 0;
 
#endif
 
NUSE_CS_Exit();
 
return NUSE_SUCCESS;


The function returns the semaphore status. Then, if blocking API calls is enabled, the number of waiting tasks and the index of the first one are returned (otherwise these two parameters are set to 0).

Obtaining the Number of Semaphores

This service call returns the number of semaphores configured in the application. Whilst in Nucleus RTOS this will vary over time and the returned value will represent the current number of semaphores, in Nucleus SE the value returned is set at build time and cannot change.

Nucleus RTOS API Call for Semaphore Count

Service call prototype:

UNSIGNED NU_Established_Semaphores(VOID);

Parameters:

None

Returns:

The number of created semaphores in the application

Nucleus SE API Call for Semaphore Count

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

U8 NUSE_Semaphore_Count(void);

Parameters:

None

Returns:

The number of configured semaphores in the application

Nucleus SE Implementation of Semaphore Count

The implementation of this API call is almost trivially simple: the value of the #define symbol NUSE_SEMAPHORE_NUMBER is returned.

Continue to page two: "Data Structures" >>

 

< Previous
Page 1 of 2
Next >

Loading comments...