mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
5b6d9d87a3
`vTaskGetSnapshot` is being used in coredump module to collect diagnostic information. It is possible that input arguments are invalid and `assert` in this situation is not correct. This commit modifies API signature to return pdTRUE in case of success, and pdFALSE otherwise. Caller can verify return value and then take appropriate decision.
215 lines
6.0 KiB
C
215 lines
6.0 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task_snapshot.h"
|
|
|
|
#ifndef DIM
|
|
#define DIM(t) (sizeof(t)/ sizeof(*(t)))
|
|
#endif
|
|
|
|
#if ( configENABLE_TASK_SNAPSHOT == 1 )
|
|
|
|
static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, void *pxTCB )
|
|
{
|
|
if (pxTCB == NULL) {
|
|
return;
|
|
}
|
|
pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB;
|
|
pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *) pxTCBGetTopOfStack(pxTCB);
|
|
#if( portSTACK_GROWTH < 0 )
|
|
{
|
|
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetEndOfStack(pxTCB);
|
|
}
|
|
#else
|
|
{
|
|
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetStartOfStack(pxTCB);
|
|
}
|
|
#endif
|
|
(*uxTask)++;
|
|
}
|
|
|
|
static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList )
|
|
{
|
|
void *pxNextTCB = NULL;
|
|
void *pxFirstTCB = NULL;
|
|
|
|
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
|
{
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
|
do
|
|
{
|
|
if( *uxTask >= uxArraySize ) {
|
|
break;
|
|
}
|
|
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
|
prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB );
|
|
} while( pxNextTCB != pxFirstTCB );
|
|
}
|
|
else
|
|
{
|
|
mtCOVERAGE_TEST_MARKER();
|
|
}
|
|
}
|
|
|
|
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz )
|
|
{
|
|
UBaseType_t uxTask = 0;
|
|
UBaseType_t i = 0;
|
|
|
|
|
|
*pxTcbSz = pxTCBGetSize();
|
|
/* Fill in an TaskStatus_t structure with information on each
|
|
task in the Ready state. */
|
|
i = configMAX_PRIORITIES;
|
|
do
|
|
{
|
|
i--;
|
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyTask(i) );
|
|
} while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
|
/* Fill in an TaskStatus_t structure with information on each
|
|
task in the Blocked state. */
|
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetDelayedTaskList() );
|
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetOverflowDelayedTaskList() );
|
|
for (i = 0; i < configNUM_CORES; i++) {
|
|
if( uxTask >= uxArraySize ) {
|
|
break;
|
|
}
|
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyPendingTask(i) );
|
|
}
|
|
|
|
#if( INCLUDE_vTaskDelete == 1 )
|
|
{
|
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetTasksWaitingTermination() );
|
|
}
|
|
#endif
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
{
|
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetSuspendedTaskList() );
|
|
}
|
|
#endif
|
|
return uxTask;
|
|
}
|
|
|
|
static void *prvFirstTaskGet( List_t *pxList )
|
|
{
|
|
ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList );
|
|
if( pxListItem != listGET_END_MARKER( pxList ) ) {
|
|
return listGET_LIST_ITEM_OWNER( pxListItem );
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void *prvNextTaskGet( void *pxTCB )
|
|
{
|
|
List_t *pxList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTCB) );
|
|
ListItem_t *pxListItem = listGET_NEXT( pxTCBGetStateListItem(pxTCB) );
|
|
if( pxListItem != listGET_END_MARKER( pxList ) ) {
|
|
return listGET_LIST_ITEM_OWNER( pxListItem );
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
BaseType_t vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot )
|
|
{
|
|
if (portVALID_TCB_MEM(pxTask) == false || pxTaskSnapshot == NULL) {
|
|
return pdFALSE;
|
|
}
|
|
pxTaskSnapshot->pxTCB = (void*) pxTask;
|
|
pxTaskSnapshot->pxTopOfStack = pxTCBGetTopOfStack((void*) pxTask);
|
|
pxTaskSnapshot->pxEndOfStack = pxTCBGetEndOfStack((void*) pxTask);
|
|
return pdTRUE;
|
|
}
|
|
|
|
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask )
|
|
{
|
|
void *pxTCB = pxTask;
|
|
List_t *pxTaskList = NULL;
|
|
UBaseType_t i = configMAX_PRIORITIES;
|
|
UBaseType_t bCurTaskListFound = pdFALSE;
|
|
List_t *task_lists[] = {
|
|
pxGetDelayedTaskList(),
|
|
pxGetOverflowDelayedTaskList(),
|
|
#if( INCLUDE_vTaskDelete == 1 )
|
|
pxGetTasksWaitingTermination(),
|
|
#endif
|
|
#if( INCLUDE_vTaskSuspend == 1 )
|
|
pxGetSuspendedTaskList()
|
|
#endif
|
|
};
|
|
|
|
if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) {
|
|
return NULL;
|
|
}
|
|
|
|
if( pxTCB != NULL ) {
|
|
pxTCB = prvNextTaskGet( pxTCB );
|
|
if( pxTCB != NULL ) {
|
|
// take care not to return garbage
|
|
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
|
|
}
|
|
pxTaskList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTask) );
|
|
}
|
|
/* ready tasks lists */
|
|
do
|
|
{
|
|
i--;
|
|
List_t *pxList = pxListGetReadyTask(i);
|
|
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
|
|
/* need to find list the current task item from */
|
|
if( pxTaskList == pxList ) {
|
|
bCurTaskListFound = pdTRUE;
|
|
}
|
|
continue; /* go to the next 'ready list' */
|
|
}
|
|
pxTCB = prvFirstTaskGet( pxList );
|
|
if( pxTCB != NULL ) {
|
|
// take care not to return garbage
|
|
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
|
|
}
|
|
}
|
|
while( i > tskIDLE_PRIORITY );
|
|
/* pending ready tasks lists */
|
|
for (i = 0; i < configNUM_CORES; i++) {
|
|
List_t *pxList = pxListGetReadyPendingTask(i);
|
|
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
|
|
/* need to find list the current task item from */
|
|
if( pxTaskList == pxList ) {
|
|
bCurTaskListFound = pdTRUE;
|
|
}
|
|
continue; /* go to the next 'ready list' */
|
|
}
|
|
pxTCB = prvFirstTaskGet( pxList );
|
|
if( pxTCB != NULL ) {
|
|
// take care not to return garbage
|
|
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
|
|
}
|
|
}
|
|
/* other tasks lists */
|
|
for (i = 0; i < DIM(task_lists); i++) {
|
|
List_t *pxList = task_lists[ i ];
|
|
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
|
|
/* need to find list the current task item from */
|
|
if( pxTaskList == pxList ) {
|
|
bCurTaskListFound = pdTRUE;
|
|
}
|
|
continue; /* go to the next 'ready list' */
|
|
}
|
|
pxTCB = prvFirstTaskGet( pxList );
|
|
if( pxTCB != NULL ) {
|
|
// take care not to return garbage
|
|
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|