]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
Create minor optimisations (just an asm instruction or two) by using consts in a...
[freertos] / FreeRTOS / Source / tasks.c
index fdcc8f349df0369f698e599965c97b929d0ee536..a93fedcdf01d8e5e01e5d52131c727fe1548493c 100644 (file)
@@ -153,16 +153,19 @@ functions but without including stdio.h here. */
 \r
        #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                                      \\r
        {                                                                                                                                                                                                       \\r
+       UBaseType_t uxTopPriority = uxTopReadyPriority;                                                                                                         \\r
+                                                                                                                                                                                                               \\r
                /* Find the highest priority queue that contains ready tasks. */                                                                \\r
-               while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )                                              \\r
+               while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) )                                                   \\r
                {                                                                                                                                                                                               \\r
-                       configASSERT( uxTopReadyPriority );                                                                                                                     \\r
-                       --uxTopReadyPriority;                                                                                                                                           \\r
+                       configASSERT( uxTopPriority );                                                                                                                          \\r
+                       --uxTopPriority;                                                                                                                                                        \\r
                }                                                                                                                                                                                               \\r
                                                                                                                                                                                                                \\r
                /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of                                                \\r
                the     same priority get an equal share of the processor time. */                                                                      \\r
-               listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );              \\r
+               listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );                   \\r
+               uxTopReadyPriority = uxTopPriority;                                                                                                                             \\r
        } /* taskSELECT_HIGHEST_PRIORITY_TASK */\r
 \r
        /*-----------------------------------------------------------*/\r
@@ -354,7 +357,7 @@ PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;                         /*< Points to the
 PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;            /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */\r
 PRIVILEGED_DATA static List_t xPendingReadyList;                                               /*< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready list when the scheduler is resumed. */\r
 \r
-#if( ( INCLUDE_vTaskDelete == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
+#if( INCLUDE_vTaskDelete == 1 )\r
 \r
        PRIVILEGED_DATA static List_t xTasksWaitingTermination;                         /*< Tasks that have been deleted - but their memory not yet freed. */\r
        PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;\r
@@ -559,12 +562,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
                configASSERT( puxStackBuffer != NULL );\r
                configASSERT( pxTaskBuffer != NULL );\r
 \r
-               /* The memory used for the task's TCB and stack are passed into this\r
-               function - use them. */\r
-               pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
-\r
-               if( pxNewTCB != NULL )\r
+               if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )\r
                {\r
+                       /* The memory used for the task's TCB and stack are passed into this\r
+                       function - use them. */\r
+                       pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
                        pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;\r
 \r
                        #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
@@ -1955,24 +1957,30 @@ BaseType_t xAlreadyYielded = pdFALSE;
                                they should be processed now.  This ensures the tick count does\r
                                not     slip, and that any delayed tasks are resumed at the correct\r
                                time. */\r
-                               if( uxPendedTicks > ( UBaseType_t ) 0U )\r
                                {\r
-                                       while( uxPendedTicks > ( UBaseType_t ) 0U )\r
+                                       UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */\r
+\r
+                                       if( uxPendedCounts > ( UBaseType_t ) 0U )\r
                                        {\r
-                                               if( xTaskIncrementTick() != pdFALSE )\r
-                                               {\r
-                                                       xYieldPending = pdTRUE;\r
-                                               }\r
-                                               else\r
+                                               do\r
                                                {\r
-                                                       mtCOVERAGE_TEST_MARKER();\r
-                                               }\r
-                                               --uxPendedTicks;\r
+                                                       if( xTaskIncrementTick() != pdFALSE )\r
+                                                       {\r
+                                                               xYieldPending = pdTRUE;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               mtCOVERAGE_TEST_MARKER();\r
+                                                       }\r
+                                                       --uxPendedCounts;\r
+                                               } while( uxPendedCounts > ( UBaseType_t ) 0U );\r
+\r
+                                               uxPendedTicks = 0;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               mtCOVERAGE_TEST_MARKER();\r
                                        }\r
-                               }\r
-                               else\r
-                               {\r
-                                       mtCOVERAGE_TEST_MARKER();\r
                                }\r
 \r
                                if( xYieldPending != pdFALSE )\r
@@ -2389,103 +2397,101 @@ BaseType_t xSwitchRequired = pdFALSE;
        traceTASK_INCREMENT_TICK( xTickCount );\r
        if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
        {\r
+               /* Minor optimisation.  The tick count cannot change in this\r
+               block. */\r
+               const TickType_t xConstTickCount = xTickCount + 1;\r
+\r
                /* Increment the RTOS tick, switching the delayed and overflowed\r
                delayed lists if it wraps to 0. */\r
-               ++xTickCount;\r
+               xTickCount = xConstTickCount;\r
 \r
+               if( xConstTickCount == ( TickType_t ) 0U )\r
                {\r
-                       /* Minor optimisation.  The tick count cannot change in this\r
-                       block. */\r
-                       const TickType_t xConstTickCount = xTickCount;\r
-\r
-                       if( xConstTickCount == ( TickType_t ) 0U )\r
-                       {\r
-                               taskSWITCH_DELAYED_LISTS();\r
-                       }\r
-                       else\r
-                       {\r
-                               mtCOVERAGE_TEST_MARKER();\r
-                       }\r
+                       taskSWITCH_DELAYED_LISTS();\r
+               }\r
+               else\r
+               {\r
+                       mtCOVERAGE_TEST_MARKER();\r
+               }\r
 \r
-                       /* See if this tick has made a timeout expire.  Tasks are stored in\r
-                       the     queue in the order of their wake time - meaning once one task\r
-                       has been found whose block time has not expired there is no need to\r
-                       look any further down the list. */\r
-                       if( xConstTickCount >= xNextTaskUnblockTime )\r
+               /* See if this tick has made a timeout expire.  Tasks are stored in\r
+               the     queue in the order of their wake time - meaning once one task\r
+               has been found whose block time has not expired there is no need to\r
+               look any further down the list. */\r
+               if( xConstTickCount >= xNextTaskUnblockTime )\r
+               {\r
+                       for( ;; )\r
                        {\r
-                               for( ;; )\r
+                               if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
+                               {\r
+                                       /* The delayed list is empty.  Set xNextTaskUnblockTime\r
+                                       to the maximum possible value so it is extremely\r
+                                       unlikely that the\r
+                                       if( xTickCount >= xNextTaskUnblockTime ) test will pass\r
+                                       next time through. */\r
+                                       xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
+                                       break;\r
+                               }\r
+                               else\r
                                {\r
-                                       if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
+                                       /* The delayed list is not empty, get the value of the\r
+                                       item at the head of the delayed list.  This is the time\r
+                                       at which the task at the head of the delayed list must\r
+                                       be removed from the Blocked state. */\r
+                                       pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );\r
+                                       xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );\r
+\r
+                                       if( xConstTickCount < xItemValue )\r
                                        {\r
-                                               /* The delayed list is empty.  Set xNextTaskUnblockTime\r
-                                               to the maximum possible value so it is extremely\r
-                                               unlikely that the\r
-                                               if( xTickCount >= xNextTaskUnblockTime ) test will pass\r
-                                               next time through. */\r
-                                               xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
+                                               /* It is not time to unblock this item yet, but the\r
+                                               item value is the time at which the task at the head\r
+                                               of the blocked list must be removed from the Blocked\r
+                                               state - so record the item value in\r
+                                               xNextTaskUnblockTime. */\r
+                                               xNextTaskUnblockTime = xItemValue;\r
                                                break;\r
                                        }\r
                                        else\r
                                        {\r
-                                               /* The delayed list is not empty, get the value of the\r
-                                               item at the head of the delayed list.  This is the time\r
-                                               at which the task at the head of the delayed list must\r
-                                               be removed from the Blocked state. */\r
-                                               pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );\r
-                                               xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );\r
-\r
-                                               if( xConstTickCount < xItemValue )\r
-                                               {\r
-                                                       /* It is not time to unblock this item yet, but the\r
-                                                       item value is the time at which the task at the head\r
-                                                       of the blocked list must be removed from the Blocked\r
-                                                       state - so record the item value in\r
-                                                       xNextTaskUnblockTime. */\r
-                                                       xNextTaskUnblockTime = xItemValue;\r
-                                                       break;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       mtCOVERAGE_TEST_MARKER();\r
-                                               }\r
+                                               mtCOVERAGE_TEST_MARKER();\r
+                                       }\r
+\r
+                                       /* It is time to remove the item from the Blocked state. */\r
+                                       ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
+\r
+                                       /* Is the task waiting on an event also?  If so remove\r
+                                       it from the event list. */\r
+                                       if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
+                                       {\r
+                                               ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               mtCOVERAGE_TEST_MARKER();\r
+                                       }\r
 \r
-                                               /* It is time to remove the item from the Blocked state. */\r
-                                               ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
+                                       /* Place the unblocked task into the appropriate ready\r
+                                       list. */\r
+                                       prvAddTaskToReadyList( pxTCB );\r
 \r
-                                               /* Is the task waiting on an event also?  If so remove\r
-                                               it from the event list. */\r
-                                               if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
+                                       /* A task being unblocked cannot cause an immediate\r
+                                       context switch if preemption is turned off. */\r
+                                       #if (  configUSE_PREEMPTION == 1 )\r
+                                       {\r
+                                               /* Preemption is on, but a context switch should\r
+                                               only be performed if the unblocked task has a\r
+                                               priority that is equal to or higher than the\r
+                                               currently executing task. */\r
+                                               if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
                                                {\r
-                                                       ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
+                                                       xSwitchRequired = pdTRUE;\r
                                                }\r
                                                else\r
                                                {\r
                                                        mtCOVERAGE_TEST_MARKER();\r
                                                }\r
-\r
-                                               /* Place the unblocked task into the appropriate ready\r
-                                               list. */\r
-                                               prvAddTaskToReadyList( pxTCB );\r
-\r
-                                               /* A task being unblocked cannot cause an immediate\r
-                                               context switch if preemption is turned off. */\r
-                                               #if (  configUSE_PREEMPTION == 1 )\r
-                                               {\r
-                                                       /* Preemption is on, but a context switch should\r
-                                                       only be performed if the unblocked task has a\r
-                                                       priority that is equal to or higher than the\r
-                                                       currently executing task. */\r
-                                                       if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
-                                                       {\r
-                                                               xSwitchRequired = pdTRUE;\r
-                                                       }\r
-                                                       else\r
-                                                       {\r
-                                                               mtCOVERAGE_TEST_MARKER();\r
-                                                       }\r
-                                               }\r
-                                               #endif /* configUSE_PREEMPTION */\r
                                        }\r
+                                       #endif /* configUSE_PREEMPTION */\r
                                }\r
                        }\r
                }\r
@@ -3248,7 +3254,7 @@ UBaseType_t uxPriority;
 static void prvCheckTasksWaitingTermination( void )\r
 {\r
 \r
-       /** THIS FUNCTION IS CALLED FROM  THE RTOS IDLE TASK **/\r
+       /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/\r
 \r
        #if ( INCLUDE_vTaskDelete == 1 )\r
        {\r
@@ -4111,7 +4117,7 @@ TickType_t uxReturn;
                                }\r
                                else\r
                                {\r
-                                       ( pxCurrentTCB->ulNotifiedValue )--;\r
+                                       pxCurrentTCB->ulNotifiedValue = ulReturn - 1;\r
                                }\r
                        }\r
                        else\r
@@ -4563,6 +4569,7 @@ TickType_t uxReturn;
 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )\r
 {\r
 TickType_t xTimeToWake;\r
+const TickType_t xConstTickCount = xTickCount;\r
 \r
        #if( INCLUDE_xTaskAbortDelay == 1 )\r
        {\r
@@ -4586,7 +4593,6 @@ TickType_t xTimeToWake;
                mtCOVERAGE_TEST_MARKER();\r
        }\r
 \r
-\r
        #if ( INCLUDE_vTaskSuspend == 1 )\r
        {\r
                if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )\r
@@ -4601,12 +4607,12 @@ TickType_t xTimeToWake;
                        /* Calculate the time at which the task should be woken if the event\r
                        does not occur.  This may overflow but this doesn't matter, the\r
                        kernel will manage it correctly. */\r
-                       xTimeToWake = xTickCount + xTicksToWait;\r
+                       xTimeToWake = xConstTickCount + xTicksToWait;\r
 \r
                        /* The list item will be inserted in wake time order. */\r
                        listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );\r
 \r
-                       if( xTimeToWake < xTickCount )\r
+                       if( xTimeToWake < xConstTickCount )\r
                        {\r
                                /* Wake time has overflowed.  Place this item in the overflow\r
                                list. */\r
@@ -4637,12 +4643,12 @@ TickType_t xTimeToWake;
                /* Calculate the time at which the task should be woken if the event\r
                does not occur.  This may overflow but this doesn't matter, the kernel\r
                will manage it correctly. */\r
-               xTimeToWake = xTickCount + xTicksToWait;\r
+               xTimeToWake = xConstTickCount + xTicksToWait;\r
 \r
                /* The list item will be inserted in wake time order. */\r
                listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );\r
 \r
-               if( xTimeToWake < xTickCount )\r
+               if( xTimeToWake < xConstTickCount )\r
                {\r
                        /* Wake time has overflowed.  Place this item in the overflow list. */\r
                        vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );\r