mirror of
https://github.com/espressif/tlsf.git
synced 2025-12-26 09:09:02 +00:00
committed by
Guillaume Souchere
parent
b76f0fefd1
commit
1968e04261
53
tlsf.c
53
tlsf.c
@@ -916,10 +916,34 @@ void* tlsf_malloc(tlsf_t tlsf, size_t size)
|
|||||||
return block_prepare_used(control, block, adjust);
|
return block_prepare_used(control, block, adjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
|
/**
|
||||||
|
* @brief Allocate memory of at least `size` bytes where byte at `data_offset` will be aligned to `alignment`.
|
||||||
|
*
|
||||||
|
* This function will allocate memory pointed by `ptr`. However, the byte at `data_offset` of
|
||||||
|
* this piece of memory (i.e., byte at `ptr` + `data_offset`) will be aligned to `alignment`.
|
||||||
|
* This function is useful for allocating memory that will internally have a header, and the
|
||||||
|
* usable memory following the header (i.e. `ptr` + `data_offset`) must be aligned.
|
||||||
|
*
|
||||||
|
* For example, a call to `multi_heap_aligned_alloc_impl_offs(heap, 64, 256, 20)` will return a
|
||||||
|
* pointer `ptr` to free memory of minimum 64 bytes, where `ptr + 20` is aligned on `256`.
|
||||||
|
* So `(ptr + 20) % 256` equals 0.
|
||||||
|
*
|
||||||
|
* @param tlsf TLSF structure to allocate memory from.
|
||||||
|
* @param align Alignment for the returned pointer's offset.
|
||||||
|
* @param size Minimum size, in bytes, of the memory to allocate INCLUDING
|
||||||
|
* `data_offset` bytes.
|
||||||
|
* @param data_offset Offset to be aligned on `alignment`. This can be 0, in
|
||||||
|
* this case, the returned pointer will be aligned on
|
||||||
|
* `alignment`. If it is not a multiple of CPU word size,
|
||||||
|
* it will be aligned up to the closest multiple of it.
|
||||||
|
*
|
||||||
|
* @return pointer to free memory.
|
||||||
|
*/
|
||||||
|
void* tlsf_memalign_offs(tlsf_t tlsf, size_t align, size_t size, size_t data_offset)
|
||||||
{
|
{
|
||||||
control_t* control = tlsf_cast(control_t*, tlsf);
|
control_t* control = tlsf_cast(control_t*, tlsf);
|
||||||
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
|
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
|
||||||
|
const size_t off_adjust = align_up(data_offset, ALIGN_SIZE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** We must allocate an additional minimum block size bytes so that if
|
** We must allocate an additional minimum block size bytes so that if
|
||||||
@@ -929,8 +953,11 @@ void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
|
|||||||
** the prev_phys_block field is not valid, and we can't simply adjust
|
** the prev_phys_block field is not valid, and we can't simply adjust
|
||||||
** the size of that block.
|
** the size of that block.
|
||||||
*/
|
*/
|
||||||
const size_t gap_minimum = sizeof(block_header_t);
|
const size_t gap_minimum = sizeof(block_header_t) + off_adjust;
|
||||||
const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align);
|
/* The offset is included in both `adjust` and `gap_minimum`, so we
|
||||||
|
** need to subtract it once.
|
||||||
|
*/
|
||||||
|
const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum - off_adjust, align);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** If alignment is less than or equals base alignment, we're done.
|
** If alignment is less than or equals base alignment, we're done.
|
||||||
@@ -950,8 +977,11 @@ void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
|
|||||||
size_t gap = tlsf_cast(size_t,
|
size_t gap = tlsf_cast(size_t,
|
||||||
tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
|
tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
|
||||||
|
|
||||||
/* If gap size is too small, offset to next aligned boundary. */
|
/*
|
||||||
if (gap && gap < gap_minimum)
|
** If gap size is too small or if there is not gap but we need one,
|
||||||
|
** offset to next aligned boundary.
|
||||||
|
*/
|
||||||
|
if ((gap && gap < gap_minimum) || (!gap && off_adjust))
|
||||||
{
|
{
|
||||||
const size_t gap_remain = gap_minimum - gap;
|
const size_t gap_remain = gap_minimum - gap;
|
||||||
const size_t offset = tlsf_max(gap_remain, align);
|
const size_t offset = tlsf_max(gap_remain, align);
|
||||||
@@ -966,13 +996,24 @@ void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
|
|||||||
if (gap)
|
if (gap)
|
||||||
{
|
{
|
||||||
tlsf_assert(gap >= gap_minimum && "gap size too small");
|
tlsf_assert(gap >= gap_minimum && "gap size too small");
|
||||||
block = block_trim_free_leading(control, block, gap);
|
block = block_trim_free_leading(control, block, gap - off_adjust);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Preparing the block will also the trailing free memory. */
|
||||||
return block_prepare_used(control, block, adjust);
|
return block_prepare_used(control, block, adjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Same as `tlsf_memalign_offs` function but with a 0 offset.
|
||||||
|
* The pointer returned is aligned on `align`.
|
||||||
|
*/
|
||||||
|
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
|
||||||
|
{
|
||||||
|
return tlsf_memalign_offs(tlsf, align, size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void tlsf_free(tlsf_t tlsf, void* ptr)
|
void tlsf_free(tlsf_t tlsf, void* ptr)
|
||||||
{
|
{
|
||||||
/* Don't attempt to free a NULL pointer. */
|
/* Don't attempt to free a NULL pointer. */
|
||||||
|
|||||||
5
tlsf.h
5
tlsf.h
@@ -30,8 +30,9 @@ pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
|
|||||||
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
|
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
|
||||||
|
|
||||||
/* malloc/memalign/realloc/free replacements. */
|
/* malloc/memalign/realloc/free replacements. */
|
||||||
void* tlsf_malloc(tlsf_t tlsf, size_t bytes);
|
void* tlsf_malloc(tlsf_t tlsf, size_t size);
|
||||||
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes);
|
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_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