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

Fix umm_blocks() #8429

Merged
merged 1 commit into from
Jan 3, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 57 additions & 17 deletions cores/esp8266/umm_malloc/umm_malloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,28 +266,68 @@ static umm_heap_context_t *umm_get_ptr_context(void *ptr) {

/* ------------------------------------------------------------------------ */

static uint16_t umm_blocks( size_t size ) {
static uint16_t umm_blocks(size_t size) {

/*
* The calculation of the block size is not too difficult, but there are
* a few little things that we need to be mindful of.
*
* When a block removed from the free list, the space used by the free
* pointers is available for data. That's what the first calculation
* of size is doing.
*/
/*
* The calculation of the block size is not too difficult, but there are
* a few little things that we need to be mindful of.
*
* When a block removed from the free list, the space used by the free
* pointers is available for data. That's what the first calculation
* of size is doing.
*
* We don't check for the special case of (size == 0) here as this needs
* special handling in the caller depending on context. For example when we
* realloc() a block to size 0 it should simply be freed.
*
* We do NOT need to check for allocating more blocks than the heap can
* possibly hold - the allocator figures this out for us.
*
* There are only two cases left to consider:
*
* 1. (size <= body) Obviously this is just one block
* 2. (blocks > (2^15)) This should return ((2^15)) to force a
* failure when the allocator runs
*
* If the requested size is greater that 32677-2 blocks (max block index
* minus the overhead of the top and bottom bookkeeping blocks) then we
* will return an incorrectly truncated value when the result is cast to
* a uint16_t.
*/

if( size <= (sizeof(((umm_block *)0)->body)) )
return( 1 );
if (size <= (sizeof(((umm_block *)0)->body))) {
return 1;
}

/*
* If it's for more than that, then we need to figure out the number of
* additional whole blocks the size of an umm_block are required.
*/
/*
* If it's for more than that, then we need to figure out the number of
* additional whole blocks the size of an umm_block are required, so
* reduce the size request by the number of bytes in the body of the
* first block.
*/

size -= (sizeof(((umm_block *)0)->body));

size -= ( 1 + (sizeof(((umm_block *)0)->body)) );
/* NOTE WELL that we take advantage of the fact that INT16_MAX is the
* number of blocks that we can index in 15 bits :-)
*
* The below expression looks wierd, but it's right. Assuming body
* size of 4 bytes and a block size of 8 bytes:
*
* BYTES (BYTES-BODY) (BYTES-BODY-1)/BLOCKSIZE BLOCKS
* 1 n/a n/a 1
* 5 1 0 2
* 12 8 0 2
* 13 9 1 3
*/

size_t blocks = (2 + ((size - 1) / sizeof(umm_block)));

if (blocks > (INT16_MAX)) {
blocks = INT16_MAX;
}

return( 2 + size/(sizeof(umm_block)) );
return (uint16_t)blocks;
}

/* ------------------------------------------------------------------------ */
Expand Down