diff --git a/lib/os/Kconfig b/lib/os/Kconfig index 9d02db81c8b..ea9ca562f9c 100644 --- a/lib/os/Kconfig +++ b/lib/os/Kconfig @@ -46,6 +46,53 @@ config SYS_HEAP_ALLOC_LOOPS keeps the maximum runtime at a tight bound so that the heap is useful in locked or ISR contexts. +choice + prompt "Supported heap sizes" + depends on !64BIT + default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) + default SYS_HEAP_AUTO + help + Heaps using reduced-size chunk headers can accommodate so called + "small" heaps with a total size of 262136 bytes or less. + + Heaps using full-size chunk headers can have a total size up to + 16383 megabytes. The overhead is of course bigger. + + On 32-bit system the tradeoff is selectable between: + + - "small" heaps with low memory and runtime overhead; + + - "big" heaps with bigger memory overhead even for small heaps; + + - "auto" providing optimal memory overhead in all cases but with + a higher runtime overhead and somewhat bigger code footprint. + + On 64-bit systems the "big" chunk header size conveniently provides + the needed alignment on returned memory allocations. Small chunk + headers would require alignment padding up to the big header size + anyway so "big" heap is the only option in that case. + +config SYS_HEAP_SMALL_ONLY + bool "Support for small heaps only" + help + Select this to optimize the code and memory usage if all your + heaps are 262136 bytes or less. + +config SYS_HEAP_BIG_ONLY + bool "Support for big heaps only" + help + Select this to optimize the code for big heaps only. This can + accommodate any heap size but memory usage won't be as + efficient with small sized heaps. + +config SYS_HEAP_AUTO + bool "Support for both small and big heaps at run time" + help + This option optimizes memory usage for each heap according to + their size albeit with some overhead in code size and execution. + +endchoice + config PRINTK_SYNC bool "Serialize printk() calls" default y if SMP && MP_NUM_CPUS > 1 diff --git a/lib/os/heap.c b/lib/os/heap.c index fcbb0c7300d..d78cd16420c 100644 --- a/lib/os/heap.c +++ b/lib/os/heap.c @@ -390,8 +390,13 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr, void sys_heap_init(struct sys_heap *heap, void *mem, size_t bytes) { - /* Must fit in a 31 bit count of HUNK_UNIT */ - __ASSERT(bytes / CHUNK_UNIT <= 0x7fffffffU, "heap size is too big"); + if (IS_ENABLED(CONFIG_SYS_HEAP_SMALL_ONLY)) { + /* Must fit in a 15 bit count of HUNK_UNIT */ + __ASSERT(bytes / CHUNK_UNIT <= 0x7fffU, "heap size is too big"); + } else { + /* Must fit in a 31 bit count of HUNK_UNIT */ + __ASSERT(bytes / CHUNK_UNIT <= 0x7fffffffU, "heap size is too big"); + } /* Reserve the end marker chunk's header */ __ASSERT(bytes > heap_footer_bytes(bytes), "heap size is too small"); diff --git a/lib/os/heap.h b/lib/os/heap.h index a268fc528b9..96f7b3826de 100644 --- a/lib/os/heap.h +++ b/lib/os/heap.h @@ -74,7 +74,13 @@ struct z_heap { static inline bool big_heap_chunks(chunksz_t chunks) { - return sizeof(void *) > 4U || chunks > 0x7fffU; + if (IS_ENABLED(CONFIG_SYS_HEAP_SMALL_ONLY)) { + return false; + } + if (IS_ENABLED(CONFIG_SYS_HEAP_BIG_ONLY) || sizeof(void *) > 4U) { + return true; + } + return chunks > 0x7fffU; } static inline bool big_heap_bytes(size_t bytes) diff --git a/tests/lib/heap/src/main.c b/tests/lib/heap/src/main.c index 76af80a8bfd..316f639d6cf 100644 --- a/tests/lib/heap/src/main.c +++ b/tests/lib/heap/src/main.c @@ -210,6 +210,11 @@ static void test_big_heap(void) struct sys_heap heap; struct z_heap_stress_result result; + if (IS_ENABLED(CONFIG_SYS_HEAP_SMALL_ONLY)) { + TC_PRINT("big heap support is disabled\n"); + ztest_test_skip(); + } + TC_PRINT("Testing big (%d byte) heap\n", (int) BIG_HEAP_SZ); sys_heap_init(&heap, heapmem, BIG_HEAP_SZ);