realloc(): move mempool internal knowledge out of generic lib code
The realloc function was a bit too intimate with the mempool accounting. Abstract that knowledge away and move it where it belongs. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
8940c25145
commit
2129937d3d
|
@ -99,4 +99,17 @@ void *sys_mem_pool_alloc(struct sys_mem_pool *p, size_t size);
|
|||
*/
|
||||
void sys_mem_pool_free(void *ptr);
|
||||
|
||||
/**
|
||||
* @brief Try to perform in-place expansion of memory allocated from a pool
|
||||
*
|
||||
* Return 0 if memory previously allocated by sys_mem_pool_alloc()
|
||||
* can accommodate a new size, otherwise return the size of data that
|
||||
* needs to be copied over to new memory.
|
||||
*
|
||||
* @param ptr Pointer to previously allocated memory
|
||||
* @param new_size New size requested for the memory block
|
||||
* @return A 0 if OK, or size of data to copy elsewhere
|
||||
*/
|
||||
size_t sys_mem_pool_try_expand_inplace(void *ptr, size_t new_size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -87,10 +87,8 @@ void *calloc(size_t nmemb, size_t size)
|
|||
|
||||
void *realloc(void *ptr, size_t requested_size)
|
||||
{
|
||||
struct sys_mem_pool_block *blk;
|
||||
size_t struct_blk_size = WB_UP(sizeof(struct sys_mem_pool_block));
|
||||
size_t block_size, total_requested_size;
|
||||
void *new_ptr;
|
||||
size_t copy_size;
|
||||
|
||||
if (ptr == NULL) {
|
||||
return malloc(requested_size);
|
||||
|
@ -101,22 +99,9 @@ void *realloc(void *ptr, size_t requested_size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Stored right before the pointer passed to the user */
|
||||
blk = (struct sys_mem_pool_block *)((char *)ptr - struct_blk_size);
|
||||
|
||||
/* Determine size of previously allocated block by its level.
|
||||
* Most likely a bit larger than the original allocation
|
||||
*/
|
||||
block_size = blk->pool->base.max_sz;
|
||||
for (int i = 1; i <= blk->level; i++) {
|
||||
block_size = WB_DN(block_size / 4);
|
||||
}
|
||||
|
||||
/* We really need this much memory */
|
||||
total_requested_size = requested_size + struct_blk_size;
|
||||
|
||||
if (block_size >= total_requested_size) {
|
||||
/* Existing block large enough, nothing to do */
|
||||
copy_size = sys_mem_pool_try_expand_inplace(ptr, requested_size);
|
||||
if (copy_size == 0) {
|
||||
/* Existing block large enough, nothing else to do */
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -125,7 +110,7 @@ void *realloc(void *ptr, size_t requested_size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(new_ptr, ptr, block_size - struct_blk_size);
|
||||
memcpy(new_ptr, ptr, copy_size);
|
||||
free(ptr);
|
||||
|
||||
return new_ptr;
|
||||
|
|
|
@ -354,3 +354,30 @@ void sys_mem_pool_free(void *ptr)
|
|||
sys_mutex_unlock(&p->mutex);
|
||||
}
|
||||
|
||||
size_t sys_mem_pool_try_expand_inplace(void *ptr, size_t requested_size)
|
||||
{
|
||||
struct sys_mem_pool_block *blk;
|
||||
size_t struct_blk_size = WB_UP(sizeof(struct sys_mem_pool_block));
|
||||
size_t block_size, total_requested_size;
|
||||
|
||||
ptr = (char *)ptr - struct_blk_size;
|
||||
blk = (struct sys_mem_pool_block *)ptr;
|
||||
|
||||
/*
|
||||
* Determine size of previously allocated block by its level.
|
||||
* Most likely a bit larger than the original allocation
|
||||
*/
|
||||
block_size = blk->pool->base.max_sz;
|
||||
for (int i = 1; i <= blk->level; i++) {
|
||||
block_size = WB_DN(block_size / 4);
|
||||
}
|
||||
|
||||
/* We really need this much memory */
|
||||
total_requested_size = requested_size + struct_blk_size;
|
||||
|
||||
if (block_size >= total_requested_size) {
|
||||
/* size adjustment can occur in-place */
|
||||
return 0;
|
||||
}
|
||||
return block_size - struct_blk_size;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue