Skip to content
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

xtensa/esp32: Fix the issue of WiFi internal malloc from PSRAM #2832

Conversation

cwespressif
Copy link
Contributor

Summary

SPIRAM is not DMA-capable, while WiFi internal malloc from heap must be DMA-capable, We must avoid internal malloc from the heap of PSRAM

Impact

If WiFi internal malloc from PSRAM, it will cause the system block.

Testing

ESP32

@cwespressif cwespressif changed the title xtensa/esp32: Fix the issue of wifi internal malloc from psram xtensa/esp32: Fix the issue of WiFi internal malloc from PSRAM Feb 9, 2021
arch/xtensa/Kconfig Outdated Show resolved Hide resolved
arch/xtensa/Kconfig Outdated Show resolved Hide resolved
@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch 2 times, most recently from 0367052 to 295e137 Compare February 10, 2021 06:20
arch/xtensa/Kconfig Outdated Show resolved Hide resolved
@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch from 295e137 to 355ceed Compare February 10, 2021 09:32
@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch from 355ceed to 2dc0062 Compare February 18, 2021 01:39
@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch from 2dc0062 to 9a6d8a0 Compare February 19, 2021 01:19
arch/xtensa/src/esp32/esp32_allocateheap.c Outdated Show resolved Hide resolved
if (size == 0 || esp32_ptr_extram(ptr))
{
esp_free(ptr);
return NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • size == 0 case is better to be left to kmm_realloc
  • standard realloc is supposed to preserve the old memory in case of a failure. does this wifi_osi_funcs_t variant have a different semantics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size == 0 case means that the size of the new malloc is 0,
In the esp_realloc_internal processing of wifi_osi_funcs_t, you can refer to:
https://github.com/espressif/esp-idf/blob/master/components/heap/heap_caps.c#L318-L321

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the esp-idf implementation does not seem to free the given ptr in case of error.
eg. https://github.com/espressif/esp-idf/blob/master/components/heap/heap_caps.c#L323-L327
it matches my expectation for realloc().
i guess this implementation should do the same.
unfortunately it seems ~impossible to implement it for !CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP case though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as the heap management of NuttX and esp-idf is too different, this part of the modification is too big, now temporarily free the given ptr in case of error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but doesn't it cause double-free sooner or later, as the library would think the ptr still needs to be freed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can do something like the following instead of kmm_realloc. how do you think?

new_ptr = kmm_malloc(new_size);
if (esp32_ptr_extram(new_ptr)) {
    kmm_free(new_ptr);
    return NULL;
}
old_size = malloc_usable_size(old_ptr);
memcpy(new_ptr, old_ptr, min(old_size, new_size));
kmm_free(old_ptr);
return new_ptr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yamt The library will check ptr and then free it, there is a risk of double-free and I also think the above code instead of kmm_realloc is more reasonable, I have modified it, thank you.

esp_free(ptr);
return NULL;
}

return kmm_realloc(ptr, size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess you want to check esp32_ptr_extram on the result of kmm_realloc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to make sure that the old memory pointer is not in external RAM (PSRAM), although this is unlikely to happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kmm_realloc also needs to be checked by esp32_ptr_extram, I have modified it, thank you for your reminder.

@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch from 9a6d8a0 to c2c67b6 Compare February 22, 2021 09:55
@acassis
Copy link
Contributor

acassis commented Feb 24, 2021

@cwespressif is everything done? May we merge it now?

@cwespressif
Copy link
Contributor Author

@cwespressif is everything done? May we merge it now?

@acassis I think it's OK, but I still need to wait to see if @yamt has any comments or suggestions ?

arch/xtensa/src/esp32/esp32_allocateheap.c Outdated Show resolved Hide resolved
if (size == 0 || esp32_ptr_extram(ptr))
{
esp_free(ptr);
return NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the esp-idf implementation does not seem to free the given ptr in case of error.
eg. https://github.com/espressif/esp-idf/blob/master/components/heap/heap_caps.c#L323-L327
it matches my expectation for realloc().
i guess this implementation should do the same.
unfortunately it seems ~impossible to implement it for !CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP case though.

}

p = kmm_realloc(ptr, size);
if (esp32_ptr_extram(ptr))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you mean p, not ptr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's p, sorry for the mistake.

@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch 2 times, most recently from 371563c to 978c21e Compare February 26, 2021 07:16
@Ouss4
Copy link
Member

Ouss4 commented Mar 1, 2021

@yamt do you have any more concerns?

void *old_ptr = ptr;
void *new_ptr = NULL;
size_t old_size = 0;
if (size == 0 || esp32_ptr_extram(old_ptr))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for size == 0 case, you should free ptr.

i don't think you need to check esp32_ptr_extram(old_ptr). the old_ptr will be freed on successful realloc anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@cwespressif cwespressif force-pushed the bugfix/esp32_fix_the_issue_of_wifi_internal_malloc_from_psram branch from 978c21e to 59a385f Compare March 2, 2021 02:36
Copy link
Contributor

@yamt yamt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. thank you

@xiaoxiang781216 xiaoxiang781216 merged commit 1962709 into apache:master Mar 3, 2021
@btashton btashton added this to To-Add in Release Notes - 10.1.0 Apr 12, 2021
@jerpelea jerpelea moved this from To-Add to Minor in Release Notes - 10.1.0 Apr 12, 2021
@jerpelea jerpelea moved this from Minor to Added in Release Notes - 10.1.0 Apr 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

6 participants