task_snapshot.c 6.0 KB

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