Merge pull request #4359 from willianchanlovegithub/Willianchan

[kernel][memheap]add memory heap track and memory heap check.
This commit is contained in:
Bernard Xiong 2021-03-15 09:25:53 +08:00 committed by GitHub
commit 4a0855c276
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 202 additions and 27 deletions

View File

@ -284,21 +284,19 @@ menu "Memory Management"
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.
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
And developer also can call memcheck() in each of scheduling
to check memory block to find which thread has wrongly modified
memory.
config RT_USING_HEAP
bool

View File

@ -35,6 +35,45 @@
#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
#define MEMITEM_SIZE(item) ((rt_ubase_t)item->next - (rt_ubase_t)item - RT_MEMHEAP_SIZE)
#define MEMITEM(ptr) (struct rt_memheap_item*)((rt_uint8_t*)ptr - RT_MEMHEAP_SIZE)
#ifdef RT_USING_MEMTRACE
rt_inline void rt_memheap_setname(struct rt_memheap_item *item, const char *name)
{
int index;
rt_uint8_t* ptr;
ptr = (rt_uint8_t*)&(item->next_free);
for (index = 0; index < sizeof(void*); index ++)
{
if (name[index] == '\0') break;
ptr[index] = name[index];
}
if (name[index] == '\0') ptr[index] = '\0';
else
{
ptr = (rt_uint8_t*)&(item->prev_free);
for (index = 0; index < sizeof(void*) && (index + sizeof(void*))< RT_NAME_MAX; index ++)
{
if (name[sizeof(void*) + index] == '\0') break;
ptr[index] = name[sizeof(void*) + index];
}
if (name[sizeof(void*) + index] == '\0') ptr[index] = '\0';
}
}
void rt_mem_set_tag(void* ptr, const char* name)
{
struct rt_memheap_item* item;
if (ptr && name)
{
item = MEMITEM(ptr);
rt_memheap_setname(item, name);
}
}
#endif
/*
* The initialized memory pool will be:
@ -66,7 +105,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
/* initialize the free list header */
item = &(memheap->free_header);
item->magic = RT_MEMHEAP_MAGIC;
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
item->pool_ptr = memheap;
item->next = RT_NULL;
item->prev = RT_NULL;
@ -78,7 +117,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
/* initialize the first big memory block */
item = (struct rt_memheap_item *)start_addr;
item->magic = RT_MEMHEAP_MAGIC;
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
item->pool_ptr = memheap;
item->next = RT_NULL;
item->prev = RT_NULL;
@ -107,7 +146,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
*/
item = item->next;
/* it's a used memory block */
item->magic = RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED;
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
item->pool_ptr = memheap;
item->next = (struct rt_memheap_item *)start_addr;
item->prev = (struct rt_memheap_item *)start_addr;
@ -205,7 +244,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
new_ptr));
/* mark the new block as a memory block and freed. */
new_ptr->magic = RT_MEMHEAP_MAGIC;
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
@ -263,7 +302,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
}
/* Mark the allocated block as not available. */
header_ptr->magic |= RT_MEMHEAP_USED;
header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
#ifdef RT_USING_MEMTRACE
if (rt_thread_self())
@ -391,7 +430,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
next_ptr->prev));
/* mark the new block as a memory block and freed. */
next_ptr->magic = RT_MEMHEAP_MAGIC;
next_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* put the pool pointer into the new block. */
next_ptr->pool_ptr = heap;
@ -460,7 +499,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
new_ptr));
/* mark the new block as a memory block and freed. */
new_ptr->magic = RT_MEMHEAP_MAGIC;
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
@ -535,8 +574,12 @@ void rt_memheap_free(void *ptr)
ptr, header_ptr));
/* check magic */
RT_ASSERT((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
RT_ASSERT(header_ptr->magic & RT_MEMHEAP_USED);
if (header_ptr->magic != (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED))
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("bad magic:0x%08x @ memheap\n",
header_ptr->magic));
}
RT_ASSERT(header_ptr->magic == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED));
/* check whether this block of memory has been over-written. */
RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
@ -556,9 +599,9 @@ void rt_memheap_free(void *ptr)
}
/* Mark the memory as available. */
header_ptr->magic &= ~RT_MEMHEAP_USED;
header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* Adjust the available number of bytes. */
heap->available_size = heap->available_size + MEMITEM_SIZE(header_ptr);
heap->available_size += MEMITEM_SIZE(header_ptr);
/* Determine if the block can be merged with the previous neighbor. */
if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
@ -567,7 +610,7 @@ void rt_memheap_free(void *ptr)
header_ptr->prev));
/* adjust the available number of bytes. */
heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
heap->available_size += RT_MEMHEAP_SIZE;
/* yes, merge block with previous neighbor. */
(header_ptr->prev)->next = header_ptr->next;
@ -583,7 +626,7 @@ void rt_memheap_free(void *ptr)
if (!RT_MEMHEAP_IS_USED(header_ptr->next))
{
/* adjust the available number of bytes. */
heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
heap->available_size += RT_MEMHEAP_SIZE;
/* merge block with next neighbor. */
new_ptr = header_ptr->next;
@ -622,6 +665,91 @@ void rt_memheap_free(void *ptr)
}
RTM_EXPORT(rt_memheap_free);
#ifdef RT_USING_FINSH
static void _memheap_dump_tag(struct rt_memheap_item* item)
{
rt_uint8_t name[2 * sizeof(void*)];
rt_uint8_t* ptr;
ptr = (rt_uint8_t*)&(item->next_free);
rt_memcpy(name, ptr, sizeof(void*));
ptr = (rt_uint8_t*)&(item->prev_free);
rt_memcpy(&name[sizeof(void*)], ptr, sizeof(void*));
rt_kprintf("%.*s", 2 * sizeof(void*), name);
}
int rt_memheap_dump(struct rt_memheap *heap)
{
struct rt_memheap_item *item, *end;
if (heap == RT_NULL) return 0;
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
rt_kprintf("\n[%.*s] [0x%08x - 0x%08x]->\n", RT_NAME_MAX, heap->parent.name,
(rt_ubase_t)heap->start_addr, (rt_ubase_t)heap->start_addr + heap->pool_size);
rt_kprintf("------------------------------\n");
/* lock memheap */
rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
item = heap->block_list;
end = (struct rt_memheap_item *) ((rt_uint8_t *)heap->start_addr + heap->pool_size - RT_MEMHEAP_SIZE);
/* for each memory block */
while ((rt_ubase_t)item < ((rt_ubase_t)end))
{
if (RT_MEMHEAP_IS_USED(item) && ((item->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC))
rt_kprintf("0x%08x", item + 1);
if (item->magic == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED))
{
rt_kprintf("0x%08x: %-8d ", item + 1, MEMITEM_SIZE(item));
_memheap_dump_tag(item);
rt_kprintf("\n");
}
else
{
rt_kprintf("0x%08x: %-8d <F>\n", item + 1, MEMITEM_SIZE(item));
}
item = item->next;
}
rt_sem_release(&(heap->lock));
return 0;
}
int memheaptrace(void)
{
int count = rt_object_get_length(RT_Object_Class_MemHeap);
struct rt_memheap **heaps;
if (count > 0)
{
int index;
extern int list_memheap(void);
heaps = (struct rt_memheap**)rt_malloc(sizeof(struct rt_memheap*) * count);
if (heaps == RT_NULL) return 0;
list_memheap();
rt_kprintf("memheap header size: %d\n", RT_MEMHEAP_SIZE);
count = rt_object_get_pointers(RT_Object_Class_MemHeap, (rt_object_t*)heaps, count);
for (index = 0; index < count; index++)
{
rt_memheap_dump(heaps[index]);
}
rt_free(heaps);
}
return 0;
}
MSH_CMD_EXPORT(memheaptrace, dump memory trace information);
#endif
#ifdef RT_USING_MEMHEAP_AS_HEAP
static struct rt_memheap _heap;
@ -670,6 +798,24 @@ void *rt_malloc(rt_size_t size)
}
}
#ifdef RT_USING_MEMTRACE
if (ptr == RT_NULL)
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("malloc[%d] => NULL", size));
}
else
{
struct rt_memheap_item *item = MEMITEM(ptr);
if (rt_thread_self())
rt_memheap_setname(item, rt_thread_self()->name);
else
rt_memheap_setname(item, "<null>");
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("malloc => 0x%08x : %d", ptr, size));
}
#endif
return ptr;
}
RTM_EXPORT(rt_malloc);
@ -718,6 +864,24 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
}
}
#ifdef RT_USING_MEMTRACE
if (new_ptr == RT_NULL)
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("realloc[%d] => NULL", newsize));
}
else
{
struct rt_memheap_item *item = MEMITEM(new_ptr);
if (rt_thread_self())
rt_memheap_setname(item, rt_thread_self()->name);
else
rt_memheap_setname(item, "<null>");
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("realloc => 0x%08x : %d",
new_ptr, newsize));
}
#endif
return new_ptr;
}
RTM_EXPORT(rt_realloc);
@ -735,6 +899,19 @@ void *rt_calloc(rt_size_t count, rt_size_t size)
rt_memset(ptr, 0, total_size);
}
#ifdef RT_USING_MEMTRACE
if (ptr == RT_NULL)
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("calloc[%d x %d] => NULL",
count, size));
}
else
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("calloc => 0x%08x : %d",
ptr, count * size));
}
#endif
return ptr;
}
RTM_EXPORT(rt_calloc);