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:
parent
97e652aed1
commit
c60dd72a2a
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 *****************************/
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user