diff --git a/firmware/buflib.c b/firmware/buflib.c index 2ceb7fcb16..1aa7404ece 100644 --- a/firmware/buflib.c +++ b/firmware/buflib.c @@ -647,9 +647,9 @@ free_space_at_end(struct buflib_context* ctx) return 0; } -/* Return the maximum allocatable memory in bytes */ +/* Return the maximum allocatable contiguous memory in bytes */ size_t -buflib_available(struct buflib_context* ctx) +buflib_allocatable(struct buflib_context* ctx) { union buflib_data *this; size_t free_space = 0, max_free_space = 0; @@ -687,6 +687,29 @@ buflib_available(struct buflib_context* ctx) return 0; } +/* Return the amount of unallocated memory in bytes (even if not contiguous) */ +size_t +buflib_available(struct buflib_context* ctx) +{ + union buflib_data *this; + size_t free_space = 0; + + /* now look if there's free in holes */ + for(this = find_first_free(ctx); this < ctx->alloc_end; this += abs(this->val)) + { + if (this->val < 0) + { + free_space += -this->val; + continue; + } + } + + free_space *= sizeof(union buflib_data); /* make it bytes */ + free_space += free_space_at_end(ctx); + + return free_space; +} + /* * Allocate all available (as returned by buflib_available()) memory and return * a handle to it diff --git a/firmware/core_alloc.c b/firmware/core_alloc.c index 47faed6e95..aa662fbee5 100644 --- a/firmware/core_alloc.c +++ b/firmware/core_alloc.c @@ -67,6 +67,11 @@ size_t core_available(void) return buflib_available(&core_ctx); } +size_t core_allocatable(void) +{ + return buflib_allocatable(&core_ctx); +} + int core_free(int handle) { return buflib_free(&core_ctx, handle); diff --git a/firmware/include/buflib.h b/firmware/include/buflib.h index 6c9ccf7402..7183951c6c 100644 --- a/firmware/include/buflib.h +++ b/firmware/include/buflib.h @@ -143,15 +143,20 @@ void buflib_init(struct buflib_context *context, void *buf, size_t size); /** - * Returns how many bytes left the buflib has to satisfy allocations. + * Returns the amount of unallocated bytes. It does not mean this amount + * can be actually allocated because they might not be contiguous. * - * This function does not yet consider possible compaction so there might - * be more space left. This may change in the future. - * - * Returns: The number of bytes left in the memory pool. + * Returns: The number of unallocated bytes in the memory pool. */ size_t buflib_available(struct buflib_context *ctx); +/** + * Returns the biggest possible allocation that can be determined to succeed. + * + * Returns: The amount of bytes of the biggest unallocated, contiguous region. + */ +size_t buflib_allocatable(struct buflib_context *ctx); + /** * Allocates memory from buflib's memory pool diff --git a/firmware/include/core_alloc.h b/firmware/include/core_alloc.h index d234947db1..a100b7cc6c 100644 --- a/firmware/include/core_alloc.h +++ b/firmware/include/core_alloc.h @@ -16,6 +16,7 @@ int core_alloc_maximum(const char* name, size_t *size, struct buflib_callbacks * bool core_shrink(int handle, void* new_start, size_t new_size); int core_free(int handle); size_t core_available(void); +size_t core_allocatable(void); /* DO NOT ADD wrappers for buflib_buffer_out/in. They do not call * the move callbacks and are therefore unsafe in the core */