mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 19:36:35 +08:00
note: add memory tracing event support
Record all memory allocation and release, save to ram, used to analyze memory allocation rate and memory usage Its absolute value is not trustworthy because the memory will be allocated in thread A and released in thread B netinit-5 [0] 0.105984392: tracing_mark_write: C|5|Heap Usage|96|free: heap: 0x606000000020 size:24, address: 0x603000000370 netinit-5 [0] 0.105996874: tracing_mark_write: C|5|Heap Usage|24|free: heap: 0x606000000020 size:72, address: 0x6070000008e0 nsh_main-4 [0] 3.825169408: tracing_mark_write: C|4|Heap Usage|2177665|free: heap: 0x606000000020 size:424, address: 0x614000000840 nsh_main-4 [0] 3.825228525: tracing_mark_write: C|4|Heap Usage|14977|free: heap: 0x606000000020 size:2162688, address: 0x7f80a639f800 nsh_main-4 [0] 3.825298789: tracing_mark_write: C|4|Heap Usage|15189|malloc: heap: 0x606000000020 size:20, address: 0x6030000003a0 Signed-off-by: yinshengkai <yinshengkai@xiaomi.com> Signed-off-by: Neo Xu <neo.xu1990@gmail.com>
This commit is contained in:
+32
-17
@@ -42,6 +42,7 @@
|
||||
#include <nuttx/mm/mm.h>
|
||||
#include <nuttx/mm/kasan.h>
|
||||
#include <nuttx/mm/mempool.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
|
||||
#include "tlsf/tlsf.h"
|
||||
|
||||
@@ -492,15 +493,16 @@ static void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem,
|
||||
{
|
||||
if (mm_lock(heap) == 0)
|
||||
{
|
||||
size_t size = mm_malloc_size(heap, mem);
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
memset(mem, MM_FREE_MAGIC, mm_malloc_size(heap, mem));
|
||||
memset(mem, MM_FREE_MAGIC, size);
|
||||
#endif
|
||||
|
||||
kasan_poison(mem, mm_malloc_size(heap, mem));
|
||||
kasan_poison(mem, size);
|
||||
|
||||
/* Update heap statistics */
|
||||
|
||||
heap->mm_curused -= mm_malloc_size(heap, mem);
|
||||
heap->mm_curused -= size;
|
||||
|
||||
/* Pass, return to the tlsf pool */
|
||||
|
||||
@@ -510,6 +512,7 @@ static void mm_delayfree(FAR struct mm_heap_s *heap, FAR void *mem,
|
||||
}
|
||||
else
|
||||
{
|
||||
sched_note_heap(false, heap, mem, size);
|
||||
tlsf_free(heap->mm_tlsf, mem);
|
||||
}
|
||||
|
||||
@@ -1134,6 +1137,7 @@ size_t mm_malloc_size(FAR struct mm_heap_s *heap, FAR void *mem)
|
||||
|
||||
FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
{
|
||||
size_t nodesize;
|
||||
FAR void *ret;
|
||||
|
||||
/* In case of zero-length allocations allocate the minimum size object */
|
||||
@@ -1168,7 +1172,8 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
ret = tlsf_malloc(heap->mm_tlsf, size);
|
||||
#endif
|
||||
|
||||
heap->mm_curused += mm_malloc_size(heap, ret);
|
||||
nodesize = mm_malloc_size(heap, ret);
|
||||
heap->mm_curused += nodesize;
|
||||
if (heap->mm_curused > heap->mm_maxused)
|
||||
{
|
||||
heap->mm_maxused = heap->mm_curused;
|
||||
@@ -1179,11 +1184,13 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
if (ret)
|
||||
{
|
||||
#if CONFIG_MM_BACKTRACE >= 0
|
||||
FAR struct memdump_backtrace_s *buf = ret + mm_malloc_size(heap, ret);
|
||||
FAR struct memdump_backtrace_s *buf = ret + nodesize;
|
||||
|
||||
memdump_backtrace(heap, buf);
|
||||
#endif
|
||||
ret = kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
|
||||
ret = kasan_unpoison(ret, nodesize);
|
||||
sched_note_heap(true, heap, ret, nodesize);
|
||||
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
memset(ret, 0xaa, nodesize);
|
||||
@@ -1218,6 +1225,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
size_t size)
|
||||
{
|
||||
size_t nodesize;
|
||||
FAR void *ret;
|
||||
|
||||
#ifdef CONFIG_MM_HEAP_MEMPOOL
|
||||
@@ -1245,7 +1253,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
ret = tlsf_memalign(heap->mm_tlsf, alignment, size);
|
||||
#endif
|
||||
|
||||
heap->mm_curused += mm_malloc_size(heap, ret);
|
||||
nodesize = mm_malloc_size(heap, ret);
|
||||
heap->mm_curused += nodesize;
|
||||
if (heap->mm_curused > heap->mm_maxused)
|
||||
{
|
||||
heap->mm_maxused = heap->mm_curused;
|
||||
@@ -1256,11 +1265,12 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
if (ret)
|
||||
{
|
||||
#if CONFIG_MM_BACKTRACE >= 0
|
||||
FAR struct memdump_backtrace_s *buf = ret + mm_malloc_size(heap, ret);
|
||||
FAR struct memdump_backtrace_s *buf = ret + nodesize;
|
||||
|
||||
memdump_backtrace(heap, buf);
|
||||
#endif
|
||||
ret = kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
ret = kasan_unpoison(ret, nodesize);
|
||||
sched_note_heap(true, heap, ret, nodesize);
|
||||
}
|
||||
|
||||
#if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0
|
||||
@@ -1302,6 +1312,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
size_t size)
|
||||
{
|
||||
FAR void *newmem;
|
||||
size_t oldsize;
|
||||
size_t newsize;
|
||||
|
||||
/* If oldmem is NULL, then realloc is equivalent to malloc */
|
||||
|
||||
@@ -1361,7 +1373,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
/* Allocate from the tlsf pool */
|
||||
|
||||
DEBUGVERIFY(mm_lock(heap));
|
||||
heap->mm_curused -= mm_malloc_size(heap, oldmem);
|
||||
oldsize = mm_malloc_size(heap, oldmem);
|
||||
heap->mm_curused -= oldsize;
|
||||
#if CONFIG_MM_BACKTRACE >= 0
|
||||
newmem = tlsf_realloc(heap->mm_tlsf, oldmem, size +
|
||||
sizeof(struct memdump_backtrace_s));
|
||||
@@ -1369,7 +1382,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
newmem = tlsf_realloc(heap->mm_tlsf, oldmem, size);
|
||||
#endif
|
||||
|
||||
heap->mm_curused += mm_malloc_size(heap, newmem ? newmem : oldmem);
|
||||
newsize = mm_malloc_size(heap, newmem);
|
||||
heap->mm_curused += newmem ? newsize : oldsize;
|
||||
if (heap->mm_curused > heap->mm_maxused)
|
||||
{
|
||||
heap->mm_maxused = heap->mm_curused;
|
||||
@@ -1377,20 +1391,21 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
|
||||
mm_unlock(heap);
|
||||
|
||||
#if CONFIG_MM_BACKTRACE >= 0
|
||||
if (newmem)
|
||||
{
|
||||
FAR struct memdump_backtrace_s *buf =
|
||||
newmem + mm_malloc_size(heap, newmem);
|
||||
|
||||
#if CONFIG_MM_BACKTRACE >= 0
|
||||
FAR struct memdump_backtrace_s *buf = newmem + newsize;
|
||||
memdump_backtrace(heap, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
sched_note_heap(false, heap, oldmem, oldsize);
|
||||
sched_note_heap(true, heap, newmem, newsize);
|
||||
}
|
||||
|
||||
#if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0
|
||||
/* Try again after free delay list */
|
||||
|
||||
if (newmem == NULL && free_delaylist(heap, true))
|
||||
else if (free_delaylist(heap, true))
|
||||
{
|
||||
return mm_realloc(heap, oldmem, size);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user