This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new bb5b5420ae mm: record the maximum system memory usage
bb5b5420ae is described below
commit bb5b5420ae40968308b173ebd106000b958adf87
Author: yinshengkai <[email protected]>
AuthorDate: Tue Oct 31 16:37:14 2023 +0800
mm: record the maximum system memory usage
Add the usmblks field to mallinfo to record the maximum space allocated
historically in the system
https://man7.org/linux/man-pages/man3/mallinfo.3.html#:~:text=mmap(2).-,usmblks,-This%20field%20is
Signed-off-by: yinshengkai <[email protected]>
---
arch/sim/src/sim/posix/sim_hostmemory.c | 29 -------------
arch/sim/src/sim/sim_heap.c | 76 ++++++++++++++++++++++++++++++---
arch/sim/src/sim/sim_internal.h | 1 -
arch/sim/src/sim/win/sim_hostmemory.c | 4 --
fs/procfs/fs_procfsmeminfo.c | 26 +++++------
include/malloc.h | 1 +
mm/mm_heap/mm.h | 8 ++++
mm/mm_heap/mm_free.c | 4 ++
mm/mm_heap/mm_mallinfo.c | 1 +
mm/mm_heap/mm_malloc.c | 8 ++++
mm/mm_heap/mm_memalign.c | 8 ++++
mm/mm_heap/mm_realloc.c | 8 ++++
mm/tlsf/mm_tlsf.c | 34 +++++++++++++++
13 files changed, 156 insertions(+), 52 deletions(-)
diff --git a/arch/sim/src/sim/posix/sim_hostmemory.c
b/arch/sim/src/sim/posix/sim_hostmemory.c
index 0c9da4c9d3..4677b70681 100644
--- a/arch/sim/src/sim/posix/sim_hostmemory.c
+++ b/arch/sim/src/sim/posix/sim_hostmemory.c
@@ -27,7 +27,6 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
-#include <stdatomic.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -45,9 +44,6 @@
* Private Data
****************************************************************************/
-static atomic_int g_aordblks;
-static atomic_int g_uordblks;
-
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -175,31 +171,21 @@ void *host_memalign(size_t alignment, size_t size)
return NULL;
}
- size = host_mallocsize(p);
- atomic_fetch_add(&g_aordblks, 1);
- atomic_fetch_add(&g_uordblks, size);
-
return p;
}
void host_free(void *mem)
{
- size_t size;
-
if (mem == NULL)
{
return;
}
- size = host_mallocsize(mem);
- atomic_fetch_sub(&g_aordblks, 1);
- atomic_fetch_sub(&g_uordblks, size);
host_uninterruptible_no_return(free, mem);
}
void *host_realloc(void *oldmem, size_t size)
{
- size_t oldsize;
void *mem;
if (oldmem == NULL)
@@ -207,21 +193,6 @@ void *host_realloc(void *oldmem, size_t size)
return host_memalign(sizeof(void *), size);
}
- oldsize = host_mallocsize(oldmem);
mem = host_uninterruptible(realloc, oldmem, size);
- if (mem == NULL)
- {
- return NULL;
- }
-
- size = host_mallocsize(mem);
- atomic_fetch_add(&g_uordblks, size - oldsize);
-
return mem;
}
-
-void host_mallinfo(int *aordblks, int *uordblks)
-{
- *aordblks = atomic_load(&g_aordblks);
- *uordblks = atomic_load(&g_uordblks);
-}
diff --git a/arch/sim/src/sim/sim_heap.c b/arch/sim/src/sim/sim_heap.c
index e0260a7656..f7b3ea092c 100644
--- a/arch/sim/src/sim/sim_heap.c
+++ b/arch/sim/src/sim/sim_heap.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include <string.h>
+#include <stdatomic.h>
#include <stdbool.h>
#include <nuttx/arch.h>
@@ -50,6 +51,9 @@ struct mm_delaynode_s
struct mm_heap_s
{
struct mm_delaynode_s *mm_delaylist[CONFIG_SMP_NCPUS];
+ atomic_int aordblks;
+ atomic_int uordblks;
+ atomic_int usmblks;
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MEMINFO)
struct procfs_meminfo_entry_s mm_procfs;
@@ -227,6 +231,9 @@ void mm_free(struct mm_heap_s *heap, void *mem)
}
else
{
+ int size = host_mallocsize(mem);
+ atomic_fetch_sub(&heap->aordblks, 1);
+ atomic_fetch_sub(&heap->uordblks, size);
host_free(mem);
}
}
@@ -255,10 +262,40 @@ void mm_free(struct mm_heap_s *heap, void *mem)
****************************************************************************/
void *mm_realloc(struct mm_heap_s *heap, void *oldmem,
- size_t size)
+ size_t size)
{
+ void *mem;
+ int uordblks;
+ int usmblks;
+ int newsize;
+
mm_free_delaylist(heap);
- return host_realloc(oldmem, size);
+
+ if (size == 0)
+ {
+ mm_free(heap, oldmem);
+ return NULL;
+ }
+
+ atomic_fetch_sub(&heap->uordblks, host_mallocsize(oldmem));
+ mem = host_realloc(oldmem, size);
+
+ atomic_fetch_add(&heap->aordblks, oldmem == NULL && mem != NULL);
+ newsize = host_mallocsize(mem ? mem : oldmem);
+ atomic_fetch_add(&heap->uordblks, newsize);
+ usmblks = atomic_load(&heap->usmblks);
+
+ do
+ {
+ uordblks = atomic_load(&heap->uordblks);
+ if (uordblks <= usmblks)
+ {
+ break;
+ }
+ }
+ while (atomic_compare_exchange_weak(&heap->usmblks, &usmblks, uordblks));
+
+ return mem;
}
/****************************************************************************
@@ -315,11 +352,36 @@ void *mm_zalloc(struct mm_heap_s *heap, size_t size)
*
****************************************************************************/
-void *mm_memalign(struct mm_heap_s *heap, size_t alignment,
- size_t size)
+void *mm_memalign(struct mm_heap_s *heap, size_t alignment, size_t size)
{
+ void *mem;
+ int uordblks;
+ int usmblks;
+
mm_free_delaylist(heap);
- return host_memalign(alignment, size);
+ mem = host_memalign(alignment, size);
+
+ if (mem == NULL)
+ {
+ return NULL;
+ }
+
+ size = host_mallocsize(mem);
+ atomic_fetch_add(&heap->aordblks, 1);
+ atomic_fetch_add(&heap->uordblks, size);
+ usmblks = atomic_load(&heap->usmblks);
+
+ do
+ {
+ uordblks = atomic_load(&heap->uordblks);
+ if (uordblks <= usmblks)
+ {
+ break;
+ }
+ }
+ while (atomic_compare_exchange_weak(&heap->usmblks, &usmblks, uordblks));
+
+ return mem;
}
/****************************************************************************
@@ -385,7 +447,9 @@ struct mallinfo mm_mallinfo(struct mm_heap_s *heap)
struct mallinfo info;
memset(&info, 0, sizeof(struct mallinfo));
- host_mallinfo(&info.aordblks, &info.uordblks);
+ info.aordblks = atomic_load(&heap->aordblks);
+ info.uordblks = atomic_load(&heap->uordblks);
+ info.usmblks = atomic_load(&heap->usmblks);
return info;
}
diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h
index 50bb44219b..c5869bfd3c 100644
--- a/arch/sim/src/sim/sim_internal.h
+++ b/arch/sim/src/sim/sim_internal.h
@@ -225,7 +225,6 @@ size_t host_mallocsize(void *mem);
void *host_memalign(size_t alignment, size_t size);
void host_free(void *mem);
void *host_realloc(void *oldmem, size_t size);
-void host_mallinfo(int *aordblks, int *uordblks);
int host_unlinkshmem(const char *name);
/* sim_hosttime.c ***********************************************************/
diff --git a/arch/sim/src/sim/win/sim_hostmemory.c
b/arch/sim/src/sim/win/sim_hostmemory.c
index a94fecb2d7..b900b9792d 100644
--- a/arch/sim/src/sim/win/sim_hostmemory.c
+++ b/arch/sim/src/sim/win/sim_hostmemory.c
@@ -96,7 +96,3 @@ void *host_realloc(void *oldmem, size_t size)
{
return _aligned_realloc(oldmem, size, 8);
}
-
-void host_mallinfo(int *aordblks, int *uordblks)
-{
-}
diff --git a/fs/procfs/fs_procfsmeminfo.c b/fs/procfs/fs_procfsmeminfo.c
index 35313ff490..aac6a8ab08 100644
--- a/fs/procfs/fs_procfsmeminfo.c
+++ b/fs/procfs/fs_procfsmeminfo.c
@@ -291,8 +291,9 @@ static ssize_t meminfo_read(FAR struct file *filep, FAR
char *buffer,
/* The first line is the headers */
linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN,
- "%13s%11s%11s%11s%11s%7s%7s\n", "", "total",
- "used", "free", "largest", "nused", "nfree");
+ "%13s%11s%11s%11s%11s%11s%7s%7s\n", "",
+ "total", "used", "free", "maxused",
+ "maxfree", "nused", "nfree");
copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen,
&offset);
@@ -306,23 +307,24 @@ static ssize_t meminfo_read(FAR struct file *filep, FAR
char *buffer,
{
if (buflen > 0)
{
- struct mallinfo minfo;
+ struct mallinfo info;
buffer += copysize;
buflen -= copysize;
/* Show heap information */
- minfo = mm_mallinfo(entry->heap);
+ info = mm_mallinfo(entry->heap);
linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN,
- "%12s:%11lu%11lu%11lu%11lu%7lu%7lu\n",
- entry->name,
- (unsigned long)minfo.arena,
- (unsigned long)minfo.uordblks,
- (unsigned long)minfo.fordblks,
- (unsigned long)minfo.mxordblk,
- (unsigned long)minfo.aordblks,
- (unsigned long)minfo.ordblks);
+ "%12s:%11lu%11lu%11lu%11lu%11lu"
+ "%7lu%7lu\n", entry->name,
+ (unsigned long)info.arena,
+ (unsigned long)info.uordblks,
+ (unsigned long)info.fordblks,
+ (unsigned long)info.usmblks,
+ (unsigned long)info.mxordblk,
+ (unsigned long)info.aordblks,
+ (unsigned long)info.ordblks);
copysize = procfs_memcpy(procfile->line, linesize, buffer,
buflen, &offset);
totalsize += copysize;
diff --git a/include/malloc.h b/include/malloc.h
index 8ea7f2c966..aac2671b2e 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -68,6 +68,7 @@ struct mallinfo
* chunks handed out by malloc. */
int fordblks; /* This is the total size of memory occupied
* by free (not in use) chunks. */
+ int usmblks; /* This is the largest amount of space ever allocated */
};
struct malltask
diff --git a/mm/mm_heap/mm.h b/mm/mm_heap/mm.h
index 163aa46818..f15a7d29ed 100644
--- a/mm/mm_heap/mm.h
+++ b/mm/mm_heap/mm.h
@@ -230,6 +230,14 @@ struct mm_heap_s
size_t mm_heapsize;
+ /* This is the heap maximum used memory size */
+
+ size_t mm_maxused;
+
+ /* This is the current used size of the heap */
+
+ size_t mm_curused;
+
/* This is the first and last nodes of the heap */
FAR struct mm_allocnode_s *mm_heapstart[CONFIG_MM_REGIONS];
diff --git a/mm/mm_heap/mm_free.c b/mm/mm_heap/mm_free.c
index b41464da9f..d2f10fff77 100644
--- a/mm/mm_heap/mm_free.c
+++ b/mm/mm_heap/mm_free.c
@@ -121,6 +121,10 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
node->size &= ~MM_ALLOC_BIT;
+ /* Update heap statistics */
+
+ heap->mm_curused -= nodesize;
+
/* Check if the following node is free and, if so, merge it */
next = (FAR struct mm_freenode_s *)((FAR char *)node + nodesize);
diff --git a/mm/mm_heap/mm_mallinfo.c b/mm/mm_heap/mm_mallinfo.c
index 84bc51718d..090dc93636 100644
--- a/mm/mm_heap/mm_mallinfo.c
+++ b/mm/mm_heap/mm_mallinfo.c
@@ -145,6 +145,7 @@ struct mallinfo mm_mallinfo(FAR struct mm_heap_s *heap)
info.arena = heap->mm_heapsize;
info.arena += sizeof(struct mm_heap_s);
info.uordblks += sizeof(struct mm_heap_s);
+ info.usmblks = heap->mm_maxused + sizeof(struct mm_heap_s);
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
poolinfo = mempool_multiple_mallinfo(heap->mm_mpool);
diff --git a/mm/mm_heap/mm_malloc.c b/mm/mm_heap/mm_malloc.c
index df2624aba0..03691c4b1e 100644
--- a/mm/mm_heap/mm_malloc.c
+++ b/mm/mm_heap/mm_malloc.c
@@ -251,6 +251,14 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t
size)
next->size &= ~MM_PREVFREE_BIT;
}
+ /* Update heap statistics */
+
+ heap->mm_curused += MM_SIZEOF_NODE(node);
+ if (heap->mm_curused > heap->mm_maxused)
+ {
+ heap->mm_maxused = heap->mm_curused;
+ }
+
/* Handle the case of an exact size match */
node->size |= MM_ALLOC_BIT;
diff --git a/mm/mm_heap/mm_memalign.c b/mm/mm_heap/mm_memalign.c
index 0dc2651cb7..0e137cd91c 100644
--- a/mm/mm_heap/mm_memalign.c
+++ b/mm/mm_heap/mm_memalign.c
@@ -259,6 +259,14 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t
alignment,
mm_shrinkchunk(heap, node, size);
}
+ /* Update heap statistics */
+
+ heap->mm_curused += MM_SIZEOF_NODE(node);
+ if (heap->mm_curused > heap->mm_maxused)
+ {
+ heap->mm_maxused = heap->mm_curused;
+ }
+
mm_unlock(heap);
MM_ADD_BACKTRACE(heap, node);
diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c
index d2b63f1756..12c95da0bc 100644
--- a/mm/mm_heap/mm_realloc.c
+++ b/mm/mm_heap/mm_realloc.c
@@ -365,6 +365,14 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void
*oldmem,
}
}
+ /* Update heap statistics */
+
+ heap->mm_curused += newsize - oldsize;
+ if (heap->mm_curused > heap->mm_maxused)
+ {
+ heap->mm_maxused = 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 0f93c2229f..1bf906a4c1 100644
--- a/mm/tlsf/mm_tlsf.c
+++ b/mm/tlsf/mm_tlsf.c
@@ -78,6 +78,14 @@ struct mm_heap_s
size_t mm_heapsize;
+ /* This is the heap maximum used memory size */
+
+ size_t mm_maxused;
+
+ /* This is the current used size of the heap */
+
+ size_t mm_curused;
+
/* This is the first and last of the heap */
FAR void *mm_heapstart[CONFIG_MM_REGIONS];
@@ -698,6 +706,10 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
kasan_poison(mem, mm_malloc_size(heap, mem));
+ /* Update heap statistics */
+
+ heap->mm_curused -= mm_malloc_size(heap, mem);
+
/* Pass, return to the tlsf pool */
tlsf_free(heap->mm_tlsf, mem);
@@ -891,6 +903,7 @@ struct mallinfo mm_mallinfo(FAR struct mm_heap_s *heap)
info.arena = heap->mm_heapsize;
info.uordblks = info.arena - info.fordblks;
+ info.usmblks = heap->mm_maxused;
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
poolinfo = mempool_multiple_mallinfo(heap->mm_mpool);
@@ -1061,6 +1074,12 @@ 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);
+ if (heap->mm_curused > heap->mm_maxused)
+ {
+ heap->mm_maxused = heap->mm_curused;
+ }
+
mm_unlock(heap);
if (ret)
@@ -1119,6 +1138,13 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t
alignment,
#else
ret = tlsf_memalign(heap->mm_tlsf, alignment, size);
#endif
+
+ heap->mm_curused += mm_malloc_size(heap, ret);
+ if (heap->mm_curused > heap->mm_maxused)
+ {
+ heap->mm_maxused = heap->mm_curused;
+ }
+
mm_unlock(heap);
if (ret)
@@ -1217,12 +1243,20 @@ 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);
#if CONFIG_MM_BACKTRACE >= 0
newmem = tlsf_realloc(heap->mm_tlsf, oldmem, size +
sizeof(struct memdump_backtrace_s));
#else
newmem = tlsf_realloc(heap->mm_tlsf, oldmem, size);
#endif
+
+ heap->mm_curused += mm_malloc_size(heap, newmem ? newmem : oldmem);
+ if (heap->mm_curused > heap->mm_maxused)
+ {
+ heap->mm_maxused = heap->mm_curused;
+ }
+
mm_unlock(heap);
#if CONFIG_MM_BACKTRACE >= 0