提交 5326bd55 编写于 作者: B Bernard Xiong

[Kernel] Add memory trace for small memory management

上级 4ab7214a
......@@ -161,6 +161,22 @@ menu "Memory Management"
endif
endchoice
if RT_USING_SMALL_MEM
config RT_USING_MEMTRACE
bool "Enable memory trace"
default n
help
When enable RT_USING_MEMTRACE with shell, developer can call cmd:
1. memtrace
to dump memory block information.
2. memcheck
to check memory block to avoid memory overwritten.
And developer also can call memcheck() in each of scheduling
to check memory block to find which thread has wrongly modified
memory.
endif
config RT_USING_HEAP
bool
default n if RT_USING_NOHEAP
......
......@@ -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
/**@}*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册