diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index a42c72aee66..a7a474081e2 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -5511,6 +5511,31 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, void *k_heap_alloc(struct k_heap *h, size_t bytes, k_timeout_t timeout) __attribute_nonnull(1); +/** + * @brief Allocate and initialize memory for an array of objects from a k_heap + * + * Allocates memory for an array of num objects of size and initializes all + * bytes in the allocated storage to zero. If no memory is available + * immediately, the call will block for the specified timeout (constructed + * via the standard timeout API, or K_NO_WAIT or K_FOREVER) waiting for memory + * to be freed. If the allocation cannot be performed by the expiration of + * the timeout, NULL will be returned. + * Allocated memory is aligned on a multiple of pointer sizes. + * + * @note @a timeout must be set to K_NO_WAIT if called from ISR. + * @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT. + * + * @funcprops \isr_ok + * + * @param h Heap from which to allocate + * @param num Number of objects to allocate + * @param size Desired size of each object to allocate + * @param timeout How long to wait, or K_NO_WAIT + * @return A pointer to valid heap memory, or NULL + */ +void *k_heap_calloc(struct k_heap *h, size_t num, size_t size, k_timeout_t timeout) + __attribute_nonnull(1); + /** * @brief Reallocate memory from a k_heap * diff --git a/kernel/kheap.c b/kernel/kheap.c index 55b9feffced..7c402e740fd 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -116,6 +116,25 @@ void *k_heap_alloc(struct k_heap *heap, size_t bytes, k_timeout_t timeout) return ret; } +void *k_heap_calloc(struct k_heap *heap, size_t num, size_t size, k_timeout_t timeout) +{ + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap, calloc, heap, timeout); + + void *ret = NULL; + size_t bounds = 0U; + + if (!size_mul_overflow(num, size, &bounds)) { + ret = k_heap_alloc(heap, bounds, timeout); + } + if (ret != NULL) { + (void)memset(ret, 0, bounds); + } + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap, calloc, heap, timeout, ret); + + return ret; +} + void *k_heap_realloc(struct k_heap *heap, void *ptr, size_t bytes, k_timeout_t timeout) { k_timepoint_t end = sys_timepoint_calc(timeout);