summaryrefslogtreecommitdiff
path: root/src/mem.c
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2017-12-22 14:29:14 +0800
committerBernard Xiong <[email protected]>2017-12-22 14:36:35 +0800
commit5326bd55a5674837c771deb6298eaf8c842b9de1 (patch)
treeb845bd0c955403580b212ffdb1f2c28ecffbc703 /src/mem.c
parent4ab7214a321477b0cb90d73f1d605ff40fd1a003 (diff)
[Kernel] Add memory trace for small memory management
Diffstat (limited to 'src/mem.c')
-rw-r--r--src/mem.c118
1 files changed, 117 insertions, 1 deletions
diff --git a/src/mem.c b/src/mem.c
index 92c85385ab..a0c60a8670 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -113,6 +113,10 @@ struct heap_mem
rt_uint16_t used;
rt_size_t next, prev;
+
+#ifdef RT_USING_MEMTRACE
+ rt_uint8_t thread[4]; /* thread name */
+#endif
};
/** pointer to the heap: for alignment, heap_ptr is now a pointer instead of an array */
@@ -133,6 +137,22 @@ static rt_size_t mem_size_aligned;
#ifdef RT_MEM_STATS
static rt_size_t used_mem, max_mem;
#endif
+#ifdef RT_USING_MEMTRACE
+rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name)
+{
+ int index;
+ for (index = 0; index < sizeof(mem->thread); index ++)
+ {
+ if (name[index] == '\0') break;
+ mem->thread[index] = name[index];
+ }
+
+ for (; index < sizeof(mem->thread); index ++)
+ {
+ mem->thread[index] = ' ';
+ }
+}
+#endif
static void plug_holes(struct heap_mem *mem)
{
@@ -217,6 +237,9 @@ void rt_system_heap_init(void *begin_addr, void *end_addr)
mem->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
mem->prev = 0;
mem->used = 0;
+ #ifdef RT_USING_MEMTRACE
+ rt_mem_setname(mem, "INIT");
+ #endif
/* initialize the end of the heap */
heap_end = (struct heap_mem *)&heap_ptr[mem->next];
@@ -224,6 +247,9 @@ void rt_system_heap_init(void *begin_addr, void *end_addr)
heap_end->used = 1;
heap_end->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
heap_end->prev = mem_size_aligned + SIZEOF_STRUCT_MEM;
+ #ifdef RT_USING_MEMTRACE
+ rt_mem_setname(heap_end, "INIT");
+ #endif
rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO);
@@ -309,6 +335,9 @@ void *rt_malloc(rt_size_t size)
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;
+ #ifdef RT_USING_MEMTRACE
+ rt_mem_setname(mem2, " ");
+ #endif
/* and insert it between mem and mem->next */
mem->next = ptr2;
@@ -342,6 +371,12 @@ void *rt_malloc(rt_size_t size)
}
/* set memory block magic */
mem->magic = HEAP_MAGIC;
+ #ifdef RT_USING_MEMTRACE
+ if (rt_thread_self())
+ rt_mem_setname(mem, rt_thread_self()->name);
+ else
+ rt_mem_setname(mem, "NONE");
+ #endif
if (mem == lfree)
{
@@ -447,6 +482,9 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;
+#ifdef RT_USING_MEMTRACE
+ rt_mem_setname(mem2, " ");
+#endif
mem->next = ptr2;
if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM)
{
@@ -543,11 +581,19 @@ void rt_free(void *rmem)
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* ... which has to be in a used state ... */
+ if (!mem->used || mem->magic != HEAP_MAGIC)
+ {
+ rt_kprintf("to free a bad data block:\n");
+ rt_kprintf("mem: 0x%08x, used flag: %d, magic code: 0x%04x\n", mem, mem->used, mem->magic);
+ }
RT_ASSERT(mem->used);
RT_ASSERT(mem->magic == HEAP_MAGIC);
/* ... and is now unused. */
mem->used = 0;
mem->magic = HEAP_MAGIC;
+#ifdef RT_USING_MEMTRACE
+ rt_mem_setname(mem, " ");
+#endif
if (mem < lfree)
{
@@ -588,7 +634,77 @@ void list_mem(void)
rt_kprintf("maximum allocated memory: %d\n", max_mem);
}
FINSH_FUNCTION_EXPORT(list_mem, list memory usage information)
-#endif
+
+#ifdef RT_USING_MEMTRACE
+int memcheck(void)
+{
+ int position;
+ rt_uint32_t level;
+ struct heap_mem *mem;
+ level = rt_hw_interrupt_disable();
+ for (mem = (struct heap_mem*)heap_ptr; mem != heap_end; mem = (struct heap_mem*)&heap_ptr[mem->next])
+ {
+ position = (rt_uint32_t)mem - (rt_uint32_t)heap_ptr;
+ if (position < 0) goto __exit;
+ if (position > mem_size_aligned) goto __exit;
+ if (mem->magic != HEAP_MAGIC) goto __exit;
+ if (mem->used != 0 && mem->used != 1) goto __exit;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return 0;
+__exit:
+ rt_kprintf("Memory block wrong:\n");
+ rt_kprintf("address: 0x%08x\n", mem);
+ rt_kprintf(" magic: 0x%04x\n", mem->magic);
+ rt_kprintf(" used: %d\n", mem->used);
+ rt_kprintf(" size: %d\n", mem->next - position - SIZEOF_STRUCT_MEM);
+ rt_hw_interrupt_enable(level);
+
+ return 0;
+}
+MSH_CMD_EXPORT(memcheck, check memory data);
+
+int memtrace(int argc, char** argv)
+{
+ struct heap_mem *mem;
+
+ list_mem();
+
+ rt_kprintf("\nmemory heap address:\n");
+ rt_kprintf("heap_ptr: 0x%08x\n", heap_ptr);
+ rt_kprintf("lfree : 0x%08x\n", lfree);
+ rt_kprintf("heap_end: 0x%08x\n", heap_end);
+
+ rt_kprintf("\n--memory item information --\n");
+ for (mem = (struct heap_mem*)heap_ptr; mem != heap_end; mem = (struct heap_mem*)&heap_ptr[mem->next])
+ {
+ int position = (rt_uint32_t)mem - (rt_uint32_t)heap_ptr;
+ int size;
+
+ rt_kprintf("[0x%08x - ", mem);
+
+ size = mem->next - position - SIZEOF_STRUCT_MEM;
+ if (size < 1024)
+ rt_kprintf("%5d", size);
+ else if (size < 1024 * 1024)
+ rt_kprintf("%4dK", size / 1024);
+ else
+ rt_kprintf("%4dM", size / (1024 * 1024));
+
+ rt_kprintf("] %c%c%c%c", mem->thread[0], mem->thread[1], mem->thread[2], mem->thread[3]);
+ if (mem->magic != HEAP_MAGIC)
+ rt_kprintf(": ***\n");
+ else
+ rt_kprintf("\n");
+ }
+
+ return 0;
+}
+MSH_CMD_EXPORT(memtrace, dump memory trace information);
+#endif /* end of RT_USING_MEMTRACE */
+#endif /* end of RT_USING_FINSH */
+
#endif
/**@}*/