head_4 and heap_5 utility function to return size of allocated block

asund wrote on Monday, March 26, 2018:

Hi, I was wondering if you thought it might be helpful to have a utility function that returns the size of an allocated block in the heap_4 and heap_5 implementations. heap_2 could also support it, but fragmentation would make my use case less useful.

I am using the GNU ARM Embedded toolchain and providing implementations for the standard C memory management functions that map to FreeRTOS’ heap to avoid using newlib’s. Knowing the size of an allocated block allows me to provide a niave realloc implementation (allocate new, copy old to new, free old) which allows nicer integration with some third party libraries that use that function.

I am currently doing this by duplicating the knowledge of the block link structure (I don’t like modifying external code if possible) and using the approach in vPortFree to obtain the allocated size, but I thought it might be nice to have this ability in the official distribution.

On a side note, does anyone think there would be interest for a community contribution of a realloc-like function at the FreeRTOS heap level that could shrink or attempt to grow an allocation in place?

rtel wrote on Monday, March 26, 2018:

Hi - do you mean to have a function to which you pass in a pointer to a
previously allocated block, and the function then returns the block’s
size? If so, I think I could add something in quite simply.

asund wrote on Monday, March 26, 2018:

Yes, that’s correct. In my implementation I just copied vPortFree to get the list traversing code and then modified it to return the size of the allocated block instead of freeing it.

rdkehn wrote on Tuesday, March 27, 2018:

I use the following addition to heap_4.c. I haven’t tested with other heap allocators; but, this does seem to work with heap_4. The name is derived from gcc/glibc malloc_usable_size() function.

size_t xPortMallocUsableSize( void *pv )
{
uint8_t *puc = ( uint8_t * ) pv;
BlockLink_t *pxLink;
size_t sz = 0;

	if( pv != NULL )
	{
		vTaskSuspendAll();
		{
			/* The memory being checked will have an BlockLink_t structure immediately
			before it. */
			puc -= xHeapStructSize;

			/* This casting is to keep the compiler from issuing warnings. */
			pxLink = ( void * ) puc;

			/* Check if the block is actually allocated. */
			configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
			configASSERT( pxLink->pxNextFreeBlock == NULL );

			sz = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize;
		}
		( void ) xTaskResumeAll();
	}

	return sz;
}