Skip to content

Commit 6bf3a75

Browse files
RichardBarryalfred2gAniruddhaKanhere
authored
Create macro versions of uxListRemove() and vListInsertEnd() for use in xTaskIncrementTick(). This provides a minor optimisation to remove the need for a few function calls. (#241)
Co-authored-by: alfred gedeon <[email protected]> Co-authored-by: Aniruddha Kanhere <[email protected]>
1 parent 71f5af4 commit 6bf3a75

File tree

2 files changed

+99
-18
lines changed

2 files changed

+99
-18
lines changed

include/list.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,86 @@ typedef struct xLIST
289289
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
290290
}
291291

292+
/*
293+
* Version of uxListRemove() that does not return a value. Provided as a slight
294+
* optimisation for xTaskIncrementTick() by being inline.
295+
*
296+
* Remove an item from a list. The list item has a pointer to the list that
297+
* it is in, so only the list item need be passed into the function.
298+
*
299+
* @param uxListRemove The item to be removed. The item will remove itself from
300+
* the list pointed to by it's pxContainer parameter.
301+
*
302+
* @return The number of items that remain in the list after the list item has
303+
* been removed.
304+
*
305+
* \page listREMOVE_ITEM listREMOVE_ITEM
306+
* \ingroup LinkedList
307+
*/
308+
#define listREMOVE_ITEM( pxItemToRemove ) \
309+
{ \
310+
/* The list item knows which list it is in. Obtain the list from the list \
311+
* item. */ \
312+
List_t * const pxList = ( pxItemToRemove )->pxContainer; \
313+
\
314+
( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \
315+
( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \
316+
/* Make sure the index is left pointing to a valid item. */ \
317+
if( pxList->pxIndex == ( pxItemToRemove ) ) \
318+
{ \
319+
pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \
320+
} \
321+
\
322+
( pxItemToRemove )->pxContainer = NULL; \
323+
( pxList->uxNumberOfItems )--; \
324+
}
325+
326+
/*
327+
* Inline version of vListInsertEnd() to provide slight optimisation for
328+
* xTaskIncrementTick().
329+
*
330+
* Insert a list item into a list. The item will be inserted in a position
331+
* such that it will be the last item within the list returned by multiple
332+
* calls to listGET_OWNER_OF_NEXT_ENTRY.
333+
*
334+
* The list member pxIndex is used to walk through a list. Calling
335+
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
336+
* Placing an item in a list using vListInsertEnd effectively places the item
337+
* in the list position pointed to by pxIndex. This means that every other
338+
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
339+
* the pxIndex parameter again points to the item being inserted.
340+
*
341+
* @param pxList The list into which the item is to be inserted.
342+
*
343+
* @param pxNewListItem The list item to be inserted into the list.
344+
*
345+
* \page listINSERT_END listINSERT_END
346+
* \ingroup LinkedList
347+
*/
348+
#define listINSERT_END( pxList, pxNewListItem ) \
349+
{ \
350+
ListItem_t * const pxIndex = ( pxList )->pxIndex; \
351+
\
352+
/* Only effective when configASSERT() is also defined, these tests may catch \
353+
* the list data structures being overwritten in memory. They will not catch \
354+
* data errors caused by incorrect configuration or use of FreeRTOS. */ \
355+
listTEST_LIST_INTEGRITY( ( pxList ) ); \
356+
listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \
357+
\
358+
/* Insert a new list item into ( pxList ), but rather than sort the list, \
359+
* makes the new list item the last item to be removed by a call to \
360+
* listGET_OWNER_OF_NEXT_ENTRY(). */ \
361+
( pxNewListItem )->pxNext = pxIndex; \
362+
( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \
363+
\
364+
pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \
365+
pxIndex->pxPrevious = ( pxNewListItem ); \
366+
\
367+
/* Remember which list the item is in. */ \
368+
( pxNewListItem )->pxContainer = ( pxList ); \
369+
\
370+
( ( pxList )->uxNumberOfItems )++; \
371+
}
292372

293373
/*
294374
* Access function to obtain the owner of the first entry in a list. Lists

tasks.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@
219219
#define prvAddTaskToReadyList( pxTCB ) \
220220
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
221221
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
222-
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
222+
listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
223223
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
224224
/*-----------------------------------------------------------*/
225225

@@ -2233,8 +2233,9 @@ BaseType_t xTaskResumeAll( void )
22332233
while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
22342234
{
22352235
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. */
2236-
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
2237-
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
2236+
listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
2237+
portMEMORY_BARRIER();
2238+
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
22382239
prvAddTaskToReadyList( pxTCB );
22392240

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

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

27992800
/* Is the task waiting on an event also? If so remove
28002801
* it from the event list. */
28012802
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
28022803
{
2803-
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
2804+
listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
28042805
}
28052806
else
28062807
{
@@ -3127,7 +3128,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
31273128
* event group implementation - and interrupts don't access event groups
31283129
* directly (instead they access them indirectly by pending function calls to
31293130
* the task level). */
3130-
vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3131+
listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
31313132

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

31563157
/* If the task should block indefinitely then set the block time to a
31573158
* value that will be recognised as an indefinite delay inside the
@@ -3188,11 +3189,11 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
31883189
* pxEventList is not empty. */
31893190
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. */
31903191
configASSERT( pxUnblockedTCB );
3191-
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
3192+
listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
31923193

31933194
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
31943195
{
3195-
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
3196+
listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
31963197
prvAddTaskToReadyList( pxUnblockedTCB );
31973198

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

32193220
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
@@ -3252,7 +3253,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
32523253
* event flags. */
32533254
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. */
32543255
configASSERT( pxUnblockedTCB );
3255-
( void ) uxListRemove( pxEventListItem );
3256+
listREMOVE_ITEM( pxEventListItem );
32563257

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

32773278
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
@@ -4922,7 +4923,7 @@ TickType_t uxTaskResetEventItemValue( void )
49224923
* notification then unblock it now. */
49234924
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
49244925
{
4925-
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
4926+
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
49264927
prvAddTaskToReadyList( pxTCB );
49274928

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

50705071
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
50715072
{
5072-
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
5073+
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
50735074
prvAddTaskToReadyList( pxTCB );
50745075
}
50755076
else
50765077
{
50775078
/* The delayed and ready lists cannot be accessed, so hold
50785079
* this task pending until the scheduler is resumed. */
5079-
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
5080+
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
50805081
}
50815082

50825083
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
@@ -5160,14 +5161,14 @@ TickType_t uxTaskResetEventItemValue( void )
51605161

51615162
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
51625163
{
5163-
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
5164+
listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
51645165
prvAddTaskToReadyList( pxTCB );
51655166
}
51665167
else
51675168
{
51685169
/* The delayed and ready lists cannot be accessed, so hold
51695170
* this task pending until the scheduler is resumed. */
5170-
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
5171+
listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
51715172
}
51725173

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

0 commit comments

Comments
 (0)