From 80cd9dac228a1b5d26d149a840007dd046b22111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Leksell?= Date: Fri, 26 Mar 2021 13:42:25 +0100 Subject: [PATCH] Tracing: Memory Heap tracing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Memory heap tracing, default trace hooks, and documentation. Signed-off-by: Torbjörn Leksell --- include/kernel.h | 12 +--- include/tracing/tracing.h | 114 ++++++++++++++++++++++++++++++++++++++ kernel/kheap.c | 30 ++++++++++ kernel/mempool.c | 31 ++++++++++- 4 files changed, 177 insertions(+), 10 deletions(-) diff --git a/include/kernel.h b/include/kernel.h index 36ffec910d7..bbda4560371 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -5028,11 +5028,8 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, * @param timeout How long to wait, or K_NO_WAIT * @return A pointer to valid heap memory, or NULL */ -static inline void *k_heap_alloc(struct k_heap *h, size_t bytes, - k_timeout_t timeout) -{ - return k_heap_aligned_alloc(h, sizeof(void *), bytes, timeout); -} +void *k_heap_alloc(struct k_heap *h, size_t bytes, + k_timeout_t timeout); /** * @brief Free memory allocated by k_heap_alloc() @@ -5105,10 +5102,7 @@ extern void *k_aligned_alloc(size_t align, size_t size); * * @return Address of the allocated memory if successful; otherwise NULL. */ -static inline void *k_malloc(size_t size) -{ - return k_aligned_alloc(sizeof(void *), size); -} +extern void *k_malloc(size_t size); /** * @brief Free memory allocated from heap. diff --git a/include/tracing/tracing.h b/include/tracing/tracing.h index 1b770e35bcc..029d5b50a91 100644 --- a/include/tracing/tracing.h +++ b/include/tracing/tracing.h @@ -1296,6 +1296,120 @@ */ /* end of pipe_tracing_apis */ + + +/** + * @brief Heap Tracing APIs + * @defgroup heap_tracing_apis Heap Tracing APIs + * @ingroup tracing_apis + * @{ + */ + +/** + * @brief Trace initialization of Heap + * @param h Heap object + */ +#define sys_port_trace_k_heap_init(h) + +/** + * @brief Trace Heap aligned alloc attempt entry + * @param h Heap object + * @param timeout Timeout period + */ +#define sys_port_trace_k_heap_aligned_alloc_enter(h, timeout) + +/** + * @brief Trace Heap align alloc attempt blocking + * @param h Heap object + * @param timeout Timeout period + */ +#define sys_port_trace_k_heap_aligned_alloc_blocking(h, timeout) + +/** + * @brief Trace Heap align alloc attempt outcome + * @param h Heap object + * @param timeout Timeout period + * @param ret Return value + */ +#define sys_port_trace_k_heap_aligned_alloc_exit(h, timeout, ret) + +/** + * @brief Trace Heap alloc enter + * @param h Heap object + * @param timeout Timeout period + */ +#define sys_port_trace_k_heap_alloc_enter(h, timeout) + +/** + * @brief Trace Heap alloc exit + * @param h Heap object + * @param timeout Timeout period + * @param ret Return value + */ +#define sys_port_trace_k_heap_alloc_exit(h, timeout, ret) + +/** + * @brief Trace Heap free + * @param h Heap object + */ +#define sys_port_trace_k_heap_free(h) + +/** + * @brief Trace System Heap aligned alloc enter + * @param heap Heap object + */ +#define sys_port_trace_k_heap_sys_k_aligned_alloc_enter(heap) + +/** + * @brief Trace System Heap aligned alloc exit + * @param heap Heap object + * @param ret Return value + */ +#define sys_port_trace_k_heap_sys_k_aligned_alloc_exit(heap, ret) + +/** + * @brief Trace System Heap aligned alloc enter + * @param heap Heap object + */ +#define sys_port_trace_k_heap_sys_k_malloc_enter(heap) + +/** + * @brief Trace System Heap aligned alloc exit + * @param heap Heap object + * @param ret Return value + */ +#define sys_port_trace_k_heap_sys_k_malloc_exit(heap, ret) + +/** + * @brief Trace System Heap free entry + * @param heap Heap object + */ +#define sys_port_trace_k_heap_sys_k_free_enter(heap) + +/** + * @brief Trace System Heap free exit + * @param heap Heap object + */ +#define sys_port_trace_k_heap_sys_k_free_exit(heap) + +/** + * @brief Trace System heap calloc enter + * @param heap + */ +#define sys_port_trace_k_heap_sys_k_calloc_enter(heap) + +/** + * @brief Trace System heap calloc exit + * @param heap Heap object + * @param ret Return value + */ +#define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) + +/** + * @} + */ /* end of heap_tracing_apis */ + + /** * @} */ diff --git a/kernel/kheap.c b/kernel/kheap.c index 7683d050702..8726342aef6 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -13,6 +13,8 @@ void k_heap_init(struct k_heap *h, void *mem, size_t bytes) { z_waitq_init(&h->wait_q); sys_heap_init(&h->heap, mem, bytes); + + SYS_PORT_TRACING_OBJ_INIT(k_heap, h); } static int statics_init(const struct device *unused) @@ -33,8 +35,12 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, void *ret = NULL; k_spinlock_key_t key = k_spin_lock(&h->lock); + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap, aligned_alloc, h, timeout); + __ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), ""); + bool blocked_alloc = false; + while (ret == NULL) { ret = sys_heap_aligned_alloc(&h->heap, align, bytes); @@ -44,21 +50,45 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, break; } + if (!blocked_alloc) { + blocked_alloc = true; + + SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_heap, aligned_alloc, h, timeout); + } else { + /** + * @todo Trace attempt to avoid empty trace segments + */ + } + (void) z_pend_curr(&h->lock, key, &h->wait_q, K_TICKS(end - now)); key = k_spin_lock(&h->lock); } + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap, aligned_alloc, h, timeout, ret); + k_spin_unlock(&h->lock, key); return ret; } +void *k_heap_alloc(struct k_heap *h, size_t bytes, k_timeout_t timeout) +{ + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap, alloc, h, timeout); + + void *ret = k_heap_aligned_alloc(h, sizeof(void *), bytes, timeout); + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap, alloc, h, timeout, ret); + + return ret; +} + void k_heap_free(struct k_heap *h, void *mem) { k_spinlock_key_t key = k_spin_lock(&h->lock); sys_heap_free(&h->heap, mem); + SYS_PORT_TRACING_OBJ_FUNC(k_heap, free, h); if (IS_ENABLED(CONFIG_MULTITHREADING) && z_unpend_all(&h->wait_q) != 0) { z_reschedule(&h->lock, key); } else { diff --git a/kernel/mempool.c b/kernel/mempool.c index 295bb2259a2..606056244ac 100644 --- a/kernel/mempool.c +++ b/kernel/mempool.c @@ -47,7 +47,12 @@ void k_free(void *ptr) if (ptr != NULL) { heap_ref = ptr; ptr = --heap_ref; + + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_free, *heap_ref); + k_heap_free(*heap_ref, ptr); + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_free, *heap_ref); } } @@ -65,7 +70,24 @@ void *k_aligned_alloc(size_t align, size_t size) __ASSERT((align & (align - 1)) == 0, "align must be a power of 2"); - return z_heap_aligned_alloc(_SYSTEM_HEAP, align, size); + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_aligned_alloc, _SYSTEM_HEAP); + + void *ret = z_heap_aligned_alloc(_SYSTEM_HEAP, align, size); + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_aligned_alloc, _SYSTEM_HEAP, ret); + + return ret; +} + +void *k_malloc(size_t size) +{ + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_malloc, _SYSTEM_HEAP); + + void *ret = k_aligned_alloc(sizeof(void *), size); + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_malloc, _SYSTEM_HEAP, ret); + + return ret; } void *k_calloc(size_t nmemb, size_t size) @@ -73,7 +95,11 @@ void *k_calloc(size_t nmemb, size_t size) void *ret; size_t bounds; + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_calloc, _SYSTEM_HEAP); + if (size_mul_overflow(nmemb, size, &bounds)) { + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_calloc, _SYSTEM_HEAP, NULL); + return NULL; } @@ -81,6 +107,9 @@ void *k_calloc(size_t nmemb, size_t size) if (ret != NULL) { (void)memset(ret, 0, bounds); } + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_calloc, _SYSTEM_HEAP, ret); + return ret; }