mirror of
https://github.com/espressif/tlsf.git
synced 2025-12-26 09:09:02 +00:00
Merge branch 'feat/add-malloc-with-address' into 'idf'
feat(tlsf): Add a function to malloc at a given address See merge request espressif/tlsf!8
This commit is contained in:
71
tlsf.c
71
tlsf.c
@@ -1009,6 +1009,77 @@ void* tlsf_malloc(tlsf_t tlsf, size_t size)
|
|||||||
return block_prepare_used(control, block, adjust);
|
return block_prepare_used(control, block, adjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate memory of at least `size` bytes at a given address in the pool.
|
||||||
|
*
|
||||||
|
* @param tlsf TLSF structure to allocate memory from.
|
||||||
|
* @param size Minimum size, in bytes, of the memory to allocate
|
||||||
|
* @param address address at which the allocation must be done
|
||||||
|
*
|
||||||
|
* @return pointer to free memory or NULL in case of incapacity to perform the malloc
|
||||||
|
*/
|
||||||
|
void* tlsf_malloc_addr(tlsf_t tlsf, size_t size, void *address)
|
||||||
|
{
|
||||||
|
control_t* control = tlsf_cast(control_t*, tlsf);
|
||||||
|
|
||||||
|
/* adjust the address to be ALIGN_SIZE bytes aligned. */
|
||||||
|
const unsigned int addr_adjusted = align_down(tlsf_cast(unsigned int, address), ALIGN_SIZE);
|
||||||
|
|
||||||
|
/* adjust the size to be ALIGN_SIZE bytes aligned. Add to the size the difference
|
||||||
|
* between the requested address and the address_adjusted. */
|
||||||
|
size_t size_adjusted = align_up(size + (tlsf_cast(unsigned int, address) - addr_adjusted), ALIGN_SIZE);
|
||||||
|
|
||||||
|
/* find the free block that starts before the address in the pool and is big enough
|
||||||
|
* to support the size of allocation at the given address */
|
||||||
|
block_header_t* block = offset_to_block(tlsf_get_pool(tlsf), -(int)block_header_overhead);
|
||||||
|
|
||||||
|
const char *alloc_start = tlsf_cast(char*, addr_adjusted);
|
||||||
|
const char *alloc_end = alloc_start + size_adjusted;
|
||||||
|
bool block_found = false;
|
||||||
|
do {
|
||||||
|
const char *block_start = tlsf_cast(char*, block_to_ptr(block));
|
||||||
|
const char *block_end = tlsf_cast(char*, block_to_ptr(block)) + block_size(block);
|
||||||
|
if (block_start <= alloc_start && block_end > alloc_start) {
|
||||||
|
/* A: block_end >= alloc_end. B: block is free */
|
||||||
|
if (block_end < alloc_end || !block_is_free(block)) {
|
||||||
|
/* not(A) || not(B)
|
||||||
|
* We won't find another suitable block from this point on
|
||||||
|
* so we can break and return NULL */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* A && B
|
||||||
|
* The block can fit the alloc and is located at a position allowing for the alloc
|
||||||
|
* to be placed at the given address. We can return from the while */
|
||||||
|
block_found = true;
|
||||||
|
} else if (!block_is_last(block)) {
|
||||||
|
/* the block doesn't match the expected criteria, continue with the next block */
|
||||||
|
block = block_next(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (!block_is_last(block) && block_found == false);
|
||||||
|
|
||||||
|
if (!block_found) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove block from the free list since a part of it will be used */
|
||||||
|
block_remove(control, block);
|
||||||
|
|
||||||
|
/* trim any leading space or add the leading space to the overall requested size
|
||||||
|
* if the leading space is not big enough to store a block of minimum size */
|
||||||
|
const size_t space_before_addr_adjusted = addr_adjusted - tlsf_cast(unsigned int, block_to_ptr(block));
|
||||||
|
block_header_t *return_block = block;
|
||||||
|
if (space_before_addr_adjusted >= block_size_min) {
|
||||||
|
return_block = block_trim_free_leading(control, block, space_before_addr_adjusted);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_adjusted += space_before_addr_adjusted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trim trailing space if any and return a pointer to the first usable byte allocated */
|
||||||
|
return block_prepare_used(control, return_block, size_adjusted);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocate memory of at least `size` bytes where byte at `data_offset` will be aligned to `alignment`.
|
* @brief Allocate memory of at least `size` bytes where byte at `data_offset` will be aligned to `alignment`.
|
||||||
*
|
*
|
||||||
|
|||||||
1
tlsf.h
1
tlsf.h
@@ -33,6 +33,7 @@ void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
|
|||||||
void* tlsf_malloc(tlsf_t tlsf, size_t size);
|
void* tlsf_malloc(tlsf_t tlsf, size_t size);
|
||||||
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size);
|
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size);
|
||||||
void* tlsf_memalign_offs(tlsf_t tlsf, size_t align, size_t size, size_t offset);
|
void* tlsf_memalign_offs(tlsf_t tlsf, size_t align, size_t size, size_t offset);
|
||||||
|
void* tlsf_malloc_addr(tlsf_t tlsf, size_t size, void *address);
|
||||||
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
|
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
|
||||||
void tlsf_free(tlsf_t tlsf, void* ptr);
|
void tlsf_free(tlsf_t tlsf, void* ptr);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user