[Kernel] Add memory trace for small memory management

This commit is contained in:
Bernard Xiong 2017-12-22 14:29:14 +08:00
parent 4ab7214a32
commit 5326bd55a5
2 changed files with 133 additions and 1 deletions

View File

@ -161,6 +161,22 @@ menu "Memory Management"
endif endif
endchoice 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 config RT_USING_HEAP
bool bool
default n if RT_USING_NOHEAP default n if RT_USING_NOHEAP

118
src/mem.c
View File

@ -113,6 +113,10 @@ struct heap_mem
rt_uint16_t used; rt_uint16_t used;
rt_size_t next, prev; 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 */ /** 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 #ifdef RT_MEM_STATS
static rt_size_t used_mem, max_mem; static rt_size_t used_mem, max_mem;
#endif #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) 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->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
mem->prev = 0; mem->prev = 0;
mem->used = 0; mem->used = 0;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(mem, "INIT");
#endif
/* initialize the end of the heap */ /* initialize the end of the heap */
heap_end = (struct heap_mem *)&heap_ptr[mem->next]; 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->used = 1;
heap_end->next = mem_size_aligned + SIZEOF_STRUCT_MEM; heap_end->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
heap_end->prev = 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); 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->used = 0;
mem2->next = mem->next; mem2->next = mem->next;
mem2->prev = ptr; mem2->prev = ptr;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(mem2, " ");
#endif
/* and insert it between mem and mem->next */ /* and insert it between mem and mem->next */
mem->next = ptr2; mem->next = ptr2;
@ -342,6 +371,12 @@ void *rt_malloc(rt_size_t size)
} }
/* set memory block magic */ /* set memory block magic */
mem->magic = HEAP_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) if (mem == lfree)
{ {
@ -447,6 +482,9 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
mem2->used = 0; mem2->used = 0;
mem2->next = mem->next; mem2->next = mem->next;
mem2->prev = ptr; mem2->prev = ptr;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(mem2, " ");
#endif
mem->next = ptr2; mem->next = ptr2;
if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM) 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); rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* ... which has to be in a used state ... */ /* ... 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->used);
RT_ASSERT(mem->magic == HEAP_MAGIC); RT_ASSERT(mem->magic == HEAP_MAGIC);
/* ... and is now unused. */ /* ... and is now unused. */
mem->used = 0; mem->used = 0;
mem->magic = HEAP_MAGIC; mem->magic = HEAP_MAGIC;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(mem, " ");
#endif
if (mem < lfree) if (mem < lfree)
{ {
@ -588,7 +634,77 @@ void list_mem(void)
rt_kprintf("maximum allocated memory: %d\n", max_mem); rt_kprintf("maximum allocated memory: %d\n", max_mem);
} }
FINSH_FUNCTION_EXPORT(list_mem, list memory usage information) 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 #endif
/**@}*/ /**@}*/