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 <28123637+alfred2g@users.noreply.github.com>
Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com>
diff --git a/include/list.h b/include/list.h
index 6f5d15d..ce3e51c 100644
--- a/include/list.h
+++ b/include/list.h
@@ -289,6 +289,86 @@
         ( 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

diff --git a/tasks.c b/tasks.c
index c7be57c..9ffbc4f 100644
--- a/tasks.c
+++ b/tasks.c
@@ -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 )

 /*-----------------------------------------------------------*/

 

@@ -2233,8 +2233,9 @@
                 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

@@ -2794,13 +2795,13 @@
                     }

 

                     /* 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

                     {

@@ -3127,7 +3128,7 @@
      * 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 );

 }

@@ -3151,7 +3152,7 @@
          * 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

@@ -3188,11 +3189,11 @@
      * 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 )

@@ -3213,7 +3214,7 @@
     {

         /* 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 )

@@ -3252,7 +3253,7 @@
      * 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 )

         {

@@ -3271,7 +3272,7 @@
     /* 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 )

@@ -4922,7 +4923,7 @@
              * 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. */

@@ -5069,14 +5070,14 @@
 

                 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 )

@@ -5160,14 +5161,14 @@
 

                 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 )

@@ -5303,7 +5304,7 @@
                 /* 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

             {