From dceb26c7b23a3d4033518bce2470658af991add6 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Wed, 28 Aug 2024 10:06:52 +0800 Subject: [PATCH] drivers/segger: add heap data plot Add heap current used to note. Plot it in segger sysview data plot. Signed-off-by: xuxingliang Signed-off-by: Neo Xu --- arch/sim/src/sim/sim_heap.c | 14 ++-- .../configs/systemview/defconfig | 1 + drivers/note/note_driver.c | 9 +- drivers/note/noteram_driver.c | 84 +------------------ drivers/segger/note_sysview.c | 53 ++++++++++-- include/nuttx/note/note_driver.h | 3 +- include/nuttx/sched_note.h | 5 +- mm/mm_heap/mm_free.c | 2 +- mm/mm_heap/mm_initialize.c | 5 +- mm/mm_heap/mm_malloc.c | 3 +- mm/mm_heap/mm_memalign.c | 3 +- mm/mm_heap/mm_realloc.c | 6 +- mm/tlsf/mm_tlsf.c | 19 +++-- sched/Kconfig | 2 +- tools/nxstyle.c | 13 ++- 15 files changed, 100 insertions(+), 122 deletions(-) diff --git a/arch/sim/src/sim/sim_heap.c b/arch/sim/src/sim/sim_heap.c index 0dc48e87f4..e95b559ff1 100644 --- a/arch/sim/src/sim/sim_heap.c +++ b/arch/sim/src/sim/sim_heap.c @@ -186,7 +186,7 @@ static void mm_delayfree(struct mm_heap_s *heap, void *mem, bool delay) int size = host_mallocsize(mem); atomic_fetch_sub(&heap->aordblks, 1); atomic_fetch_sub(&heap->uordblks, size); - sched_note_heap(NOTE_HEAP_FREE, heap, mem, size); + sched_note_heap(NOTE_HEAP_FREE, heap, mem, size, 0); host_free(mem); } } @@ -230,7 +230,7 @@ struct mm_heap_s *mm_initialize(const char *name, procfs_register_meminfo(&heap->mm_procfs); #endif - sched_note_heap(NOTE_HEAP_ADD, heap, heap_start, heap_size); + sched_note_heap(NOTE_HEAP_ADD, heap, heap_start, heap_size, 0); return heap; } @@ -252,9 +252,7 @@ struct mm_heap_s *mm_initialize(const char *name, void mm_uninitialize(struct mm_heap_s *heap) { - sched_note_heap(NOTE_HEAP_REMOVE, heap, heap_start, - (uintptr_t)heap->mm_heapend[0] - - (uintptr_t)heap->mm_heapstart[0]); + sched_note_heap(NOTE_HEAP_REMOVE, heap, NULL, 0, 0); #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO) procfs_unregister_meminfo(&heap->mm_procfs); @@ -393,10 +391,10 @@ void *mm_realloc(struct mm_heap_s *heap, void *oldmem, { if (oldmem != NULL) { - sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize); + sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize, 0); } - sched_note_heap(NOTE_HEAP_ALLOC, heap, mem, newsize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, mem, newsize, 0); } do @@ -488,7 +486,7 @@ void *mm_memalign(struct mm_heap_s *heap, size_t alignment, size_t size) } size = host_mallocsize(mem); - sched_note_heap(NOTE_HEAP_ALLOC, heap, mem, size); + sched_note_heap(NOTE_HEAP_ALLOC, heap, mem, size, 0); atomic_fetch_add(&heap->aordblks, 1); atomic_fetch_add(&heap->uordblks, size); usmblks = atomic_load(&heap->usmblks); diff --git a/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig b/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig index 075534e939..adb3a67086 100644 --- a/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig +++ b/boards/arm/stm32/stm32f429i-disco/configs/systemview/defconfig @@ -38,6 +38,7 @@ CONFIG_RAM_START=0x20000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_INSTRUMENTATION=y +CONFIG_SCHED_INSTRUMENTATION_HEAP=y CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER=y CONFIG_SCHED_INSTRUMENTATION_SWITCH=y CONFIG_SEGGER_SYSVIEW=y diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index 232efde066..7414166542 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -92,8 +92,8 @@ #define note_irqhandler(drv, irq, handler, enter) \ ((drv)->ops->irqhandler && \ ((drv)->ops->irqhandler(drv, irq, handler, enter), true)) -#define note_heap(drv, alloc, data, mem, size) \ - ((drv)->ops->heap && ((drv)->ops->heap(drv, alloc, data, mem, size), true)) +#define note_heap(drv, event, data, mem, size, used) \ + ((drv)->ops->heap && ((drv)->ops->heap(drv, event, data, mem, size, used), true)) #define note_string(drv, ip, buf) \ ((drv)->ops->string && ((drv)->ops->string(drv, ip, buf), true)) #define note_event(drv, ip, event, buf, len) \ @@ -1356,7 +1356,7 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, - size_t size) + size_t size, size_t used) { FAR struct note_driver_s **driver; struct note_heap_s note; @@ -1372,7 +1372,7 @@ void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, for (driver = g_note_drivers; *driver; driver++) { - if (note_heap(*driver, event, heap, mem, size)) + if (note_heap(*driver, event, heap, mem, size, used)) { continue; } @@ -1389,6 +1389,7 @@ void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, note.heap = heap; note.mem = mem; note.size = size; + note.used = used; } /* Add the note to circular buffer */ diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index c3897d6012..e9b60333ab 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -98,17 +98,9 @@ struct noteram_dump_cpu_context_s uint8_t next_priority; /* Task Priority of the next line */ }; -struct noteram_dump_task_context_s -{ - FAR struct noteram_dump_task_context_s *next; - pid_t pid; - size_t mm_used; -}; - struct noteram_dump_context_s { struct noteram_dump_cpu_context_s cpu[NCPUS]; - struct noteram_dump_task_context_s *task; }; /**************************************************************************** @@ -429,13 +421,6 @@ int noteram_close(FAR struct file *filep) { FAR struct noteram_dump_context_s *ctx = filep->f_priv; - while (ctx->task != NULL) - { - FAR struct noteram_dump_task_context_s *task = ctx->task; - ctx->task = task->next; - kmm_free(task); - } - kmm_free(ctx); return OK; } @@ -638,60 +623,7 @@ static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx) } /**************************************************************************** - * Name: noteram_dump_find_task_context - ****************************************************************************/ - -#ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP -static FAR struct noteram_dump_task_context_s * -noteram_dump_find_task_context(FAR struct noteram_dump_context_s *ctx, - pid_t pid) -{ - FAR struct noteram_dump_task_context_s *task; - FAR struct noteram_dump_task_context_s *prev; - - if (ctx->task == NULL) - { - ctx->task = kmm_zalloc(sizeof(*ctx->task)); - if (ctx->task == NULL) - { - return NULL; - } - - ctx->task->pid = pid; - ctx->task->next = NULL; - return ctx->task; - } - else - { - task = ctx->task; - } - - while (task != NULL) - { - if (task->pid == pid) - { - return task; - } - - prev = task; - task = task->next; - } - - prev->next = kmm_zalloc(sizeof(*prev)); - if (prev->next == NULL) - { - return NULL; - } - - task = prev->next; - task->pid = pid; - task->next = NULL; - return task; -} -#endif - -/**************************************************************************** - * Name: get_task_name + * Name: get_taskname ****************************************************************************/ static const char *get_taskname(pid_t pid) @@ -1094,26 +1026,16 @@ static int noteram_dump_one(FAR uint8_t *p, FAR struct lib_outstream_s *s, case NOTE_HEAP_FREE: { FAR struct note_heap_s *nmm = (FAR struct note_heap_s *)p; - FAR struct noteram_dump_task_context_s *tctx; - int used = 0; FAR const char *name[] = { "add", "remove", "malloc", "free" }; - tctx = noteram_dump_find_task_context(ctx, pid); - if (tctx != NULL) - { - tctx->mm_used += note->nc_type == NOTE_HEAP_FREE ? -nmm->size - : note->nc_type == NOTE_HEAP_ALLOC ? nmm->size - : 0; - used = tctx->mm_used; - } - ret += noteram_dump_header(s, &nmm->nmm_cmn, ctx); ret += lib_sprintf(s, "tracing_mark_write: C|%d|Heap Usage|%d|%s" ": heap: %p size:%" PRIiPTR ", address: %p\n", - pid, used, name[note->nc_type - NOTE_HEAP_ADD], + pid, nmm->used, + name[note->nc_type - NOTE_HEAP_ADD], nmm->heap, nmm->size, nmm->mem); } break; diff --git a/drivers/segger/note_sysview.c b/drivers/segger/note_sysview.c index 0af3f562dc..95ded2b2eb 100644 --- a/drivers/segger/note_sysview.c +++ b/drivers/segger/note_sysview.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include #include @@ -76,7 +77,7 @@ static void note_sysview_syscall_leave(FAR struct note_driver_s *drv, #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP static void note_sysview_heap(FAR struct note_driver_s *drv, uint8_t event, FAR void *heap, FAR void *mem, - size_t size); + size_t size, size_t curused); #endif /**************************************************************************** @@ -330,19 +331,55 @@ static void note_sysview_syscall_leave(FAR struct note_driver_s *drv, #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP static void note_sysview_heap(FAR struct note_driver_s *drv, uint8_t event, FAR void *heap, FAR void *mem, - size_t size) + size_t size, size_t curused) { switch (event) { case NOTE_HEAP_ALLOC: - SEGGER_SYSVIEW_HeapAlloc(heap, mem, size); - break; case NOTE_HEAP_FREE: - SEGGER_SYSVIEW_HeapFree(heap, mem); - break; + { + U32 value = (U32)curused; + const SEGGER_SYSVIEW_DATA_SAMPLE data = + { + .ID = (U32)(uintptr_t)heap, + .pU32_Value = &value, + }; + + SEGGER_SYSVIEW_SampleData(&data); + if (event == NOTE_HEAP_ALLOC) + { + SEGGER_SYSVIEW_HeapAlloc(heap, mem, size); + } + else + { + SEGGER_SYSVIEW_HeapFree(heap, mem); + } + + break; + } + case NOTE_HEAP_ADD: - SEGGER_SYSVIEW_HeapDefine(heap, mem, size, 0); - break; + { + char name[32]; + SEGGER_SYSVIEW_DATA_REGISTER data = + { + .ID = (U32)(uintptr_t)heap, + .DataType = SEGGER_SYSVIEW_TYPE_U32, + .Offset = 0, + .RangeMin = 0, + .RangeMax = 0, + .ScalingFactor = 1.f, + .sUnit = "B", + .sName = name, + }; + + snprintf(name, sizeof(name), "Heap%p", heap); + + SEGGER_SYSVIEW_RegisterData(&data); + SEGGER_SYSVIEW_HeapDefine(heap, mem, size, 0); + break; + } + default: break; } diff --git a/include/nuttx/note/note_driver.h b/include/nuttx/note/note_driver.h index 5372e14643..cefe5e95b3 100644 --- a/include/nuttx/note/note_driver.h +++ b/include/nuttx/note/note_driver.h @@ -91,7 +91,8 @@ struct note_driver_ops_s #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP CODE void (*heap)(FAR struct note_driver_s *drv, uint8_t event, - FAR void *heap, FAR void *mem, size_t size); + FAR void *heap, FAR void *mem, size_t size, + size_t curused); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP CODE void (*string)(FAR struct note_driver_s *drv, uintptr_t ip, diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 2b9725de47..b49207ccf0 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -390,6 +390,7 @@ struct note_heap_s FAR void *heap; FAR void *mem; size_t size; + size_t used; }; struct note_string_s @@ -556,9 +557,9 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter); #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, - size_t size); + size_t size, size_t used); #else -# define sched_note_heap(e,h,m,s) +# define sched_note_heap(e,h,m,s,c) #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP diff --git a/mm/mm_heap/mm_free.c b/mm/mm_heap/mm_free.c index 5a1dcb7989..6848ad3ab8 100644 --- a/mm/mm_heap/mm_free.c +++ b/mm/mm_heap/mm_free.c @@ -128,7 +128,7 @@ void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem, bool delay) /* Update heap statistics */ heap->mm_curused -= nodesize; - sched_note_heap(NOTE_HEAP_FREE, heap, mem, nodesize); + sched_note_heap(NOTE_HEAP_FREE, heap, mem, nodesize, heap->mm_curused); /* Check if the following node is free and, if so, merge it */ diff --git a/mm/mm_heap/mm_initialize.c b/mm/mm_heap/mm_initialize.c index d35604cd7b..ae31af1219 100644 --- a/mm/mm_heap/mm_initialize.c +++ b/mm/mm_heap/mm_initialize.c @@ -203,7 +203,8 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart, heap->mm_curused += 2 * MM_SIZEOF_ALLOCNODE; mm_unlock(heap); - sched_note_heap(NOTE_HEAP_ADD, heap, heapstart, heapsize); + sched_note_heap(NOTE_HEAP_ADD, heap, heapstart, heapsize, + heap->mm_curused); } /**************************************************************************** @@ -371,7 +372,7 @@ void mm_uninitialize(FAR struct mm_heap_s *heap) kasan_unregister(heap->mm_heapstart[i]); sched_note_heap(NOTE_HEAP_REMOVE, heap, heap->mm_heapstart[i], (uintptr_t)heap->mm_heapend[i] - - (uintptr_t)heap->mm_heapstart[i]); + (uintptr_t)heap->mm_heapstart[i], heap->mm_curused); } #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO) diff --git a/mm/mm_heap/mm_malloc.c b/mm/mm_heap/mm_malloc.c index 4345fc1f4b..3d15c326ac 100644 --- a/mm/mm_heap/mm_malloc.c +++ b/mm/mm_heap/mm_malloc.c @@ -327,7 +327,8 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) { MM_ADD_BACKTRACE(heap, node); ret = kasan_unpoison(ret, nodesize - MM_ALLOCNODE_OVERHEAD); - sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize, + heap->mm_curused); #ifdef CONFIG_MM_FILL_ALLOCATIONS memset(ret, MM_ALLOC_MAGIC, alignsize - MM_ALLOCNODE_OVERHEAD); #endif diff --git a/mm/mm_heap/mm_memalign.c b/mm/mm_heap/mm_memalign.c index d446c600bc..aa0621889f 100644 --- a/mm/mm_heap/mm_memalign.c +++ b/mm/mm_heap/mm_memalign.c @@ -281,7 +281,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, alignedchunk = (uintptr_t)kasan_unpoison((FAR const void *)alignedchunk, size - MM_ALLOCNODE_OVERHEAD); - sched_note_heap(NOTE_HEAP_ALLOC, heap, (FAR void *)alignedchunk, size); + sched_note_heap(NOTE_HEAP_ALLOC, heap, (FAR void *)alignedchunk, size, + heap->mm_curused); DEBUGASSERT(alignedchunk % alignment == 0); return (FAR void *)alignedchunk; diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c index a6e67d8ce2..13fc849541 100644 --- a/mm/mm_heap/mm_realloc.c +++ b/mm/mm_heap/mm_realloc.c @@ -383,8 +383,10 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, heap->mm_maxused = heap->mm_curused; } - sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize); - sched_note_heap(NOTE_HEAP_ALLOC, heap, newmem, newsize); + sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize, + heap->mm_curused - newsize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, newmem, newsize, + heap->mm_curused); mm_unlock(heap); MM_ADD_BACKTRACE(heap, (FAR char *)newmem - MM_SIZEOF_ALLOCNODE); diff --git a/mm/tlsf/mm_tlsf.c b/mm/tlsf/mm_tlsf.c index 811cb47217..ff32de3726 100644 --- a/mm/tlsf/mm_tlsf.c +++ b/mm/tlsf/mm_tlsf.c @@ -511,7 +511,7 @@ static void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem, /* Update heap statistics */ heap->mm_curused -= size; - sched_note_heap(NOTE_HEAP_FREE, heap, mem, size); + sched_note_heap(NOTE_HEAP_FREE, heap, mem, size, heap->mm_curused); tlsf_free(heap->mm_tlsf, mem); } @@ -601,7 +601,8 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart, tlsf_add_pool(heap->mm_tlsf, heapstart, heapsize); mm_unlock(heap); - sched_note_heap(NOTE_HEAP_ADD, heap, heapstart, heapsize); + sched_note_heap(NOTE_HEAP_ADD, heap, heapstart, heapsize, + heap->mm_curused); } /**************************************************************************** @@ -1191,7 +1192,8 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) #endif ret = kasan_unpoison(ret, nodesize); - sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize, + heap->mm_curused); #ifdef CONFIG_MM_FILL_ALLOCATIONS memset(ret, 0xaa, nodesize); @@ -1271,7 +1273,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, memdump_backtrace(heap, buf); #endif ret = kasan_unpoison(ret, nodesize); - sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, ret, nodesize, + heap->mm_curused); } #if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0 @@ -1399,8 +1402,10 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, memdump_backtrace(heap, buf); #endif - sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize); - sched_note_heap(NOTE_HEAP_ALLOC, heap, newmem, newsize); + sched_note_heap(NOTE_HEAP_FREE, heap, oldmem, oldsize, + heap->mm_curused - newsize); + sched_note_heap(NOTE_HEAP_ALLOC, heap, newmem, newsize, + heap->mm_curused); } #if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0 @@ -1443,7 +1448,7 @@ void mm_uninitialize(FAR struct mm_heap_s *heap) kasan_unregister(heap->mm_heapstart[i]); sched_note_heap(NOTE_HEAP_REMOVE, heap, heap->mm_heapstart[i], (uintptr_t)heap->mm_heapend[i] - - (uintptr_t)heap->mm_heapstart[i]); + (uintptr_t)heap->mm_heapstart[i], heap->mm_curused); } #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO) diff --git a/sched/Kconfig b/sched/Kconfig index 63b27f3752..1fca42e460 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1290,7 +1290,7 @@ config SCHED_INSTRUMENTATION_HEAP ---help--- Enables additional hooks for heap allocation. - void sched_note_heap(uint8_t event, FAR void* heap, FAR void *mem, size_t size); + void sched_note_heap(uint8_t event, FAR void* heap, FAR void *mem, size_t size, size_t curused); config SCHED_INSTRUMENTATION_DUMP bool "Use note dump for instrumentation" diff --git a/tools/nxstyle.c b/tools/nxstyle.c index ce9b8fb1c4..ce1a957f09 100644 --- a/tools/nxstyle.c +++ b/tools/nxstyle.c @@ -294,12 +294,19 @@ static const char *g_white_content_list[] = * drivers/segger/note_sysview.c */ - "SEGGER_SYSVIEW", - "TaskID", - "sName", + "DataType", + "Offset", "Prio", + "pU32_Value", + "RangeMax", + "RangeMin", + "SEGGER_SYSVIEW", + "ScalingFactor", + "sName", + "sUnit", "StackBase", "StackSize", + "TaskID", /* Ref: * drivers/segger/syslog_rtt.c