|
@@ -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
|
|
|
|
|
|
/**@}*/
|