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 <yinshengkai@xiaomi.com>
This commit is contained in:
parent
225062305b
commit
bb5b5420ae
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
@ -257,8 +264,38 @@ void mm_free(struct mm_heap_s *heap, void *mem)
|
||||
void *mm_realloc(struct mm_heap_s *heap, void *oldmem,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 ***********************************************************/
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user