]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
Add vTaskGetTaskInfo() function that allows a TaskStatus_t structure to be returned...
[freertos] / FreeRTOS / Source / tasks.c
index d73f8d2770de83410b58974e9685004c387f9d16..b9b17576a9b488dfe79b2b3b0539e71f458ee0b8 100644 (file)
@@ -507,7 +507,17 @@ static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t *
  */\r
 #if ( configUSE_TRACE_FACILITY == 1 )\r
 \r
-       static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;\r
+       static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;\r
+\r
+#endif\r
+\r
+/*\r
+ * Searches pxList for a task with name pcNameToQuery - returning a handle to\r
+ * the task if it is found, or NULL if the task is not found.\r
+ */\r
+#if ( INCLUDE_xTaskGetTaskHandle == 1 )\r
+\r
+       static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] );\r
 \r
 #endif\r
 \r
@@ -985,7 +995,7 @@ StackType_t *pxTopOfStack;
 #endif /* INCLUDE_vTaskDelay */\r
 /*-----------------------------------------------------------*/\r
 \r
-#if ( INCLUDE_eTaskGetState == 1 )\r
+#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )\r
 \r
        eTaskState eTaskGetState( TaskHandle_t xTask )\r
        {\r
@@ -1321,6 +1331,21 @@ StackType_t *pxTopOfStack;
                }\r
                taskEXIT_CRITICAL();\r
 \r
+               if( xSchedulerRunning != pdFALSE )\r
+               {\r
+                       /* Reset the next expected unblock time in case it referred to the\r
+                       task that is now in the Suspended state. */\r
+                       taskENTER_CRITICAL();\r
+                       {\r
+                               prvResetNextTaskUnblockTime();\r
+                       }\r
+                       taskEXIT_CRITICAL();\r
+               }\r
+               else\r
+               {\r
+                       mtCOVERAGE_TEST_MARKER();\r
+               }\r
+\r
                if( pxTCB == pxCurrentTCB )\r
                {\r
                        if( xSchedulerRunning != pdFALSE )\r
@@ -1350,21 +1375,7 @@ StackType_t *pxTopOfStack;
                }\r
                else\r
                {\r
-                       if( xSchedulerRunning != pdFALSE )\r
-                       {\r
-                               /* A task other than the currently running task was suspended,\r
-                               reset the next expected unblock time in case it referred to the\r
-                               task that is now in the Suspended state. */\r
-                               taskENTER_CRITICAL();\r
-                               {\r
-                                       prvResetNextTaskUnblockTime();\r
-                               }\r
-                               taskEXIT_CRITICAL();\r
-                       }\r
-                       else\r
-                       {\r
-                               mtCOVERAGE_TEST_MARKER();\r
-                       }\r
+                       mtCOVERAGE_TEST_MARKER();\r
                }\r
        }\r
 \r
@@ -1710,7 +1721,7 @@ void vTaskSuspendAll( void )
 \r
 BaseType_t xTaskResumeAll( void )\r
 {\r
-TCB_t *pxTCB;\r
+TCB_t *pxTCB = NULL;\r
 BaseType_t xAlreadyYielded = pdFALSE;\r
 \r
        /* If uxSchedulerSuspended is zero then this function does not match a\r
@@ -1751,6 +1762,17 @@ BaseType_t xAlreadyYielded = pdFALSE;
                                        }\r
                                }\r
 \r
+                               if( pxTCB != NULL )\r
+                               {\r
+                                       /* A task was unblocked while the scheduler was suspended,\r
+                                       which may have prevented the next unblock time from being\r
+                                       re-calculated, in which case re-calculate it now.  Mainly\r
+                                       important for low power tickless implementations, where\r
+                                       this can prevent an unnecessary exit from low power\r
+                                       state. */\r
+                                       prvResetNextTaskUnblockTime();\r
+                               }\r
+\r
                                /* If any ticks occurred while the scheduler was suspended then\r
                                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
@@ -1861,7 +1883,8 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
        {\r
        TCB_t *pxTCB;\r
 \r
-               /* If null is passed in here then the name of the calling task is being queried. */\r
+               /* If null is passed in here then the name of the calling task is being\r
+               queried. */\r
                pxTCB = prvGetTCBFromHandle( xTaskToQuery );\r
                configASSERT( pxTCB );\r
                return &( pxTCB->pcTaskName[ 0 ] );\r
@@ -1870,6 +1893,129 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
 #endif /* INCLUDE_pcTaskGetTaskName */\r
 /*-----------------------------------------------------------*/\r
 \r
+#if ( INCLUDE_xTaskGetTaskHandle == 1 )\r
+\r
+       static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )\r
+       {\r
+       TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;\r
+       UBaseType_t x;\r
+       char cNextChar;\r
+\r
+               /* This function is called with the scheduler suspended. */\r
+\r
+               if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
+               {\r
+                       listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );\r
+\r
+                       do\r
+                       {\r
+                               listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );\r
+\r
+                               /* Check each character in the name looking for a match or\r
+                               mismatch. */\r
+                               for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )\r
+                               {\r
+                                       cNextChar = pxNextTCB->pcTaskName[ x ];\r
+\r
+                                       if( cNextChar != pcNameToQuery[ x ] )\r
+                                       {\r
+                                               /* Characters didn't match. */\r
+                                               break;\r
+                                       }\r
+                                       else if( cNextChar == 0x00 )\r
+                                       {\r
+                                               /* Both strings terminated, a match must have been\r
+                                               found. */\r
+                                               pxReturn = pxNextTCB;\r
+                                               break;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               mtCOVERAGE_TEST_MARKER();\r
+                                       }\r
+                               }\r
+\r
+                               if( pxReturn != NULL )\r
+                               {\r
+                                       /* The handle has been found. */\r
+                                       break;\r
+                               }\r
+\r
+                       } while( pxNextTCB != pxFirstTCB );\r
+               }\r
+               else\r
+               {\r
+                       mtCOVERAGE_TEST_MARKER();\r
+               }\r
+\r
+               return pxReturn;\r
+       }\r
+\r
+#endif /* INCLUDE_xTaskGetTaskHandle */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( INCLUDE_xTaskGetTaskHandle == 1 )\r
+\r
+       TaskHandle_t xTaskGetTaskHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
+       {\r
+       UBaseType_t uxQueue = configMAX_PRIORITIES;\r
+       TCB_t* pxTCB;\r
+\r
+               vTaskSuspendAll();\r
+               {\r
+                       /* Search the ready lists. */\r
+                       do\r
+                       {\r
+                               uxQueue--;\r
+                               pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );\r
+\r
+                               if( pxTCB != NULL )\r
+                               {\r
+                                       /* Found the handle. */\r
+                                       break;\r
+                               }\r
+\r
+                       } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
+\r
+                       /* Search the delayed lists. */\r
+                       if( pxTCB == NULL )\r
+                       {\r
+                               pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );\r
+                       }\r
+\r
+                       if( pxTCB == NULL )\r
+                       {\r
+                               pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );\r
+                       }\r
+\r
+                       #if ( INCLUDE_vTaskSuspend == 1 )\r
+                       {\r
+                               if( pxTCB == NULL )\r
+                               {\r
+                                       /* Search the suspended list. */\r
+                                       pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );\r
+                               }\r
+                       }\r
+                       #endif\r
+\r
+                       #if( INCLUDE_vTaskDelete == 1 )\r
+                       {\r
+                               if( pxTCB == NULL )\r
+                               {\r
+                                       /* Search the deleted list. */\r
+                                       pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );\r
+                               }\r
+                       }\r
+                       #endif\r
+               }\r
+               ( void ) xTaskResumeAll();\r
+\r
+               return ( TaskHandle_t ) pxTCB;\r
+       }\r
+\r
+#endif /* INCLUDE_xTaskGetTaskHandle */\r
+/*-----------------------------------------------------------*/\r
+\r
 #if ( configUSE_TRACE_FACILITY == 1 )\r
 \r
        UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )\r
@@ -1886,20 +2032,20 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
                                do\r
                                {\r
                                        uxQueue--;\r
-                                       uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );\r
+                                       uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );\r
 \r
                                } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
 \r
                                /* Fill in an TaskStatus_t structure with information on each\r
                                task in the Blocked state. */\r
-                               uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );\r
-                               uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );\r
+                               uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );\r
+                               uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );\r
 \r
                                #if( INCLUDE_vTaskDelete == 1 )\r
                                {\r
                                        /* Fill in an TaskStatus_t structure with information on\r
                                        each task that has been deleted but not yet cleaned up. */\r
-                                       uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );\r
+                                       uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );\r
                                }\r
                                #endif\r
 \r
@@ -1907,7 +2053,7 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
                                {\r
                                        /* Fill in an TaskStatus_t structure with information on\r
                                        each task in the Suspended state. */\r
-                                       uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );\r
+                                       uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );\r
                                }\r
                                #endif\r
 \r
@@ -3268,9 +3414,98 @@ TCB_t *pxNewTCB;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if( configUSE_TRACE_FACILITY == 1 )\r
+\r
+       void vTaskGetTaskInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )\r
+       {\r
+       TCB_t *pxTCB;\r
+\r
+               /* xTask is NULL then get the state of the calling task. */\r
+               pxTCB = prvGetTCBFromHandle( xTask );\r
+\r
+               pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;\r
+               pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );\r
+               pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;\r
+               pxTaskStatus->pxStackBase = pxTCB->pxStack;\r
+               pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;\r
+\r
+               #if ( INCLUDE_vTaskSuspend == 1 )\r
+               {\r
+                       /* If the task is in the suspended list then there is a chance it is\r
+                       actually just blocked indefinitely - so really it should be reported as\r
+                       being in the Blocked state. */\r
+                       if( pxTaskStatus->eCurrentState == eSuspended )\r
+                       {\r
+                               vTaskSuspendAll();\r
+                               {\r
+                                       if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
+                                       {\r
+                                               pxTaskStatus->eCurrentState = eBlocked;\r
+                                       }\r
+                               }\r
+                               xTaskResumeAll();\r
+                       }\r
+               }\r
+               #endif /* INCLUDE_vTaskSuspend */\r
+\r
+               #if ( configUSE_MUTEXES == 1 )\r
+               {\r
+                       pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;\r
+               }\r
+               #else\r
+               {\r
+                       pxTaskStatus->uxBasePriority = 0;\r
+               }\r
+               #endif\r
+\r
+               #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
+               {\r
+                       pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;\r
+               }\r
+               #else\r
+               {\r
+                       pxTaskStatus->ulRunTimeCounter = 0;\r
+               }\r
+               #endif\r
+\r
+               /* Obtaining the task state is a little fiddly, so is only done if the value\r
+               of eState passed into this function is eInvalid - otherwise the state is\r
+               just set to whatever is passed in. */\r
+               if( eState != eInvalid )\r
+               {\r
+                       pxTaskStatus->eCurrentState = eState;\r
+               }\r
+               else\r
+               {\r
+                       pxTaskStatus->eCurrentState = eTaskGetState( xTask );\r
+               }\r
+\r
+               /* Obtaining the stack space takes some time, so the xGetFreeStackSpace\r
+               parameter is provided to allow it to be skipped. */\r
+               if( xGetFreeStackSpace != pdFALSE )\r
+               {\r
+                       #if ( portSTACK_GROWTH > 0 )\r
+                       {\r
+                               pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );\r
+                       }\r
+                       #else\r
+                       {\r
+                               pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );\r
+                       }\r
+                       #endif\r
+               }\r
+               else\r
+               {\r
+                       pxTaskStatus->usStackHighWaterMark = 0;\r
+               }\r
+       }\r
+\r
+#endif /* INCLUDE_eTaskGetState */\r
+/*-----------------------------------------------------------*/\r
+\r
 #if ( configUSE_TRACE_FACILITY == 1 )\r
 \r
-       static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )\r
+       static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )\r
        {\r
        volatile TCB_t *pxNextTCB, *pxFirstTCB;\r
        UBaseType_t uxTask = 0;\r
@@ -3286,60 +3521,8 @@ TCB_t *pxNewTCB;
                        do\r
                        {\r
                                listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );\r
-\r
-                               pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;\r
-                               pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );\r
-                               pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;\r
-                               pxTaskStatusArray[ uxTask ].eCurrentState = eState;\r
-                               pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;\r
-\r
-                               #if ( INCLUDE_vTaskSuspend == 1 )\r
-                               {\r
-                                       /* If the task is in the suspended list then there is a chance\r
-                                       it is actually just blocked indefinitely - so really it should\r
-                                       be reported as being in the Blocked state. */\r
-                                       if( eState == eSuspended )\r
-                                       {\r
-                                               if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )\r
-                                               {\r
-                                                       pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;\r
-                                               }\r
-                                       }\r
-                               }\r
-                               #endif /* INCLUDE_vTaskSuspend */\r
-\r
-                               #if ( configUSE_MUTEXES == 1 )\r
-                               {\r
-                                       pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;\r
-                               }\r
-                               #else\r
-                               {\r
-                                       pxTaskStatusArray[ uxTask ].uxBasePriority = 0;\r
-                               }\r
-                               #endif\r
-\r
-                               #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
-                               {\r
-                                       pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;\r
-                               }\r
-                               #else\r
-                               {\r
-                                       pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;\r
-                               }\r
-                               #endif\r
-\r
-                               #if ( portSTACK_GROWTH > 0 )\r
-                               {\r
-                                       pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );\r
-                               }\r
-                               #else\r
-                               {\r
-                                       pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );\r
-                               }\r
-                               #endif\r
-\r
+                               vTaskGetTaskInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );\r
                                uxTask++;\r
-\r
                        } while( pxNextTCB != pxFirstTCB );\r
                }\r
                else\r
@@ -3422,7 +3605,7 @@ TCB_t *pxNewTCB;
                {\r
                        /* Only free the stack and TCB if they were allocated dynamically in\r
                        the first place. */\r
-                       if( ( pxTCB->ucStaticAllocationFlags & taskSTATICALLY_ALLOCATED_STACK ) == ( UBaseType_t ) 0 )\r
+                       if( ( pxTCB->ucStaticAllocationFlags & taskSTATICALLY_ALLOCATED_STACK ) == ( uint8_t ) 0 )\r
                        {\r
                                vPortFreeAligned( pxTCB->pxStack );\r
                        }\r
@@ -3431,7 +3614,7 @@ TCB_t *pxNewTCB;
                                mtCOVERAGE_TEST_MARKER();\r
                        }\r
 \r
-                       if( ( pxTCB->ucStaticAllocationFlags & taskSTATICALLY_ALLOCATED_TCB ) == ( UBaseType_t ) 0 )\r
+                       if( ( pxTCB->ucStaticAllocationFlags & taskSTATICALLY_ALLOCATED_TCB ) == ( uint8_t ) 0 )\r
                        {\r
                                vPortFreeAligned( pxTCB );\r
                        }\r