-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Bugfixes in FX data allocation #4783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
1960066
04c9c93
633eb04
3ce0cc7
716da32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,8 +159,17 @@ bool Segment::allocateData(size_t len) { | |
| return false; | ||
| } | ||
| // prefer DRAM over SPI RAM on ESP32 since it is slow | ||
| if (data) data = (byte*)d_realloc(data, len); | ||
| else data = (byte*)d_malloc(len); | ||
| if (data) { | ||
| void* newData = d_realloc(data, len); // note: realloc returns null if it fails but does not free the original pointer | ||
| if (!newData || newData != data) // realloc failed or used a new memory block causing fragmentation. free and allocate new block | ||
| d_free(newData); | ||
| d_free(data); | ||
| data = nullptr; // reset pointer to null | ||
| Segment::addUsedSegmentData(-_dataLen); // subtract original buffer size | ||
| _dataLen = 0; // reset data length | ||
| } | ||
| else data = (byte*)d_malloc(len); | ||
|
|
||
| if (data) { | ||
| memset(data, 0, len); // erase buffer | ||
| Segment::addUsedSegmentData(len - _dataLen); | ||
|
|
@@ -170,7 +179,6 @@ bool Segment::allocateData(size_t len) { | |
| } | ||
| // allocation failed | ||
| DEBUG_PRINTLN(F("!!! Allocation failed. !!!")); | ||
| Segment::addUsedSegmentData(-_dataLen); // subtract original buffer size | ||
| errorFlag = ERR_NORAM; | ||
| return false; | ||
| } | ||
|
|
@@ -449,8 +457,8 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui | |
| } | ||
| // re-allocate FX render buffer | ||
| if (length() != oldLength) { | ||
| if (pixels) pixels = static_cast<uint32_t*>(d_realloc(pixels, sizeof(uint32_t) * length())); | ||
| else pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * length())); | ||
| if (pixels) d_free(pixels); //pixels = static_cast<uint32_t*>(d_realloc(pixels, sizeof(uint32_t) * length())); // using realloc can cause additional fragmentation instead of reducing it | ||
|
||
| pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * length())); | ||
| if (!pixels) { | ||
| DEBUG_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!")); | ||
| errorFlag = ERR_NORAM_PX; | ||
|
|
@@ -563,8 +571,8 @@ Segment &Segment::setName(const char *newName) { | |
| if (newName) { | ||
| const int newLen = min(strlen(newName), (size_t)WLED_MAX_SEGNAME_LEN); | ||
| if (newLen) { | ||
| if (name) name = static_cast<char*>(d_realloc(name, newLen+1)); | ||
| else name = static_cast<char*>(d_malloc(newLen+1)); | ||
| if (name) d_free(name); // free old name | ||
| name = static_cast<char*>(d_malloc(newLen+1)); | ||
| if (name) strlcpy(name, newName, newLen+1); | ||
| name[newLen] = 0; | ||
| return *this; | ||
|
|
@@ -729,8 +737,8 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) const | |
| } | ||
| break; | ||
| case M12_pCorner: | ||
| for (int x = 0; x <= i; x++) setPixelColorRaw(XY(x, i), col); | ||
| for (int y = 0; y < i; y++) setPixelColorRaw(XY(i, y), col); | ||
| for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col); // note: <= to include i=0. Relies on overflow check in sPC() | ||
| for (int y = 0; y < i; y++) setPixelColorXY(i, y, col); | ||
| break; | ||
| case M12_sPinwheel: { | ||
| // Uses Bresenham's algorithm to place coordinates of two lines in arrays then draws between them | ||
|
|
@@ -1189,8 +1197,8 @@ void WS2812FX::finalizeInit() { | |
| deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist) | ||
|
|
||
| // allocate frame buffer after matrix has been set up (gaps!) | ||
| if (_pixels) _pixels = static_cast<uint32_t*>(d_realloc(_pixels, getLengthTotal() * sizeof(uint32_t))); | ||
| else _pixels = static_cast<uint32_t*>(d_malloc(getLengthTotal() * sizeof(uint32_t))); | ||
| if (_pixels) d_free(_pixels); | ||
| _pixels = static_cast<uint32_t*>(d_malloc(getLengthTotal() * sizeof(uint32_t))); | ||
| DEBUG_PRINTF_P(PSTR("strip buffer size: %uB\n"), getLengthTotal() * sizeof(uint32_t)); | ||
|
|
||
| DEBUG_PRINTF_P(PSTR("Heap after strip init: %uB\n"), ESP.getFreeHeap()); | ||
|
|
@@ -1677,7 +1685,7 @@ void WS2812FX::setTransitionMode(bool t) { | |
|
|
||
| // wait until frame is over (service() has finished or time for 1 frame has passed; yield() crashes on 8266) | ||
| void WS2812FX::waitForIt() { | ||
| unsigned long maxWait = millis() + getFrameTime(); | ||
| unsigned long maxWait = millis() + getFrameTime() + 100; // TODO: this needs a proper fix for timeout! | ||
| while (isServicing() && maxWait > millis()) delay(1); | ||
| #ifdef WLED_DEBUG | ||
| if (millis() >= maxWait) DEBUG_PRINTLN(F("Waited for strip to finish servicing.")); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to free the old buffer,
realloc()has alreadyfree()d it for you.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unless it returned null)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but only if it does not fail, i.e. if newData is valid. Or ist that incorrect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct.
But if realloc did allocate a new buffer for you, there's no point in releasing it and trying again; malloc could just give you the new buffer back, since there wasn't enough space to extend the old one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right, I had an error in my thought process thinking that if a new segment is created and the old data copied it would help fragmentation if deleting all and allocating new but that is exactly what realloc() actually does.