Skip to content

Commit 4a0855c

Browse files
authored
Merge pull request #4359 from willianchanlovegithub/Willianchan
[kernel][memheap]add memory heap track and memory heap check.
2 parents 6090930 + ffe4493 commit 4a0855c

File tree

2 files changed

+203
-28
lines changed

2 files changed

+203
-28
lines changed

src/Kconfig

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -284,21 +284,19 @@ menu "Memory Management"
284284

285285
endchoice
286286

287-
if RT_USING_SMALL_MEM
288-
config RT_USING_MEMTRACE
289-
bool "Enable memory trace"
290-
default n
291-
help
292-
When enable RT_USING_MEMTRACE with shell, developer can call cmd:
293-
1. memtrace
294-
to dump memory block information.
295-
2. memcheck
296-
to check memory block to avoid memory overwritten.
297-
298-
And developer also can call memcheck() in each of scheduling
299-
to check memory block to find which thread has wrongly modified
300-
memory.
301-
endif
287+
config RT_USING_MEMTRACE
288+
bool "Enable memory trace"
289+
default n
290+
help
291+
When enable RT_USING_MEMTRACE with shell, developer can call cmd:
292+
1. memtrace
293+
to dump memory block information.
294+
2. memcheck
295+
to check memory block to avoid memory overwritten.
296+
297+
And developer also can call memcheck() in each of scheduling
298+
to check memory block to find which thread has wrongly modified
299+
memory.
302300

303301
config RT_USING_HEAP
304302
bool

src/memheap.c

Lines changed: 190 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,45 @@
3535

3636
#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
3737
#define MEMITEM_SIZE(item) ((rt_ubase_t)item->next - (rt_ubase_t)item - RT_MEMHEAP_SIZE)
38+
#define MEMITEM(ptr) (struct rt_memheap_item*)((rt_uint8_t*)ptr - RT_MEMHEAP_SIZE)
39+
40+
#ifdef RT_USING_MEMTRACE
41+
rt_inline void rt_memheap_setname(struct rt_memheap_item *item, const char *name)
42+
{
43+
int index;
44+
rt_uint8_t* ptr;
45+
46+
ptr = (rt_uint8_t*)&(item->next_free);
47+
for (index = 0; index < sizeof(void*); index ++)
48+
{
49+
if (name[index] == '\0') break;
50+
ptr[index] = name[index];
51+
}
52+
if (name[index] == '\0') ptr[index] = '\0';
53+
else
54+
{
55+
ptr = (rt_uint8_t*)&(item->prev_free);
56+
for (index = 0; index < sizeof(void*) && (index + sizeof(void*))< RT_NAME_MAX; index ++)
57+
{
58+
if (name[sizeof(void*) + index] == '\0') break;
59+
ptr[index] = name[sizeof(void*) + index];
60+
}
61+
62+
if (name[sizeof(void*) + index] == '\0') ptr[index] = '\0';
63+
}
64+
}
65+
66+
void rt_mem_set_tag(void* ptr, const char* name)
67+
{
68+
struct rt_memheap_item* item;
69+
70+
if (ptr && name)
71+
{
72+
item = MEMITEM(ptr);
73+
rt_memheap_setname(item, name);
74+
}
75+
}
76+
#endif
3877

3978
/*
4079
* The initialized memory pool will be:
@@ -66,7 +105,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
66105

67106
/* initialize the free list header */
68107
item = &(memheap->free_header);
69-
item->magic = RT_MEMHEAP_MAGIC;
108+
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
70109
item->pool_ptr = memheap;
71110
item->next = RT_NULL;
72111
item->prev = RT_NULL;
@@ -78,7 +117,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
78117

79118
/* initialize the first big memory block */
80119
item = (struct rt_memheap_item *)start_addr;
81-
item->magic = RT_MEMHEAP_MAGIC;
120+
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
82121
item->pool_ptr = memheap;
83122
item->next = RT_NULL;
84123
item->prev = RT_NULL;
@@ -107,7 +146,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
107146
*/
108147
item = item->next;
109148
/* it's a used memory block */
110-
item->magic = RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED;
149+
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
111150
item->pool_ptr = memheap;
112151
item->next = (struct rt_memheap_item *)start_addr;
113152
item->prev = (struct rt_memheap_item *)start_addr;
@@ -205,7 +244,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
205244
new_ptr));
206245

207246
/* mark the new block as a memory block and freed. */
208-
new_ptr->magic = RT_MEMHEAP_MAGIC;
247+
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
209248

210249
/* put the pool pointer into the new block. */
211250
new_ptr->pool_ptr = heap;
@@ -263,7 +302,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
263302
}
264303

265304
/* Mark the allocated block as not available. */
266-
header_ptr->magic |= RT_MEMHEAP_USED;
305+
header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
267306

268307
#ifdef RT_USING_MEMTRACE
269308
if (rt_thread_self())
@@ -391,7 +430,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
391430
next_ptr->prev));
392431

393432
/* mark the new block as a memory block and freed. */
394-
next_ptr->magic = RT_MEMHEAP_MAGIC;
433+
next_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
395434

396435
/* put the pool pointer into the new block. */
397436
next_ptr->pool_ptr = heap;
@@ -460,7 +499,7 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
460499
new_ptr));
461500

462501
/* mark the new block as a memory block and freed. */
463-
new_ptr->magic = RT_MEMHEAP_MAGIC;
502+
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
464503
/* put the pool pointer into the new block. */
465504
new_ptr->pool_ptr = heap;
466505

@@ -535,8 +574,12 @@ void rt_memheap_free(void *ptr)
535574
ptr, header_ptr));
536575

537576
/* check magic */
538-
RT_ASSERT((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
539-
RT_ASSERT(header_ptr->magic & RT_MEMHEAP_USED);
577+
if (header_ptr->magic != (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED))
578+
{
579+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("bad magic:0x%08x @ memheap\n",
580+
header_ptr->magic));
581+
}
582+
RT_ASSERT(header_ptr->magic == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED));
540583
/* check whether this block of memory has been over-written. */
541584
RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
542585

@@ -556,9 +599,9 @@ void rt_memheap_free(void *ptr)
556599
}
557600

558601
/* Mark the memory as available. */
559-
header_ptr->magic &= ~RT_MEMHEAP_USED;
602+
header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
560603
/* Adjust the available number of bytes. */
561-
heap->available_size = heap->available_size + MEMITEM_SIZE(header_ptr);
604+
heap->available_size += MEMITEM_SIZE(header_ptr);
562605

563606
/* Determine if the block can be merged with the previous neighbor. */
564607
if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
@@ -567,7 +610,7 @@ void rt_memheap_free(void *ptr)
567610
header_ptr->prev));
568611

569612
/* adjust the available number of bytes. */
570-
heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
613+
heap->available_size += RT_MEMHEAP_SIZE;
571614

572615
/* yes, merge block with previous neighbor. */
573616
(header_ptr->prev)->next = header_ptr->next;
@@ -583,7 +626,7 @@ void rt_memheap_free(void *ptr)
583626
if (!RT_MEMHEAP_IS_USED(header_ptr->next))
584627
{
585628
/* adjust the available number of bytes. */
586-
heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
629+
heap->available_size += RT_MEMHEAP_SIZE;
587630

588631
/* merge block with next neighbor. */
589632
new_ptr = header_ptr->next;
@@ -622,6 +665,91 @@ void rt_memheap_free(void *ptr)
622665
}
623666
RTM_EXPORT(rt_memheap_free);
624667

668+
#ifdef RT_USING_FINSH
669+
static void _memheap_dump_tag(struct rt_memheap_item* item)
670+
{
671+
rt_uint8_t name[2 * sizeof(void*)];
672+
rt_uint8_t* ptr;
673+
674+
ptr = (rt_uint8_t*)&(item->next_free);
675+
rt_memcpy(name, ptr, sizeof(void*));
676+
ptr = (rt_uint8_t*)&(item->prev_free);
677+
rt_memcpy(&name[sizeof(void*)], ptr, sizeof(void*));
678+
679+
rt_kprintf("%.*s", 2 * sizeof(void*), name);
680+
}
681+
682+
int rt_memheap_dump(struct rt_memheap *heap)
683+
{
684+
struct rt_memheap_item *item, *end;
685+
686+
if (heap == RT_NULL) return 0;
687+
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
688+
689+
rt_kprintf("\n[%.*s] [0x%08x - 0x%08x]->\n", RT_NAME_MAX, heap->parent.name,
690+
(rt_ubase_t)heap->start_addr, (rt_ubase_t)heap->start_addr + heap->pool_size);
691+
rt_kprintf("------------------------------\n");
692+
693+
/* lock memheap */
694+
rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
695+
item = heap->block_list;
696+
697+
end = (struct rt_memheap_item *) ((rt_uint8_t *)heap->start_addr + heap->pool_size - RT_MEMHEAP_SIZE);
698+
699+
/* for each memory block */
700+
while ((rt_ubase_t)item < ((rt_ubase_t)end))
701+
{
702+
if (RT_MEMHEAP_IS_USED(item) && ((item->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC))
703+
rt_kprintf("0x%08x", item + 1);
704+
705+
if (item->magic == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED))
706+
{
707+
rt_kprintf("0x%08x: %-8d ", item + 1, MEMITEM_SIZE(item));
708+
_memheap_dump_tag(item);
709+
rt_kprintf("\n");
710+
}
711+
else
712+
{
713+
rt_kprintf("0x%08x: %-8d <F>\n", item + 1, MEMITEM_SIZE(item));
714+
}
715+
716+
item = item->next;
717+
}
718+
rt_sem_release(&(heap->lock));
719+
720+
return 0;
721+
}
722+
723+
int memheaptrace(void)
724+
{
725+
int count = rt_object_get_length(RT_Object_Class_MemHeap);
726+
struct rt_memheap **heaps;
727+
728+
if (count > 0)
729+
{
730+
int index;
731+
extern int list_memheap(void);
732+
733+
heaps = (struct rt_memheap**)rt_malloc(sizeof(struct rt_memheap*) * count);
734+
if (heaps == RT_NULL) return 0;
735+
736+
list_memheap();
737+
738+
rt_kprintf("memheap header size: %d\n", RT_MEMHEAP_SIZE);
739+
count = rt_object_get_pointers(RT_Object_Class_MemHeap, (rt_object_t*)heaps, count);
740+
for (index = 0; index < count; index++)
741+
{
742+
rt_memheap_dump(heaps[index]);
743+
}
744+
745+
rt_free(heaps);
746+
}
747+
748+
return 0;
749+
}
750+
MSH_CMD_EXPORT(memheaptrace, dump memory trace information);
751+
#endif
752+
625753
#ifdef RT_USING_MEMHEAP_AS_HEAP
626754
static struct rt_memheap _heap;
627755

@@ -670,6 +798,24 @@ void *rt_malloc(rt_size_t size)
670798
}
671799
}
672800

801+
802+
#ifdef RT_USING_MEMTRACE
803+
if (ptr == RT_NULL)
804+
{
805+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("malloc[%d] => NULL", size));
806+
}
807+
else
808+
{
809+
struct rt_memheap_item *item = MEMITEM(ptr);
810+
if (rt_thread_self())
811+
rt_memheap_setname(item, rt_thread_self()->name);
812+
else
813+
rt_memheap_setname(item, "<null>");
814+
815+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("malloc => 0x%08x : %d", ptr, size));
816+
}
817+
#endif
818+
673819
return ptr;
674820
}
675821
RTM_EXPORT(rt_malloc);
@@ -718,6 +864,24 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
718864
}
719865
}
720866

867+
#ifdef RT_USING_MEMTRACE
868+
if (new_ptr == RT_NULL)
869+
{
870+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("realloc[%d] => NULL", newsize));
871+
}
872+
else
873+
{
874+
struct rt_memheap_item *item = MEMITEM(new_ptr);
875+
if (rt_thread_self())
876+
rt_memheap_setname(item, rt_thread_self()->name);
877+
else
878+
rt_memheap_setname(item, "<null>");
879+
880+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("realloc => 0x%08x : %d",
881+
new_ptr, newsize));
882+
}
883+
#endif
884+
721885
return new_ptr;
722886
}
723887
RTM_EXPORT(rt_realloc);
@@ -735,6 +899,19 @@ void *rt_calloc(rt_size_t count, rt_size_t size)
735899
rt_memset(ptr, 0, total_size);
736900
}
737901

902+
#ifdef RT_USING_MEMTRACE
903+
if (ptr == RT_NULL)
904+
{
905+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("calloc[%d x %d] => NULL",
906+
count, size));
907+
}
908+
else
909+
{
910+
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("calloc => 0x%08x : %d",
911+
ptr, count * size));
912+
}
913+
#endif
914+
738915
return ptr;
739916
}
740917
RTM_EXPORT(rt_calloc);

0 commit comments

Comments
 (0)