Support memdump to realize incremental dump function

Add a new field to record the global on the basis of mm_backtrace.
When using alloc, the field is incremented by 1,
so that the memory usage can be dumped within the range
Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2023-05-05 16:52:30 +08:00 committed by Xiang Xiao
parent 97e652aed1
commit c60dd72a2a
17 changed files with 296 additions and 152 deletions

View File

@ -396,11 +396,15 @@ int mm_mallinfo(struct mm_heap_s *heap, struct mallinfo *info)
*
****************************************************************************/
int mm_mallinfo_task(struct mm_heap_s *heap, struct mallinfo_task *info)
struct mallinfo_task mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump)
{
info->aordblks = 0;
info->uordblks = 0;
return 0;
struct mallinfo_task info =
{
0, 0
};
return info;
}
/****************************************************************************
@ -411,7 +415,7 @@ int mm_mallinfo_task(struct mm_heap_s *heap, struct mallinfo_task *info)
*
****************************************************************************/
void mm_memdump(struct mm_heap_s *heap, pid_t pid)
void mm_memdump(struct mm_heap_s *heap, const struct mm_memdump_s *dump)
{
}

View File

@ -419,7 +419,8 @@ static ssize_t memdump_read(FAR struct file *filep, FAR char *buffer,
#if CONFIG_MM_BACKTRACE >= 0
linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN,
"usage: <pid/used/free/on/off>\n"
"usage: <pid/used/free/on/off>"
"<seqmin> <seqmax> \n"
"on/off backtrace\n"
"pid: dump pid allocated node\n");
#else
@ -436,8 +437,20 @@ static ssize_t memdump_read(FAR struct file *filep, FAR char *buffer,
"used: dump all allocated node\n"
"free: dump all free node\n");
copysize = procfs_memcpy(procfile->line, linesize, buffer, buflen,
&offset);
totalsize += copysize;
#if CONFIG_MM_BACKTRACE >= 0
buffer += copysize;
buflen -= copysize;
linesize = procfs_snprintf(procfile->line, MEMINFO_LINELEN,
"The current sequence number %lu\n", g_mm_seqno);
totalsize += procfs_memcpy(procfile->line, linesize, buffer, buflen,
&offset);
#endif
filep->f_pos += totalsize;
return totalsize;
}
@ -453,10 +466,20 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
{
FAR struct procfs_meminfo_entry_s *entry;
FAR struct meminfo_file_s *procfile;
pid_t pid = INVALID_PROCESS_ID;
struct mm_memdump_s dump =
{
MM_BACKTRACE_ALLOC_PID,
#if CONFIG_MM_BACKTRACE >= 0
0,
ULONG_MAX
#endif
};
#if CONFIG_MM_BACKTRACE >= 0
FAR char *p;
#endif
#if CONFIG_MM_BACKTRACE > 0
FAR struct tcb_s *tcb;
FAR char *p;
#endif
DEBUGASSERT(filep != NULL && buffer != NULL && buflen > 0);
@ -488,8 +511,8 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
else if ((p = strstr(buffer, "on")) != NULL)
{
*p = '\0';
pid = atoi(buffer);
tcb = nxsched_get_tcb(pid);
dump.pid = atoi(buffer);
tcb = nxsched_get_tcb(dump.pid);
if (tcb == NULL)
{
return -EINVAL;
@ -501,8 +524,8 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
else if ((p = strstr(buffer, "off")) != NULL)
{
*p = '\0';
pid = atoi(buffer);
tcb = nxsched_get_tcb(pid);
dump.pid = atoi(buffer);
tcb = nxsched_get_tcb(dump.pid);
if (tcb == NULL)
{
return -EINVAL;
@ -516,11 +539,21 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
switch (buffer[0])
{
case 'u':
pid = MM_BACKTRACE_ALLOC_PID;
dump.pid = MM_BACKTRACE_ALLOC_PID;
#if CONFIG_MM_BACKTRACE >= 0
p = (FAR char *)buffer + 4;
goto dump;
#endif
break;
case 'f':
pid = MM_BACKTRACE_FREE_PID;
dump.pid = MM_BACKTRACE_FREE_PID;
#if CONFIG_MM_BACKTRACE >= 0
p = (FAR char *)buffer + 4;
goto dump;
#endif
break;
#if CONFIG_MM_BACKTRACE >= 0
default:
@ -529,13 +562,26 @@ static ssize_t memdump_write(FAR struct file *filep, FAR const char *buffer,
return buflen;
}
pid = atoi(buffer);
dump.pid = strtol(buffer, &p, 0);
if (!isdigit(*(p + 1)))
{
break;
}
dump:
dump.seqmin = strtoul(p + 1, &p, 0);
if (!isdigit(*(p + 1)))
{
break;
}
dump.seqmax = strtoul(p + 1, &p, 0);
#endif
}
for (entry = g_procfs_meminfo; entry != NULL; entry = entry->next)
{
mm_memdump(entry->heap, pid);
mm_memdump(entry->heap, &dump);
}
return buflen;

View File

@ -886,16 +886,20 @@ static ssize_t proc_heap(FAR struct proc_file_s *procfile,
size_t copysize;
size_t totalsize = 0;
struct mallinfo_task info;
struct mm_memdump_s dump;
dump.pid = tcb->pid;
dump.seqmin = 0;
dump.seqmax = ULONG_MAX;
#ifdef CONFIG_MM_KERNEL_HEAP
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)
{
info = kmm_mallinfo_task(tcb->pid);
info = kmm_mallinfo_task(&dump);
}
else
#endif
{
info = mallinfo_task(tcb->pid);
info = mallinfo_task(&dump);
}
/* Show the heap alloc size */

View File

@ -52,13 +52,29 @@ struct mallinfo
* by free (not in use) chunks. */
};
struct mm_memdump_s
{
pid_t pid; /* Process id */
#if CONFIG_MM_BACKTRACE >= 0
unsigned long seqmin; /* The minimum sequence */
unsigned long seqmax; /* The maximum sequence */
#endif
};
struct mallinfo_task
{
pid_t pid; /* The pid of task */
int aordblks; /* This is the number of allocated (in use) chunks for task */
int uordblks; /* This is the total size of memory occupied for task */
};
/****************************************************************************
* Public data
****************************************************************************/
#if CONFIG_MM_BACKTRACE >= 0
extern unsigned long g_mm_seqno;
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@ -70,7 +86,7 @@ extern "C"
struct mallinfo mallinfo(void);
size_t malloc_size(FAR void *ptr);
struct mallinfo_task mallinfo_task(pid_t pid);
struct mallinfo_task mallinfo_task(FAR const struct mm_memdump_s *dump);
#if defined(__cplusplus)
}

View File

@ -118,6 +118,7 @@ struct mempool_backtrace_s
{
struct list_node node;
pid_t pid;
unsigned long seqno; /* The sequence of memory malloc */
# if CONFIG_MM_BACKTRACE > 0
FAR void *backtrace[CONFIG_MM_BACKTRACE];
# endif
@ -229,13 +230,14 @@ int mempool_info(FAR struct mempool_s *pool, FAR struct mempoolinfo_s *info);
*
* Input Parameters:
* pool - Address of the memory pool to be used.
* info - The pointer of mempoolinfo.
* dump - The information of what need dump.
*
* Returned Value:
* OK on success; A negated errno value on any failure.
****************************************************************************/
void mempool_memdump(FAR struct mempool_s *pool, pid_t pid);
void mempool_memdump(FAR struct mempool_s *pool,
FAR const struct mm_memdump_s *dump);
/****************************************************************************
* Name: mempool_deinit
@ -257,11 +259,15 @@ int mempool_deinit(FAR struct mempool_s *pool);
*
* Input Parameters:
* pool - Address of the memory pool to be used.
* info - Memory info.
* dump - The information of what need dump.
*
* Returned Value:
* Statistics of memory information based on dump.
****************************************************************************/
int mempool_info_task(FAR struct mempool_s *pool,
FAR struct mempoolinfo_task *info);
struct mempoolinfo_task
mempool_info_task(FAR struct mempool_s *pool,
FAR const struct mm_memdump_s *dump);
/****************************************************************************
* Name: mempool_procfs_register
@ -454,12 +460,12 @@ FAR void *mempool_multiple_memalign(FAR struct mempool_multiple_s *mpool,
*
* Input Parameters:
* mpool - The handle of multiple memory pool to be used.
* pid - The pid of task.
* dump - The information of what need dump.
*
****************************************************************************/
void mempool_multiple_memdump(FAR struct mempool_multiple_s *mpool,
pid_t pid);
FAR const struct mm_memdump_s *dump);
/****************************************************************************
* Name: mempool_multiple_deinit
@ -489,11 +495,15 @@ void mempool_multiple_info(FAR struct mempool_multiple_s *mpool);
*
* Input Parameters:
* mpool - The handle of multiple memory pool to be used.
* info - Memory info.
* dump - The information of what need dump.
*
* Returned Value:
* Statistics of memory information based on dump.
****************************************************************************/
void mempool_multiple_info_task(FAR struct mempool_multiple_s *mpool,
FAR struct mempoolinfo_task *info);
struct mempoolinfo_task
mempool_multiple_info_task(FAR struct mempool_multiple_s *mpool,
FAR const struct mm_memdump_s *dump);
#undef EXTERN
#if defined(__cplusplus)

View File

@ -107,6 +107,7 @@
****************************************************************************/
struct mm_heap_s; /* Forward reference */
struct mm_memdump_s;
/****************************************************************************
* Public Data
@ -253,7 +254,7 @@ FAR void *kmm_zalloc(size_t size) malloc_like1(1);
/* Functions contained in kmm_memdump.c *************************************/
#ifdef CONFIG_MM_KERNEL_HEAP
void kmm_memdump(pid_t pid);
void kmm_memdump(FAR const struct mm_memdump_s *dump);
#endif
/* Functions contained in mm_memalign.c *************************************/
@ -315,21 +316,22 @@ void kmm_extend(FAR void *mem, size_t size, int region);
struct mallinfo; /* Forward reference */
int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info);
struct mallinfo_task; /* Forward reference */
int mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR struct mallinfo_task *info);
struct mallinfo_task mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump);
/* Functions contained in kmm_mallinfo.c ************************************/
#ifdef CONFIG_MM_KERNEL_HEAP
struct mallinfo kmm_mallinfo(void);
# if CONFIG_MM_BACKTRACE >= 0
struct mallinfo_task kmm_mallinfo_task(pid_t pid);
struct mallinfo_task kmm_mallinfo_task(FAR const struct mm_memdump_s *dump);
# endif
#endif
/* Functions contained in mm_memdump.c **************************************/
void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid);
void mm_memdump(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump);
#ifdef CONFIG_DEBUG_MM
/* Functions contained in mm_checkcorruption.c ******************************/
@ -342,7 +344,7 @@ FAR void umm_checkcorruption(void);
/* Functions contained in umm_memdump.c *************************************/
void umm_memdump(pid_t pid);
void umm_memdump(FAR const struct mm_memdump_s *dump);
/* Functions contained in kmm_checkcorruption.c *****************************/

View File

@ -59,12 +59,8 @@ struct mallinfo kmm_mallinfo(void)
*
****************************************************************************/
struct mallinfo_task kmm_mallinfo_task(pid_t pid)
struct mallinfo_task kmm_mallinfo_task(FAR const struct mm_memdump_s *dump)
{
struct mallinfo_task info;
info.pid = pid;
mm_mallinfo_task(g_kmmheap, &info);
return info;
return mm_mallinfo_task(g_kmmheap, dump);
}
#endif /* CONFIG_MM_KERNEL_HEAP */

View File

@ -39,9 +39,9 @@
*
****************************************************************************/
void kmm_memdump(pid_t pid)
void kmm_memdump(FAR const struct mm_memdump_s *dump)
{
mm_memdump(g_kmmheap, pid);
mm_memdump(g_kmmheap, dump);
}
#endif /* CONFIG_MM_KERNEL_HEAP */

View File

@ -89,6 +89,7 @@ static inline void mempool_add_backtrace(FAR struct mempool_s *pool,
{
list_add_head(&pool->alist, &buf->node);
buf->pid = _SCHED_GETTID();
buf->seqno = g_mm_seqno++;
# if CONFIG_MM_BACKTRACE > 0
if (pool->procfs.backtrace)
{
@ -396,21 +397,25 @@ int mempool_info(FAR struct mempool_s *pool, FAR struct mempoolinfo_s *info)
* Name: mempool_info_task
****************************************************************************/
int mempool_info_task(FAR struct mempool_s *pool,
FAR struct mempoolinfo_task *info)
struct mempoolinfo_task
mempool_info_task(FAR struct mempool_s *pool,
FAR const struct mm_memdump_s *dump)
{
irqstate_t flags = spin_lock_irqsave(&pool->lock);
struct mempoolinfo_task info =
{
0, 0
};
DEBUGASSERT(info);
if (info->pid == MM_BACKTRACE_FREE_PID)
if (dump->pid == MM_BACKTRACE_FREE_PID)
{
size_t count = mempool_queue_lenth(&pool->queue) +
mempool_queue_lenth(&pool->iqueue);
info->aordblks += count;
info->uordblks += count * pool->blocksize;
info.aordblks += count;
info.uordblks += count * pool->blocksize;
}
else if (info->pid == MM_BACKTRACE_ALLOC_PID)
else if (dump->pid == MM_BACKTRACE_ALLOC_PID)
{
#if CONFIG_MM_BACKTRACE >= 0
size_t count = list_length(&pool->alist);
@ -418,10 +423,10 @@ int mempool_info_task(FAR struct mempool_s *pool,
size_t count = pool->nalloc;
#endif
info->aordblks += count;
info->uordblks += count * pool->blocksize;
info->aordblks -= pool->nexpend;
info->uordblks -= pool->totalsize;
info.aordblks += count;
info.uordblks += count * pool->blocksize;
info.aordblks -= pool->nexpend;
info.uordblks -= pool->totalsize;
}
#if CONFIG_MM_BACKTRACE >= 0
else
@ -431,17 +436,19 @@ int mempool_info_task(FAR struct mempool_s *pool,
list_for_every_entry(&pool->alist, buf, struct mempool_backtrace_s,
node)
{
if (buf->pid == info->pid)
if (buf->pid == dump->pid &&
buf->seqno >= dump->seqmin &&
buf->seqno <= dump->seqmax)
{
info->aordblks++;
info->uordblks += pool->blocksize;
info.aordblks++;
info.uordblks += pool->blocksize;
}
}
}
#endif
spin_unlock_irqrestore(&pool->lock, flags);
return OK;
return info;
}
/****************************************************************************
@ -457,15 +464,16 @@ int mempool_info_task(FAR struct mempool_s *pool,
*
* Input Parameters:
* pool - Address of the memory pool to be used.
* pid - The task of pid.
* dump - The information of what need dump.
*
* Returned Value:
* OK on success; A negated errno value on any failure.
****************************************************************************/
void mempool_memdump(FAR struct mempool_s *pool, pid_t pid)
void mempool_memdump(FAR struct mempool_s *pool,
FAR const struct mm_memdump_s *dump)
{
if (pid == MM_BACKTRACE_FREE_PID)
if (dump->pid == MM_BACKTRACE_FREE_PID)
{
FAR sq_entry_t *entry;
@ -491,7 +499,9 @@ void mempool_memdump(FAR struct mempool_s *pool, pid_t pid)
list_for_every_entry(&pool->alist, buf, struct mempool_backtrace_s,
node)
{
if (buf->pid == pid || pid == MM_BACKTRACE_ALLOC_PID)
if ((buf->pid == dump->pid ||
dump->pid == MM_BACKTRACE_ALLOC_PID) &&
buf->seqno >= dump->seqmin && buf->seqno <= dump->seqmax)
{
# if CONFIG_MM_BACKTRACE > 0
int i;
@ -509,8 +519,9 @@ void mempool_memdump(FAR struct mempool_s *pool, pid_t pid)
}
# endif
syslog(LOG_INFO, "%6d%12zu%*p%s\n",
(int)buf->pid, pool->blocksize, MM_PTR_FMT_WIDTH,
syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n",
(int)buf->pid, pool->blocksize, buf->seqno,
MM_PTR_FMT_WIDTH,
((FAR char *)buf - pool->blocksize), bt);
}
}

View File

@ -618,15 +618,25 @@ void mempool_multiple_info(FAR struct mempool_multiple_s *mpool)
* Name: mempool_multiple_info_task
****************************************************************************/
void mempool_multiple_info_task(FAR struct mempool_multiple_s *mpool,
FAR struct mempoolinfo_task *info)
struct mempoolinfo_task
mempool_multiple_info_task(FAR struct mempool_multiple_s *mpool,
FAR const struct mm_memdump_s *dump)
{
size_t i;
int i;
struct mempoolinfo_task info;
struct mempoolinfo_task ret =
{
0, 0
};
for (i = 0; i < mpool->npools; i++)
{
mempool_info_task(mpool->pools + i, info);
info = mempool_info_task(mpool->pools + i, dump);
ret.aordblks += info.aordblks;
ret.uordblks += info.uordblks;
}
return ret;
}
/****************************************************************************
@ -642,18 +652,18 @@ void mempool_multiple_info_task(FAR struct mempool_multiple_s *mpool,
*
* Input Parameters:
* mpool - The handle of multiple memory pool to be used.
* pid - The pid of task.
* dump - The information of what need dump.
*
****************************************************************************/
void mempool_multiple_memdump(FAR struct mempool_multiple_s *mpool,
pid_t pid)
FAR const struct mm_memdump_s *dump)
{
size_t i;
for (i = 0; i < mpool->npools; i++)
{
mempool_memdump(mpool->pools + i, pid);
mempool_memdump(mpool->pools + i, dump);
}
}

View File

@ -76,6 +76,7 @@
{ \
FAR struct mm_allocnode_s *tmp = (FAR struct mm_allocnode_s *)(ptr); \
tmp->pid = _SCHED_GETTID(); \
tmp->seqno = g_mm_seqno++; \
} \
while (0)
#elif CONFIG_MM_BACKTRACE > 0
@ -98,6 +99,7 @@
{ \
tmp->backtrace[0] = NULL; \
} \
tmp->seqno = g_mm_seqno++; \
} \
while (0)
#else
@ -170,6 +172,7 @@ struct mm_allocnode_s
mmsize_t size; /* Size of this chunk */
#if CONFIG_MM_BACKTRACE >= 0
pid_t pid; /* The pid for caller */
unsigned long seqno; /* The sequence of memory malloc */
# if CONFIG_MM_BACKTRACE > 0
FAR void *backtrace[CONFIG_MM_BACKTRACE]; /* The backtrace buffer for caller */
# endif
@ -184,6 +187,7 @@ struct mm_freenode_s
mmsize_t size; /* Size of this chunk */
#if CONFIG_MM_BACKTRACE >= 0
pid_t pid; /* The pid for caller */
unsigned long seqno; /* The sequence of memory malloc */
# if CONFIG_MM_BACKTRACE > 0
FAR void *backtrace[CONFIG_MM_BACKTRACE]; /* The backtrace buffer for caller */
# endif

View File

@ -32,6 +32,16 @@
#include "mm_heap/mm.h"
/****************************************************************************
* Private Types
****************************************************************************/
struct mm_mallinfo_handler_s
{
FAR const struct mm_memdump_s *dump;
FAR struct mallinfo_task *info;
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -78,7 +88,7 @@ static void mallinfo_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
static void mallinfo_task_handler(FAR struct mm_allocnode_s *node,
FAR void *arg)
{
FAR struct mallinfo_task *info = arg;
FAR struct mm_mallinfo_handler_s *handle = arg;
size_t nodesize = SIZEOF_MM_NODE(node);
/* Check if the node corresponds to an allocated memory chunk */
@ -87,19 +97,22 @@ static void mallinfo_task_handler(FAR struct mm_allocnode_s *node,
{
DEBUGASSERT(nodesize >= SIZEOF_MM_ALLOCNODE);
#if CONFIG_MM_BACKTRACE < 0
if (info->pid == MM_BACKTRACE_ALLOC_PID)
if (handle->dump->pid == MM_BACKTRACE_ALLOC_PID)
#else
if (info->pid == MM_BACKTRACE_ALLOC_PID || node->pid == info->pid)
if ((handle->dump->pid == MM_BACKTRACE_ALLOC_PID ||
handle->dump->pid == node->pid) &&
node->seqno >= handle->dump->seqmin &&
node->seqno <= handle->dump->seqmax)
#endif
{
info->aordblks++;
info->uordblks += nodesize;
handle->info->aordblks++;
handle->info->uordblks += nodesize;
}
}
else if (info->pid == MM_BACKTRACE_FREE_PID)
else if (handle->dump->pid == MM_BACKTRACE_FREE_PID)
{
info->aordblks++;
info->uordblks += nodesize;
handle->info->aordblks++;
handle->info->uordblks += nodesize;
}
}
@ -153,18 +166,23 @@ int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info)
*
****************************************************************************/
int mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR struct mallinfo_task *info)
struct mallinfo_task mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump)
{
DEBUGASSERT(info);
info->uordblks = 0;
info->aordblks = 0;
struct mm_mallinfo_handler_s handle;
struct mallinfo_task info =
{
0, 0
};
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
mempool_multiple_info_task(heap->mm_mpool, info);
info = mempool_multiple_info_task(heap->mm_mpool, dump);
#endif
mm_foreach(heap, mallinfo_task_handler, info);
return OK;
handle.dump = dump;
handle.info = &info;
mm_foreach(heap, mallinfo_task_handler, &handle);
return info;
}

View File

@ -79,9 +79,12 @@ static void free_delaylist(FAR struct mm_heap_s *heap)
void mm_dump_handler(FAR struct tcb_s *tcb, FAR void *arg)
{
struct mallinfo_task info;
struct mm_memdump_s dump;
info.pid = tcb->pid;
mm_mallinfo_task(arg, &info);
dump.pid = tcb->pid;
dump.seqmin = 0;
dump.seqmax = ULONG_MAX;
info = mm_mallinfo_task(arg, &dump);
mwarn("pid:%5d, used:%10d, nused:%10d\n",
tcb->pid, info.uordblks, info.aordblks);
}

View File

@ -53,16 +53,17 @@
static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
{
pid_t pid = *(FAR pid_t *)arg;
FAR const struct mm_memdump_s *dump = arg;
size_t nodesize = SIZEOF_MM_NODE(node);
if ((node->size & MM_ALLOC_BIT) != 0)
{
DEBUGASSERT(nodesize >= SIZEOF_MM_ALLOCNODE);
#if CONFIG_MM_BACKTRACE < 0
if (pid == MM_BACKTRACE_ALLOC_PID)
if (dump->pid == MM_BACKTRACE_ALLOC_PID)
#else
if (pid == MM_BACKTRACE_ALLOC_PID || node->pid == pid)
if ((dump->pid == MM_BACKTRACE_ALLOC_PID || node->pid == dump->pid) &&
node->seqno >= dump->seqmin && node->seqno <= dump->seqmax)
#endif
{
#if CONFIG_MM_BACKTRACE < 0
@ -86,8 +87,9 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
}
# endif
syslog(LOG_INFO, "%6d%12zu%*p%s\n",
(int)node->pid, nodesize, MM_PTR_FMT_WIDTH,
syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n",
(int)node->pid, nodesize, node->seqno,
MM_PTR_FMT_WIDTH,
((FAR char *)node + SIZEOF_MM_ALLOCNODE), buf);
#endif
}
@ -105,7 +107,7 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
SIZEOF_MM_NODE(fnode->flink) == 0 ||
SIZEOF_MM_NODE(fnode->flink) >= nodesize);
if (pid <= MM_BACKTRACE_FREE_PID)
if (dump->pid <= MM_BACKTRACE_FREE_PID)
{
syslog(LOG_INFO, "%12zu%*p\n",
nodesize, MM_PTR_FMT_WIDTH,
@ -129,18 +131,19 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
* than or equal to 0, will dump pid allocated node and output backtrace.
****************************************************************************/
void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
void mm_memdump(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump)
{
struct mallinfo_task info;
if (pid >= -1)
if (dump->pid >= -1)
{
syslog(LOG_INFO, "Dump all used memory node info:\n");
#if CONFIG_MM_BACKTRACE < 0
syslog(LOG_INFO, "%12s%*s\n", "Size", MM_PTR_FMT_WIDTH, "Address");
#else
syslog(LOG_INFO, "%6s%12s%*s %s\n", "PID", "Size", MM_PTR_FMT_WIDTH,
"Address", "Backtrace");
syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence",
MM_PTR_FMT_WIDTH, "Address", "Backtrace");
#endif
}
else
@ -150,12 +153,12 @@ void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
}
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
mempool_multiple_memdump(heap->mm_mpool, pid);
mempool_multiple_memdump(heap->mm_mpool, dump);
#endif
mm_foreach(heap, memdump_handler, &pid);
mm_foreach(heap, memdump_handler, (FAR void *)dump);
info = mm_mallinfo_task(heap, dump);
info.pid = pid;
mm_mallinfo_task(heap, &info);
syslog(LOG_INFO, "%12s%12s\n", "Total Blks", "Total Size");
syslog(LOG_INFO, "%12d%12d\n", info.aordblks, info.uordblks);
}

View File

@ -110,23 +110,23 @@ struct mm_heap_s
#endif
};
struct memdump_info_s
{
pid_t pid;
int blks;
int size;
};
#if CONFIG_MM_BACKTRACE >= 0
struct memdump_backtrace_s
{
pid_t pid; /* The pid for caller */
unsigned long seqno; /* The sequence of memory malloc */
#if CONFIG_MM_BACKTRACE > 0
FAR void *backtrace[CONFIG_MM_BACKTRACE]; /* The backtrace buffer for caller */
#endif
};
#endif
struct mm_mallinfo_handler_s
{
FAR const struct mm_memdump_s *dump;
FAR struct mallinfo_task *info;
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -145,6 +145,7 @@ static void memdump_backtrace(FAR struct mm_heap_s *heap,
# endif
dump->pid = _SCHED_GETTID();
dump->seqno = g_mm_seqno++;
# if CONFIG_MM_BACKTRACE > 0
tcb = nxsched_get_tcb(dump->pid);
if (heap->mm_procfs.backtrace ||
@ -282,27 +283,32 @@ static void mallinfo_task_handler(FAR void *ptr, size_t size, int used,
{
#if CONFIG_MM_BACKTRACE >= 0
FAR struct memdump_backtrace_s *dump;
FAR struct mallinfo_task *info = user;
#endif
FAR struct mm_mallinfo_handler_s *handler = user;
#if CONFIG_MM_BACKTRACE >= 0
size -= sizeof(struct memdump_backtrace_s);
dump = ptr + size;
if (used)
{
#if CONFIG_MM_BACKTRACE < 0
if (info->pid = MM_BACKTRACE_ALLOC_PID)
if (handler->dump->pid = MM_BACKTRACE_ALLOC_PID)
#else
if (info->pid == MM_BACKTRACE_ALLOC_PID || info->pid == dump->pid)
if ((handler->dump->pid == MM_BACKTRACE_ALLOC_PID ||
handler->dump->pid == dump->pid) &&
dump->seqno >= handler->dump->seqmin &&
dump->seqno <= handler->dump->seqmax)
#endif
{
info->aordblks++;
info->uordblks += size;
handler->info->aordblks++;
handler->info->uordblks += size;
}
}
else if (info->pid == MM_BACKTRACE_FREE_PID)
else if (handler->dump->pid == MM_BACKTRACE_FREE_PID)
{
info->aordblks++;
info->uordblks += size;
handler->info->aordblks++;
handler->info->uordblks += size;
}
#endif
}
@ -393,12 +399,12 @@ static void mm_unlock(FAR struct mm_heap_s *heap)
static void memdump_handler(FAR void *ptr, size_t size, int used,
FAR void *user)
{
pid_t pid = *(FAR pid_t *)user;
FAR const struct mm_memdump_s *dump = user;
#if CONFIG_MM_BACKTRACE >= 0
FAR struct memdump_backtrace_s *dump;
FAR struct memdump_backtrace_s *bt;
size -= sizeof(struct memdump_backtrace_s);
dump = ptr + size;
bt = ptr + size;
#endif
if (used)
@ -406,7 +412,10 @@ static void memdump_handler(FAR void *ptr, size_t size, int used,
#if CONFIG_MM_BACKTRACE < 0
if (pid == MM_BACKTRACE_ALLOC_PID)
#else
if (pid == MM_BACKTRACE_ALLOC_PID || dump->pid == pid)
if ((dump->pid == MM_BACKTRACE_ALLOC_PID ||
bt->pid == dump->pid) &&
bt->seqno >= dump->seqmin &&
bt->seqno <= dump->seqmax)
#endif
{
#if CONFIG_MM_BACKTRACE < 0
@ -428,13 +437,13 @@ static void memdump_handler(FAR void *ptr, size_t size, int used,
}
# endif
syslog(LOG_INFO, "%6d%12zu%*p%s\n",
(int)dump->pid, size, MM_PTR_FMT_WIDTH,
syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n",
(int)bt->pid, size, bt->seqno, MM_PTR_FMT_WIDTH,
ptr, buf);
#endif
}
}
else if (pid <= MM_BACKTRACE_FREE_PID)
else if (dump->pid <= MM_BACKTRACE_FREE_PID)
{
syslog(LOG_INFO, "%12zu%*p\n", size, MM_PTR_FMT_WIDTH, ptr);
}
@ -877,23 +886,27 @@ int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info)
return OK;
}
int mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR struct mallinfo_task *info)
struct mallinfo_task mm_mallinfo_task(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump)
{
struct mm_mallinfo_handler_s handle;
struct mallinfo_task info =
{
0, 0
};
#if CONFIG_MM_REGIONS > 1
int region;
#else
#define region 0
#endif
DEBUGASSERT(info);
info->uordblks = 0;
info->aordblks = 0;
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
mempool_multiple_info_task(heap->mm_mpool, info);
info = mempool_multiple_info_task(heap->mm_mpool, dump);
#endif
handle.dump = dump;
handle.info = &info;
#if CONFIG_MM_REGIONS > 1
for (region = 0; region < heap->mm_nregions; region++)
#endif
@ -902,12 +915,12 @@ int mm_mallinfo_task(FAR struct mm_heap_s *heap,
DEBUGVERIFY(mm_lock(heap));
tlsf_walk_pool(heap->mm_heapstart[region],
mallinfo_task_handler, info);
mallinfo_task_handler, &handle);
mm_unlock(heap);
}
#undef region
return OK;
return info;
}
/****************************************************************************
@ -921,7 +934,8 @@ int mm_mallinfo_task(FAR struct mm_heap_s *heap,
* than or equal to 0, will dump pid allocated node and output backtrace.
****************************************************************************/
void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
void mm_memdump(FAR struct mm_heap_s *heap,
FAR const struct mm_memdump_s *dump)
{
#if CONFIG_MM_REGIONS > 1
int region;
@ -930,14 +944,14 @@ void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
#endif
struct mallinfo_task info;
if (pid >= MM_BACKTRACE_ALLOC_PID)
if (dump->pid >= MM_BACKTRACE_ALLOC_PID)
{
syslog(LOG_INFO, "Dump all used memory node info:\n");
#if CONFIG_MM_BACKTRACE < 0
syslog(LOG_INFO, "%12s%*s\n", "Size", MM_PTR_FMT_WIDTH, "Address");
#else
syslog(LOG_INFO, "%6s%12s%*s %s\n", "PID", "Size", MM_PTR_FMT_WIDTH,
"Address", "Backtrace");
syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence",
MM_PTR_FMT_WIDTH, "Address", "Backtrace");
#endif
}
else
@ -947,7 +961,7 @@ void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
}
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0
mempool_multiple_memdump(heap->mm_mpool, pid);
mempool_multiple_memdump(heap->mm_mpool, dump);
#endif
#if CONFIG_MM_REGIONS > 1
@ -956,13 +970,12 @@ void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid)
{
DEBUGVERIFY(mm_lock(heap));
tlsf_walk_pool(heap->mm_heapstart[region],
memdump_handler, &pid);
memdump_handler, (FAR void *)dump);
mm_unlock(heap);
}
#undef region
info.pid = pid;
mm_mallinfo_task(heap, &info);
info = mm_mallinfo_task(heap, dump);
syslog(LOG_INFO, "%12s%12s\n", "Total Blks", "Total Size");
syslog(LOG_INFO, "%12d%12d\n", info.aordblks, info.uordblks);
}

View File

@ -59,11 +59,7 @@ struct mallinfo mallinfo(void)
*
****************************************************************************/
struct mallinfo_task mallinfo_task(pid_t pid)
struct mallinfo_task mallinfo_task(FAR const struct mm_memdump_s *dump)
{
struct mallinfo_task info;
info.pid = pid;
mm_mallinfo_task(USR_HEAP, &info);
return info;
return mm_mallinfo_task(USR_HEAP, dump);
}

View File

@ -27,6 +27,14 @@
#include "umm_heap/umm_heap.h"
/****************************************************************************
* Public data
****************************************************************************/
#if CONFIG_MM_BACKTRACE >= 0
unsigned long g_mm_seqno;
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -39,7 +47,7 @@
*
****************************************************************************/
void umm_memdump(pid_t pid)
void umm_memdump(FAR const struct mm_memdump_s *dump)
{
mm_memdump(USR_HEAP, pid);
mm_memdump(USR_HEAP, dump);
}