1 /* 2 * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <freertos/FreeRTOS.h> 8 #include <freertos/task.h> 9 #include <multi_heap.h> 10 #include "multi_heap_internal.h" 11 #include "heap_private.h" 12 #include "esp_heap_task_info.h" 13 14 #ifdef CONFIG_HEAP_TASK_TRACKING 15 16 /* 17 * Return per-task heap allocation totals and lists of blocks. 18 * 19 * For each task that has allocated memory from the heap, return totals for 20 * allocations within regions matching one or more sets of capabilities. 21 * 22 * Optionally also return an array of structs providing details about each 23 * block allocated by one or more requested tasks, or by all tasks. 24 * 25 * Returns the number of block detail structs returned. 26 */ heap_caps_get_per_task_info(heap_task_info_params_t * params)27size_t heap_caps_get_per_task_info(heap_task_info_params_t *params) 28 { 29 heap_t *reg; 30 heap_task_block_t *blocks = params->blocks; 31 size_t count = *params->num_totals; 32 size_t remaining = params->max_blocks; 33 34 // Clear out totals for any prepopulated tasks. 35 if (params->totals) { 36 for (size_t i = 0; i < count; ++i) { 37 for (size_t type = 0; type < NUM_HEAP_TASK_CAPS; ++type) { 38 params->totals[i].size[type] = 0; 39 params->totals[i].count[type] = 0; 40 } 41 } 42 } 43 44 SLIST_FOREACH(reg, ®istered_heaps, next) { 45 multi_heap_handle_t heap = reg->heap; 46 if (heap == NULL) { 47 continue; 48 } 49 50 // Find if the capabilities of this heap region match on of the desired 51 // sets of capabilities. 52 uint32_t caps = get_all_caps(reg); 53 uint32_t type; 54 for (type = 0; type < NUM_HEAP_TASK_CAPS; ++type) { 55 if ((caps & params->mask[type]) == params->caps[type]) { 56 break; 57 } 58 } 59 if (type == NUM_HEAP_TASK_CAPS) { 60 continue; 61 } 62 63 multi_heap_block_handle_t b = multi_heap_get_first_block(heap); 64 multi_heap_internal_lock(heap); 65 for ( ; b ; b = multi_heap_get_next_block(heap, b)) { 66 if (multi_heap_is_free(b)) { 67 continue; 68 } 69 void *p = multi_heap_get_block_address(b); // Safe, only arithmetic 70 size_t bsize = multi_heap_get_allocated_size(heap, p); // Validates 71 TaskHandle_t btask = (TaskHandle_t)multi_heap_get_block_owner(b); 72 73 // Accumulate per-task allocation totals. 74 if (params->totals) { 75 size_t i; 76 for (i = 0; i < count; ++i) { 77 if (params->totals[i].task == btask) { 78 break; 79 } 80 } 81 if (i < count) { 82 params->totals[i].size[type] += bsize; 83 params->totals[i].count[type] += 1; 84 } 85 else { 86 if (count < params->max_totals) { 87 params->totals[count].task = btask; 88 params->totals[count].size[type] = bsize; 89 params->totals[i].count[type] = 1; 90 ++count; 91 } 92 } 93 } 94 95 // Return details about allocated blocks for selected tasks. 96 if (blocks && remaining > 0) { 97 if (params->tasks) { 98 size_t i; 99 for (i = 0; i < params->num_tasks; ++i) { 100 if (btask == params->tasks[i]) { 101 break; 102 } 103 } 104 if (i == params->num_tasks) { 105 continue; 106 } 107 } 108 blocks->task = btask; 109 blocks->address = p; 110 blocks->size = bsize; 111 ++blocks; 112 --remaining; 113 } 114 } 115 multi_heap_internal_unlock(heap); 116 } 117 *params->num_totals = count; 118 return params->max_blocks - remaining; 119 } 120 121 #endif // CONFIG_HEAP_TASK_TRACKING 122