From: Chali Anis <chalian...@gmail.com> barebox running under an operating system (or nearly one like UEFI) does not have control over all the memory and should not hog too much memory upfront as that can interfere with other applications, e.g. EFI drivers or the EFI firmware itself.
To accommodate this use case, allow TLSF to dynamically request more memory from an external store via tlsf_register_store(). Signed-off-by: Ahmad Fatoum <a.fat...@barebox.org> Signed-off-by: Chali Anis <chalian...@gmail.com> --- common/tlsf.c | 29 ++++++++++++++++++++++++++++- include/tlsf.h | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/common/tlsf.c b/common/tlsf.c index 4ee53a9b2f20..636b57b1c642 100644 --- a/common/tlsf.c +++ b/common/tlsf.c @@ -159,6 +159,9 @@ typedef struct control_t /* Empty lists point at this block to indicate they are free. */ block_header_t block_null; + void (*request_store)(tlsf_t, size_t); + + /* Bitmaps for free lists. */ unsigned int fl_bitmap; unsigned int sl_bitmap[FL_INDEX_COUNT]; @@ -568,7 +571,7 @@ static block_header_t* block_trim_free_leading(control_t* control, block_header_ return remaining_block; } -static block_header_t* block_locate_free(control_t* control, size_t size) +static block_header_t* __block_locate_free(control_t* control, size_t size) { int fl = 0, sl = 0; block_header_t* block = 0; @@ -598,6 +601,23 @@ static block_header_t* block_locate_free(control_t* control, size_t size) return block; } +static block_header_t* block_locate_free(control_t* control, size_t size) +{ + block_header_t *block; + + block = __block_locate_free(control, size); + if (block) + return block; + + if (!control->request_store || !size) + return NULL; + + control->request_store(tlsf_cast(tlsf_t, control), + size + tlsf_pool_overhead()); + + return __block_locate_free(control, size); +} + static void* block_prepare_used(control_t* control, block_header_t* block, size_t size, size_t used) { @@ -934,6 +954,13 @@ tlsf_t tlsf_create_with_pool(void* mem, size_t bytes) return tlsf; } +void tlsf_register_store(tlsf_t tlsf, void (*cb)(tlsf_t tlsf, size_t bytes)) +{ + control_t* control = tlsf_cast(control_t*, tlsf); + + control->request_store = cb; +} + void tlsf_destroy(tlsf_t tlsf) { /* Nothing to do. */ diff --git a/include/tlsf.h b/include/tlsf.h index e0dcdac1e7ab..ea86b0600c49 100644 --- a/include/tlsf.h +++ b/include/tlsf.h @@ -63,6 +63,7 @@ tlsf_t tlsf_create(void* mem); tlsf_t tlsf_create_with_pool(void* mem, size_t bytes); void tlsf_destroy(tlsf_t tlsf); pool_t tlsf_get_pool(tlsf_t tlsf); +void tlsf_register_store(tlsf_t tlsf, void (*cb)(tlsf_t tlsf, size_t bytes)); /* Add/remove memory pools. */ pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes); -- 2.34.1