| 
									
										
										
										
											2022-07-20 13:59:14 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-01-10 01:14:47 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <freertos/FreeRTOS.h>
 | 
					
						
							|  |  |  | #include <freertos/task.h>
 | 
					
						
							|  |  |  | #include <multi_heap.h>
 | 
					
						
							|  |  |  | #include "multi_heap_internal.h"
 | 
					
						
							|  |  |  | #include "heap_private.h"
 | 
					
						
							|  |  |  | #include "esp_heap_task_info.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_HEAP_TASK_TRACKING
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Return per-task heap allocation totals and lists of blocks. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * For each task that has allocated memory from the heap, return totals for | 
					
						
							|  |  |  |  * allocations within regions matching one or more sets of capabilities. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Optionally also return an array of structs providing details about each | 
					
						
							|  |  |  |  * block allocated by one or more requested tasks, or by all tasks. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns the number of block detail structs returned. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | size_t heap_caps_get_per_task_info(heap_task_info_params_t *params) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     heap_t *reg; | 
					
						
							|  |  |  |     heap_task_block_t *blocks = params->blocks; | 
					
						
							|  |  |  |     size_t count = *params->num_totals; | 
					
						
							|  |  |  |     size_t remaining = params->max_blocks; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Clear out totals for any prepopulated tasks.
 | 
					
						
							|  |  |  |     if (params->totals) { | 
					
						
							|  |  |  |         for (size_t i = 0; i < count; ++i) { | 
					
						
							|  |  |  |             for (size_t type = 0; type < NUM_HEAP_TASK_CAPS; ++type) { | 
					
						
							|  |  |  |                 params->totals[i].size[type] = 0; | 
					
						
							|  |  |  |                 params->totals[i].count[type] = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SLIST_FOREACH(reg, ®istered_heaps, next) { | 
					
						
							|  |  |  |         multi_heap_handle_t heap = reg->heap; | 
					
						
							|  |  |  |         if (heap == NULL) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Find if the capabilities of this heap region match on of the desired
 | 
					
						
							|  |  |  |         // sets of capabilities.
 | 
					
						
							|  |  |  |         uint32_t caps = get_all_caps(reg); | 
					
						
							|  |  |  |         uint32_t type; | 
					
						
							|  |  |  |         for (type = 0; type < NUM_HEAP_TASK_CAPS; ++type) { | 
					
						
							|  |  |  |             if ((caps & params->mask[type]) == params->caps[type]) { | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (type == NUM_HEAP_TASK_CAPS) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         multi_heap_block_handle_t b = multi_heap_get_first_block(heap); | 
					
						
							|  |  |  |         multi_heap_internal_lock(heap); | 
					
						
							|  |  |  |         for ( ; b ; b = multi_heap_get_next_block(heap, b)) { | 
					
						
							|  |  |  |             if (multi_heap_is_free(b)) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             void *p = multi_heap_get_block_address(b);  // Safe, only arithmetic
 | 
					
						
							|  |  |  |             size_t bsize = multi_heap_get_allocated_size(heap, p); // Validates
 | 
					
						
							| 
									
										
										
										
											2023-10-04 14:42:00 +02:00
										 |  |  |             TaskHandle_t btask = MULTI_HEAP_GET_BLOCK_OWNER(p); | 
					
						
							| 
									
										
										
										
											2018-01-10 01:14:47 -08:00
										 |  |  |             // Accumulate per-task allocation totals.
 | 
					
						
							|  |  |  |             if (params->totals) { | 
					
						
							|  |  |  |                 size_t i; | 
					
						
							|  |  |  |                 for (i = 0; i < count; ++i) { | 
					
						
							|  |  |  |                     if (params->totals[i].task == btask) { | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (i < count) { | 
					
						
							|  |  |  |                     params->totals[i].size[type] += bsize; | 
					
						
							|  |  |  |                     params->totals[i].count[type] += 1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else { | 
					
						
							|  |  |  |                     if (count < params->max_totals) { | 
					
						
							|  |  |  |                         params->totals[count].task = btask; | 
					
						
							|  |  |  |                         params->totals[count].size[type] = bsize; | 
					
						
							|  |  |  |                         params->totals[i].count[type] = 1; | 
					
						
							|  |  |  |                         ++count; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Return details about allocated blocks for selected tasks.
 | 
					
						
							|  |  |  |             if (blocks && remaining > 0) { | 
					
						
							|  |  |  |                 if (params->tasks) { | 
					
						
							|  |  |  |                     size_t i; | 
					
						
							|  |  |  |                     for (i = 0; i < params->num_tasks; ++i) { | 
					
						
							|  |  |  |                         if (btask == params->tasks[i]) { | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (i == params->num_tasks) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 blocks->task = btask; | 
					
						
							|  |  |  |                 blocks->address = p; | 
					
						
							|  |  |  |                 blocks->size = bsize; | 
					
						
							|  |  |  |                 ++blocks; | 
					
						
							|  |  |  |                 --remaining; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         multi_heap_internal_unlock(heap); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *params->num_totals = count; | 
					
						
							|  |  |  |     return params->max_blocks - remaining; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // CONFIG_HEAP_TASK_TRACKING
 |