[Kernel] Add memory trace for small memory management
This commit is contained in:
parent
4ab7214a32
commit
5326bd55a5
16
src/Kconfig
16
src/Kconfig
|
@ -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
|
||||
|
|
118
src/mem.c
118
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
|
||||
|
||||
/**@}*/
|
||||
|
|
Loading…
Reference in New Issue