Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor optimisations to xTaskIncrementTick(). #241

80 changes: 80 additions & 0 deletions include/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,86 @@ typedef struct xLIST
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}

/*
* Version of uxListRemove() that does not return a value. Provided as a slight
* optimisation for xTaskIncrementTick() by being inline.
*
* Remove an item from a list. The list item has a pointer to the list that
* it is in, so only the list item need be passed into the function.
*
* @param uxListRemove The item to be removed. The item will remove itself from
* the list pointed to by it's pxContainer parameter.
*
* @return The number of items that remain in the list after the list item has
* been removed.
*
* \page listREMOVE_ITEM listREMOVE_ITEM
* \ingroup LinkedList
*/
#define listREMOVE_ITEM( pxItemToRemove ) \
{ \
/* The list item knows which list it is in. Obtain the list from the list \
* item. */ \
List_t * const pxList = ( pxItemToRemove )->pxContainer; \
\
( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \
( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \
/* Make sure the index is left pointing to a valid item. */ \
if( pxList->pxIndex == ( pxItemToRemove ) ) \
{ \
pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \
} \
\
( pxItemToRemove )->pxContainer = NULL; \
( pxList->uxNumberOfItems )--; \
}

/*
* Inline version of vListInsertEnd() to provide slight optimisation for
* xTaskIncrementTick().
*
* Insert a list item into a list. The item will be inserted in a position
* such that it will be the last item within the list returned by multiple
* calls to listGET_OWNER_OF_NEXT_ENTRY.
*
* The list member pxIndex is used to walk through a list. Calling
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
* Placing an item in a list using vListInsertEnd effectively places the item
* in the list position pointed to by pxIndex. This means that every other
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
* the pxIndex parameter again points to the item being inserted.
*
* @param pxList The list into which the item is to be inserted.
*
* @param pxNewListItem The list item to be inserted into the list.
*
* \page listINSERT_END listINSERT_END
* \ingroup LinkedList
*/
#define listINSERT_END( pxList, pxNewListItem ) \
{ \
ListItem_t * const pxIndex = ( pxList )->pxIndex; \
\
/* Only effective when configASSERT() is also defined, these tests may catch \
* the list data structures being overwritten in memory. They will not catch \
* data errors caused by incorrect configuration or use of FreeRTOS. */ \
listTEST_LIST_INTEGRITY( ( pxList ) ); \
listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \
\
/* Insert a new list item into ( pxList ), but rather than sort the list, \
* makes the new list item the last item to be removed by a call to \
* listGET_OWNER_OF_NEXT_ENTRY(). */ \
( pxNewListItem )->pxNext = pxIndex; \
( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \
\
pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \
pxIndex->pxPrevious = ( pxNewListItem ); \
\
/* Remember which list the item is in. */ \
( pxNewListItem )->pxContainer = ( pxList ); \
\
( ( pxList )->uxNumberOfItems )++; \
}

/*
* Access function to obtain the owner of the first entry in a list. Lists
Expand Down
37 changes: 19 additions & 18 deletions tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
#define prvAddTaskToReadyList( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
/*-----------------------------------------------------------*/

Expand Down Expand Up @@ -2233,8 +2233,9 @@ BaseType_t xTaskResumeAll( void )
while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
{
pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
portMEMORY_BARRIER();
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );

/* If the moved task has a priority higher than or equal to
Expand Down Expand Up @@ -2794,13 +2795,13 @@ BaseType_t xTaskIncrementTick( void )
}

/* It is time to remove the item from the Blocked state. */
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );

/* Is the task waiting on an event also? If so remove
* it from the event list. */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
}
else
{
Expand Down Expand Up @@ -3127,7 +3128,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
* event group implementation - and interrupts don't access event groups
* directly (instead they access them indirectly by pending function calls to
* the task level). */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );

prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
}
Expand All @@ -3151,7 +3152,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
* In this case it is assume that this is the only task that is going to
* be waiting on this event list, so the faster vListInsertEnd() function
* can be used in place of vListInsert. */
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );

/* If the task should block indefinitely then set the block time to a
* value that will be recognised as an indefinite delay inside the
Expand Down Expand Up @@ -3188,11 +3189,11 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
* pxEventList is not empty. */
pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
configASSERT( pxUnblockedTCB );
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );

if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );

#if ( configUSE_TICKLESS_IDLE != 0 )
Expand All @@ -3213,7 +3214,7 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
{
/* The delayed and ready lists cannot be accessed, so hold this task
* pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
}

if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
Expand Down Expand Up @@ -3252,7 +3253,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
* event flags. */
pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
configASSERT( pxUnblockedTCB );
( void ) uxListRemove( pxEventListItem );
listREMOVE_ITEM( pxEventListItem );

#if ( configUSE_TICKLESS_IDLE != 0 )
{
Expand All @@ -3271,7 +3272,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
/* Remove the task from the delayed list and add it to the ready list. The
* scheduler is suspended so interrupts will not be accessing the ready
* lists. */
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );

if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
Expand Down Expand Up @@ -4922,7 +4923,7 @@ TickType_t uxTaskResetEventItemValue( void )
* notification then unblock it now. */
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );

/* The task should not have been on an event list. */
Expand Down Expand Up @@ -5069,14 +5070,14 @@ TickType_t uxTaskResetEventItemValue( void )

if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
{
/* The delayed and ready lists cannot be accessed, so hold
* this task pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}

if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
Expand Down Expand Up @@ -5160,14 +5161,14 @@ TickType_t uxTaskResetEventItemValue( void )

if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
{
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
else
{
/* The delayed and ready lists cannot be accessed, so hold
* this task pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}

if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
Expand Down Expand Up @@ -5303,7 +5304,7 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
/* Add the task to the suspended task list instead of a delayed task
* list to ensure it is not woken by a timing event. It will block
* indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
Expand Down