When splitting a memory block, check if the next block is free.
If it is, then just extend it upwards instead of creating a new block.
This fixes a bug where when shrinking existing allocations would result in irreversible free space fragmentation.
When testing on the host, test all the poisoning configurations.
Add back a feature that was available in the old heap implementation
in release/v2.1 and earlier: keep track of which task allocates each
block from the heap. The task handle is conditionally added as
another word in the heap poisoning header under this configuration
option CONFIG_HEAP_TASK_TRACKING.
To allow custom monitoring and debugging code to be added, add helper
functions in multi_heap.c and multi_heap_poisoning.c to provide access
to information in the block headers.
Add esp_heap_debug_dump_totals() to monitor heap usage
esp_heap_debug_dump_totals() dumps into a user-provided data structure
a summary of the amound of heap memory in region type that is used by
each task. Optionally it will also dump into another data structure
the metadata about each allocated block for a given list of tasks or
for all tasks (limited by available space).
Address change requests on PR #1498
This set of changes fixes the files in e3b702c to just add the
CONFIG_HEAP_TASK_TRACKING option without adding the new function
heap_caps_get_per_task_info() in case that is the only portion of the
PR that will be accepted. Part of the change is to remove the new .c
and .h files containing that function and to remove the line to
compile it from components/heap/component.mk since it should not have
been included in e3b702c. One or more additional commits to add the
new function will follow.
The other changes here:
- uint32_t get_all_caps() moves to heap_private.h
- replace "void* foo" with "void *foo"
- add braces around single-line "if" blocks
- replace tab characters with spaces
Address change requests on PR #1498, part 2
This set of changes fixes the files in cdf32aa to add the new function
heap_caps_get_per_task_info() with its new name and to add the line to
compile it in components/heap/component.mk. This does not address all
the suggested changes because there are some needing further
discussion.
This commit does not include the suggested change to move the
declaration of the new function into esp_heap_caps.h because the new
function references TaskHandle_t so esp_heap_caps.h would have to
include freertos/FreeRTOS.h and freertos/task.h, but FreeRTOS.h
includes esp_heap_caps.h through two other header files which results
in compilation errors because not all of FreeRTOS.h has been read yet.
Change heap_caps_get_per_task_info() to take struct of params
In addition to moving the large number of function parameters into a
struct as the single parameter, the following changes were made:
- Clear out the totals for any prepopulated tasks so the app code
doesn't have to do it.
- Rather than partitioning the per-task totals into a predetermined
set of heap capabilities, take a list of <caps,mask> pairs to
compare the caps to the heap capabilities as masked. This lets the
caller configure the desired partitioning, or none.
- Allow the totals array pointer or the blocks array pointer to be
NULL to indicate not to collect that part of the information.
- In addition to returning the total space allocated by each task,
return the number of blocks allocated by each task.
- Don't need to return the heap capabilities as part of the details
for each block since the heap region (and therefore its
capabilities) can be determined from the block address.
- Renamed heap_task_info.h to esp_heap_task_info.h to fit the naming
convention, and renamed the structs for totals and block details to
better fit the revised function name.
- Provide full Doxygen commenting for the function and parameter
structs.
Add copyright header to new files
Merges https://github.com/espressif/esp-idf/pull/1498
When realloc-ing to a smaller buffer size which ends up allocated in a different heap, the heap
structure is corrupted. This can only happen:
* If heap checking is Comprehensive (meaning buffers are never shrunk in place) and the heap the buffer was originally allocated in is full.
* Calling heap_caps_realloc() to deliberately move a buffer to a different capabilities type, and shrink it at the same time.
Probable fix for https://github.com/espressif/esp-idf/issues/1582
Probably the same issue:
https://www.esp32.com/viewtopic.php?f=2&t=4583https://www.esp32.com/viewtopic.php?f=13&t=3717
esp_heap_debug_dump_totals() dumps into a user-provided data structure
a summary of the amound of heap memory in region type that is used by
each task. Optionally it will also dump into another data structure
the metadata about each allocated block for a given list of tasks or
for all tasks (limited by available space).
Add back a feature that was available in the old heap implementation
in release/v2.1 and earlier: keep track of which task allocates each
block from the heap. The task handle is conditionally added as
another word in the heap poisoning header under this configuration
option CONFIG_HEAP_TASK_TRACKING.
To allow custom monitoring and debugging code to be added, add helper
functions in multi_heap.c and multi_heap_poisoning.c to provide access
to information in the block headers.
During a call to multi_heap_malloc(), if both these conditions were true:
- That heap only has one block large enough for the allocation
(this is always the case if the heap is unfragmented).
- Another allocation is simultaneously occurring in the same heap.
... multi_heap_malloc() could incorrectly return NULL.
This caused IDF heap_caps_malloc() and malloc() to also fail, particularly
often if only one or two heaps had space for the allocation (otherwise
heap_caps_malloc() fails over to the next heap).
New multi_heap code has proven effective at aborting when buffer overruns occur,
but it's currently hard to debug the stack traces from these failures.