mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-29 05:21:37 +03:00
umm_malloc manual merge with upstream (#7337)
* umm_malloc manual merge with upstream * Fix divide by zero, case when heap is 100% allocated. * Removed extra line. * Fixed block count for debug build. This resolves OOM events for debug build. Correct overstepping array when freeing. * Handle another corner case in example HeapMetric.ino. Comment corrections. * Revert - ESP.getMaxFreeBlockSize() is back to indicating the size of a contiguous block of memory before the umm_malloc overhead is removed. * Stale code cleanup and comment improvements
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
// released to public domain
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <umm_malloc/umm_malloc.h>
|
||||
|
||||
void stats(const char* what) {
|
||||
// we could use getFreeHeap() getMaxFreeBlockSize() and getHeapFragmentation()
|
||||
@ -21,9 +22,53 @@ void tryit(int blocksize) {
|
||||
void** p;
|
||||
int blocks;
|
||||
|
||||
// heap-used ~= blocks*sizeof(void*) + blocks*blocksize
|
||||
blocks = ((ESP.getMaxFreeBlockSize() / (blocksize + sizeof(void*))) + 3) & ~3; // rounded up, multiple of 4
|
||||
/*
|
||||
heap-used ~= blocks*sizeof(void*) + blocks*blocksize
|
||||
|
||||
This calculation gets deep into how umm_malloc divides up memory and
|
||||
understanding it is not important for this example. However, some may find
|
||||
the details useful when creating memory restricted test cases and possibly
|
||||
other manufactured failures.
|
||||
|
||||
Internally the umm_malloc works with memory in 8-byte increments and aligns
|
||||
to 8 bytes. The creation of an allocation adds about 4-bytes of overhead
|
||||
plus alignment to the allocation size and more for debug builds. This
|
||||
complicates the calculation of `blocks` a little.
|
||||
|
||||
ESP.getMaxFreeBlockSize() does not indicate the amount of memory that is
|
||||
available for use in a single malloc call. It indicates the size of a
|
||||
contiguous block of (raw) memory before the umm_malloc overhead is removed.
|
||||
|
||||
It should also be pointed out that, if you allow for the needed overhead in
|
||||
your malloc call, it could still fail in the general case. An IRQ handler
|
||||
could have allocated memory between the time you call
|
||||
ESP.getMaxFreeBlockSize() and your malloc call, reducing the available
|
||||
memory. In this particular sketch, with "WiFi off" we are not expecting this
|
||||
to be an issue.
|
||||
|
||||
The macro UMM_OVERHEAD_ADJUST provides a value that can be used to adjust
|
||||
calculations when trying to dividing up memory as we are here. However, the
|
||||
calculation of multiple elements combined with the rounding up for the
|
||||
8-byte alignment of each allocation can make for some tricky calculations.
|
||||
*/
|
||||
int rawMemoryMaxFreeBlockSize = ESP.getMaxFreeBlockSize();
|
||||
// Remove the space for overhead component of the blocks*sizeof(void*) array.
|
||||
int maxFreeBlockSize = rawMemoryMaxFreeBlockSize - UMM_OVERHEAD_ADJUST;
|
||||
// Initial estimate to use all of the MaxFreeBlock with multiples of 8 rounding up.
|
||||
blocks = maxFreeBlockSize /
|
||||
(((blocksize + UMM_OVERHEAD_ADJUST + 7) & ~7) + sizeof(void*));
|
||||
/*
|
||||
While we allowed for the 8-byte alignment overhead for blocks*blocksize we
|
||||
were unable to compensate in advance for the later 8-byte aligning needed
|
||||
for the blocks*sizeof(void*) allocation. Thus blocks may be off by one count.
|
||||
We now validate the estimate and adjust as needed.
|
||||
*/
|
||||
int rawMemoryEstimate =
|
||||
blocks * ((blocksize + UMM_OVERHEAD_ADJUST + 7) & ~7) +
|
||||
((blocks * sizeof(void*) + UMM_OVERHEAD_ADJUST + 7) & ~7);
|
||||
if (rawMemoryMaxFreeBlockSize < rawMemoryEstimate) {
|
||||
--blocks;
|
||||
}
|
||||
Serial.printf("\nFilling memory with blocks of %d bytes each\n", blocksize);
|
||||
stats("before");
|
||||
|
||||
@ -41,7 +86,7 @@ void tryit(int blocksize) {
|
||||
}
|
||||
stats("freeing every other blocks");
|
||||
|
||||
for (int i = 0; i < blocks; i += 4) {
|
||||
for (int i = 0; i < (blocks - 1); i += 4) {
|
||||
if (p[i + 1]) {
|
||||
free(p[i + 1]);
|
||||
}
|
||||
|
Reference in New Issue
Block a user