1 /* 2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include "freertos/FreeRTOS.h" 8 #include "freertos/task_snapshot.h" 9 10 #ifndef DIM 11 #define DIM(t) (sizeof(t)/ sizeof(*(t))) 12 #endif 13 14 #if ( configENABLE_TASK_SNAPSHOT == 1 ) 15 prvTaskGetSnapshot(TaskSnapshot_t * pxTaskSnapshotArray,UBaseType_t * uxTask,void * pxTCB)16 static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, void *pxTCB ) 17 { 18 if (pxTCB == NULL) { 19 return; 20 } 21 pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; 22 pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *) pxTCBGetTopOfStack(pxTCB); 23 #if( portSTACK_GROWTH < 0 ) 24 { 25 pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetEndOfStack(pxTCB); 26 } 27 #else 28 { 29 pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetStartOfStack(pxTCB); 30 } 31 #endif 32 (*uxTask)++; 33 } 34 prvTaskGetSnapshotsFromList(TaskSnapshot_t * pxTaskSnapshotArray,UBaseType_t * uxTask,const UBaseType_t uxArraySize,List_t * pxList)35 static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) 36 { 37 void *pxNextTCB = NULL; 38 void *pxFirstTCB = NULL; 39 40 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) 41 { 42 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); 43 do 44 { 45 if( *uxTask >= uxArraySize ) { 46 break; 47 } 48 49 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); 50 prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); 51 } while( pxNextTCB != pxFirstTCB ); 52 } 53 else 54 { 55 mtCOVERAGE_TEST_MARKER(); 56 } 57 } 58 uxTaskGetSnapshotAll(TaskSnapshot_t * const pxTaskSnapshotArray,const UBaseType_t uxArraySize,UBaseType_t * const pxTcbSz)59 UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) 60 { 61 UBaseType_t uxTask = 0; 62 UBaseType_t i = 0; 63 64 65 *pxTcbSz = pxTCBGetSize(); 66 /* Fill in an TaskStatus_t structure with information on each 67 task in the Ready state. */ 68 i = configMAX_PRIORITIES; 69 do 70 { 71 i--; 72 prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyTask(i) ); 73 } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ 74 75 /* Fill in an TaskStatus_t structure with information on each 76 task in the Blocked state. */ 77 prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetDelayedTaskList() ); 78 prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetOverflowDelayedTaskList() ); 79 for (i = 0; i < configNUM_CORES; i++) { 80 if( uxTask >= uxArraySize ) { 81 break; 82 } 83 prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyPendingTask(i) ); 84 } 85 86 #if( INCLUDE_vTaskDelete == 1 ) 87 { 88 prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetTasksWaitingTermination() ); 89 } 90 #endif 91 92 #if ( INCLUDE_vTaskSuspend == 1 ) 93 { 94 prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetSuspendedTaskList() ); 95 } 96 #endif 97 return uxTask; 98 } 99 prvFirstTaskGet(List_t * pxList)100 static void *prvFirstTaskGet( List_t *pxList ) 101 { 102 ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList ); 103 if( pxListItem != listGET_END_MARKER( pxList ) ) { 104 return listGET_LIST_ITEM_OWNER( pxListItem ); 105 } 106 return NULL; 107 } 108 prvNextTaskGet(void * pxTCB)109 static void *prvNextTaskGet( void *pxTCB ) 110 { 111 List_t *pxList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTCB) ); 112 ListItem_t *pxListItem = listGET_NEXT( pxTCBGetStateListItem(pxTCB) ); 113 if( pxListItem != listGET_END_MARKER( pxList ) ) { 114 return listGET_LIST_ITEM_OWNER( pxListItem ); 115 } 116 return NULL; 117 } 118 vTaskGetSnapshot(TaskHandle_t pxTask,TaskSnapshot_t * pxTaskSnapshot)119 void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ) 120 { 121 configASSERT( portVALID_TCB_MEM(pxTask) ); 122 configASSERT( pxTaskSnapshot != NULL ); 123 pxTaskSnapshot->pxTCB = (void*) pxTask; 124 pxTaskSnapshot->pxTopOfStack = pxTCBGetTopOfStack((void*) pxTask); 125 pxTaskSnapshot->pxEndOfStack = pxTCBGetEndOfStack((void*) pxTask); 126 } 127 pxTaskGetNext(TaskHandle_t pxTask)128 TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ) 129 { 130 void *pxTCB = pxTask; 131 List_t *pxTaskList = NULL; 132 UBaseType_t i = configMAX_PRIORITIES; 133 UBaseType_t bCurTaskListFound = pdFALSE; 134 List_t *task_lists[] = { 135 pxGetDelayedTaskList(), 136 pxGetOverflowDelayedTaskList(), 137 #if( INCLUDE_vTaskDelete == 1 ) 138 pxGetTasksWaitingTermination(), 139 #endif 140 #if( INCLUDE_vTaskSuspend == 1 ) 141 pxGetSuspendedTaskList() 142 #endif 143 }; 144 145 if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) { 146 return NULL; 147 } 148 149 if( pxTCB != NULL ) { 150 pxTCB = prvNextTaskGet( pxTCB ); 151 if( pxTCB != NULL ) { 152 // take care not to return garbage 153 return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; 154 } 155 pxTaskList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTask) ); 156 } 157 /* ready tasks lists */ 158 do 159 { 160 i--; 161 List_t *pxList = pxListGetReadyTask(i); 162 if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { 163 /* need to find list the current task item from */ 164 if( pxTaskList == pxList ) { 165 bCurTaskListFound = pdTRUE; 166 } 167 continue; /* go to the next 'ready list' */ 168 } 169 pxTCB = prvFirstTaskGet( pxList ); 170 if( pxTCB != NULL ) { 171 // take care not to return garbage 172 return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; 173 } 174 } 175 while( i > tskIDLE_PRIORITY ); 176 /* pending ready tasks lists */ 177 for (i = 0; i < configNUM_CORES; i++) { 178 List_t *pxList = pxListGetReadyPendingTask(i); 179 if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { 180 /* need to find list the current task item from */ 181 if( pxTaskList == pxList ) { 182 bCurTaskListFound = pdTRUE; 183 } 184 continue; /* go to the next 'ready list' */ 185 } 186 pxTCB = prvFirstTaskGet( pxList ); 187 if( pxTCB != NULL ) { 188 // take care not to return garbage 189 return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; 190 } 191 } 192 /* other tasks lists */ 193 for (i = 0; i < DIM(task_lists); i++) { 194 List_t *pxList = task_lists[ i ]; 195 if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { 196 /* need to find list the current task item from */ 197 if( pxTaskList == pxList ) { 198 bCurTaskListFound = pdTRUE; 199 } 200 continue; /* go to the next 'ready list' */ 201 } 202 pxTCB = prvFirstTaskGet( pxList ); 203 if( pxTCB != NULL ) { 204 // take care not to return garbage 205 return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; 206 } 207 } 208 209 return NULL; 210 } 211 212 #endif 213