27#ifdef RT_USING_MEMHEAP
29#define DBG_TAG "kernel.memheap"
30#define DBG_LVL DBG_INFO
34#define RT_MEMHEAP_MAGIC 0x1ea01ea0
35#define RT_MEMHEAP_MASK 0xFFFFFFFE
36#define RT_MEMHEAP_USED 0x01
37#define RT_MEMHEAP_FREED 0x00
39#define RT_MEMHEAP_IS_USED(i) ((i)->magic & RT_MEMHEAP_USED)
40#define RT_MEMHEAP_MINIALLOC RT_ALIGN(12, RT_ALIGN_SIZE)
42#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
43#define MEMITEM_SIZE(item) ((rt_uintptr_t)item->next - (rt_uintptr_t)item - RT_MEMHEAP_SIZE)
44#define MEMITEM(ptr) (struct rt_memheap_item*)((rt_uint8_t*)ptr - RT_MEMHEAP_SIZE)
46static void _remove_next_ptr(
volatile struct rt_memheap_item *next_ptr)
50 next_ptr->next_free->prev_free = next_ptr->prev_free;
51 next_ptr->prev_free->next_free = next_ptr->next_free;
52 next_ptr->next->prev = next_ptr->prev;
53 next_ptr->prev->next = next_ptr->next;
79rt_err_t rt_memheap_init(
struct rt_memheap *memheap,
84 struct rt_memheap_item *item;
91 memheap->start_addr = start_addr;
93 memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE);
94 memheap->max_used_size = memheap->pool_size - memheap->available_size;
97 item = &(memheap->free_header);
98 item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
99 item->pool_ptr = memheap;
102 item->next_free = item;
103 item->prev_free = item;
106 memheap->free_list = item;
109 item = (
struct rt_memheap_item *)start_addr;
110 item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
111 item->pool_ptr = memheap;
114 item->next_free = item;
115 item->prev_free = item;
117#ifdef RT_USING_MEMTRACE
118 rt_memset(item->owner_thread_name,
' ',
sizeof(item->owner_thread_name));
121 item->next = (
struct rt_memheap_item *)
122 ((
rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE);
123 item->prev = item->next;
126 memheap->block_list = item;
129 item->next_free = memheap->free_list->next_free;
130 item->prev_free = memheap->free_list;
131 memheap->free_list->next_free->prev_free = item;
132 memheap->free_list->next_free = item;
139 item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
140 item->pool_ptr = memheap;
141 item->next = (
struct rt_memheap_item *)start_addr;
142 item->prev = (
struct rt_memheap_item *)start_addr;
144 item->next_free = item->prev_free =
RT_NULL;
150 LOG_D(
"memory heap: start addr 0x%08x, size %d, free list header 0x%08x",
151 start_addr, size, &(memheap->free_header));
164rt_err_t rt_memheap_detach(
struct rt_memheap *heap)
187void *rt_memheap_alloc(
struct rt_memheap *heap,
rt_size_t size)
191 struct rt_memheap_item *header_ptr;
197 size =
RT_ALIGN(size, RT_ALIGN_SIZE);
198 if (size < RT_MEMHEAP_MINIALLOC)
199 size = RT_MEMHEAP_MINIALLOC;
201 LOG_D(
"allocate %d on heap:%8.*s",
202 size, RT_NAME_MAX, heap->parent.name);
204 if (size < heap->available_size)
213 if (result != RT_EOK)
215 rt_set_errno(result);
222 header_ptr = heap->free_list->next_free;
223 while (header_ptr != heap->free_list && free_size < size)
226 free_size = MEMITEM_SIZE(header_ptr);
227 if (free_size < size)
230 header_ptr = header_ptr->next_free;
235 if (free_size >= size)
240 if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC))
242 struct rt_memheap_item *new_ptr;
245 new_ptr = (
struct rt_memheap_item *)
246 (((
rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
248 LOG_D(
"split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]",
255 new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
258 new_ptr->pool_ptr = heap;
260#ifdef RT_USING_MEMTRACE
261 rt_memset(new_ptr->owner_thread_name,
' ',
sizeof(new_ptr->owner_thread_name));
265 new_ptr->prev = header_ptr;
266 new_ptr->next = header_ptr->next;
267 header_ptr->next->prev = new_ptr;
268 header_ptr->next = new_ptr;
271 header_ptr->next_free->prev_free = header_ptr->prev_free;
272 header_ptr->prev_free->next_free = header_ptr->next_free;
273 header_ptr->next_free =
RT_NULL;
274 header_ptr->prev_free =
RT_NULL;
277 new_ptr->next_free = heap->free_list->next_free;
278 new_ptr->prev_free = heap->free_list;
279 heap->free_list->next_free->prev_free = new_ptr;
280 heap->free_list->next_free = new_ptr;
281 LOG_D(
"new ptr: next_free 0x%08x, prev_free 0x%08x",
286 heap->available_size = heap->available_size -
289 if (heap->pool_size - heap->available_size > heap->max_used_size)
290 heap->max_used_size = heap->pool_size - heap->available_size;
295 heap->available_size = heap->available_size - free_size;
296 if (heap->pool_size - heap->available_size > heap->max_used_size)
297 heap->max_used_size = heap->pool_size - heap->available_size;
300 LOG_D(
"one block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x",
302 header_ptr->next_free,
303 header_ptr->prev_free);
305 header_ptr->next_free->prev_free = header_ptr->prev_free;
306 header_ptr->prev_free->next_free = header_ptr->next_free;
307 header_ptr->next_free =
RT_NULL;
308 header_ptr->prev_free =
RT_NULL;
312 header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
314#ifdef RT_USING_MEMTRACE
316 rt_memcpy(header_ptr->owner_thread_name,
rt_thread_self()->parent.name,
sizeof(header_ptr->owner_thread_name));
318 rt_memcpy(header_ptr->owner_thread_name,
"NONE",
sizeof(header_ptr->owner_thread_name));
328 LOG_D(
"alloc mem: memory[0x%08x], heap[0x%08x], size: %d",
329 (
void *)((
rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE),
333 return (
void *)((
rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE);
343 LOG_D(
"allocate memory: failed");
362void *rt_memheap_realloc(
struct rt_memheap *heap,
void *ptr,
rt_size_t newsize)
366 struct rt_memheap_item *header_ptr;
367 struct rt_memheap_item *new_ptr;
374 rt_memheap_free(ptr);
379 newsize =
RT_ALIGN(newsize, RT_ALIGN_SIZE);
380 if (newsize < RT_MEMHEAP_MINIALLOC)
381 newsize = RT_MEMHEAP_MINIALLOC;
385 return rt_memheap_alloc(heap, newsize);
389 header_ptr = (
struct rt_memheap_item *)
391 oldsize = MEMITEM_SIZE(header_ptr);
393 if (newsize > oldsize)
396 volatile struct rt_memheap_item *next_ptr;
402 if (result != RT_EOK)
404 rt_set_errno(result);
409 next_ptr = header_ptr->next;
415 if (!RT_MEMHEAP_IS_USED(next_ptr))
419 nextsize = MEMITEM_SIZE(next_ptr);
431 if (nextsize + oldsize > newsize + RT_MEMHEAP_MINIALLOC)
434 heap->available_size = heap->available_size - (newsize - oldsize);
435 if (heap->pool_size - heap->available_size > heap->max_used_size)
436 heap->max_used_size = heap->pool_size - heap->available_size;
439 LOG_D(
"remove block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x",
442 next_ptr->prev_free);
444 _remove_next_ptr(next_ptr);
447 next_ptr = (
struct rt_memheap_item *)((
char *)ptr + newsize);
449 LOG_D(
"new free block: block[0x%08x] nextm[0x%08x] prevm[0x%08x]",
455 next_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
458 next_ptr->pool_ptr = heap;
460#ifdef RT_USING_MEMTRACE
461 rt_memset((
void *)next_ptr->owner_thread_name,
' ',
sizeof(next_ptr->owner_thread_name));
464 next_ptr->prev = header_ptr;
465 next_ptr->next = header_ptr->next;
466 header_ptr->next->prev = (
struct rt_memheap_item *)next_ptr;
467 header_ptr->next = (
struct rt_memheap_item *)next_ptr;
470 next_ptr->next_free = heap->free_list->next_free;
471 next_ptr->prev_free = heap->free_list;
472 heap->free_list->next_free->prev_free = (
struct rt_memheap_item *)next_ptr;
473 heap->free_list->next_free = (
struct rt_memheap_item *)next_ptr;
474 LOG_D(
"new ptr: next_free 0x%08x, prev_free 0x%08x",
476 next_ptr->prev_free);
494 new_ptr = (
void *)rt_memheap_alloc(heap, newsize);
497 rt_memcpy(new_ptr, ptr, oldsize < newsize ? oldsize : newsize);
498 rt_memheap_free(ptr);
505 if (newsize + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC >= oldsize)
512 if (result != RT_EOK)
514 rt_set_errno(result);
521 new_ptr = (
struct rt_memheap_item *)
522 (((
rt_uint8_t *)header_ptr) + newsize + RT_MEMHEAP_SIZE);
524 LOG_D(
"split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]",
531 new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
533 new_ptr->pool_ptr = heap;
535#ifdef RT_USING_MEMTRACE
536 rt_memset(new_ptr->owner_thread_name,
' ',
sizeof(new_ptr->owner_thread_name));
540 new_ptr->prev = header_ptr;
541 new_ptr->next = header_ptr->next;
542 header_ptr->next->prev = new_ptr;
543 header_ptr->next = new_ptr;
546 if (!RT_MEMHEAP_IS_USED(new_ptr->next))
548 struct rt_memheap_item *free_ptr;
551 free_ptr = new_ptr->next;
552 heap->available_size = heap->available_size - MEMITEM_SIZE(free_ptr);
554 LOG_D(
"merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x",
555 header_ptr, header_ptr->next_free, header_ptr->prev_free);
557 free_ptr->next->prev = new_ptr;
558 new_ptr->next = free_ptr->next;
561 free_ptr->next_free->prev_free = free_ptr->prev_free;
562 free_ptr->prev_free->next_free = free_ptr->next_free;
566 new_ptr->next_free = heap->free_list->next_free;
567 new_ptr->prev_free = heap->free_list;
568 heap->free_list->next_free->prev_free = new_ptr;
569 heap->free_list->next_free = new_ptr;
570 LOG_D(
"new free ptr: next_free 0x%08x, prev_free 0x%08x",
575 heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr);
594void rt_memheap_free(
void *ptr)
597 struct rt_memheap *heap;
598 struct rt_memheap_item *header_ptr, *new_ptr;
607 header_ptr = (
struct rt_memheap_item *)
610 LOG_D(
"free memory: memory[0x%08x], block[0x%08x]",
614 if (header_ptr->magic != (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED) ||
615 (header_ptr->next->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
617 LOG_D(
"bad magic:0x%08x @ memheap",
619 RT_ASSERT(header_ptr->magic == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED));
621 RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
625 heap = header_ptr->pool_ptr;
634 if (result != RT_EOK)
636 rt_set_errno(result);
643 header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
645 heap->available_size += MEMITEM_SIZE(header_ptr);
648 if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
650 LOG_D(
"merge: left node 0x%08x",
654 heap->available_size += RT_MEMHEAP_SIZE;
657 (header_ptr->prev)->next = header_ptr->next;
658 (header_ptr->next)->prev = header_ptr->prev;
661 header_ptr = header_ptr->prev;
667 if (!RT_MEMHEAP_IS_USED(header_ptr->next))
670 heap->available_size += RT_MEMHEAP_SIZE;
673 new_ptr = header_ptr->next;
675 LOG_D(
"merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x",
676 new_ptr, new_ptr->next_free, new_ptr->prev_free);
678 new_ptr->next->prev = header_ptr;
679 header_ptr->next = new_ptr->next;
682 new_ptr->next_free->prev_free = new_ptr->prev_free;
683 new_ptr->prev_free->next_free = new_ptr->next_free;
688 struct rt_memheap_item *n = heap->free_list->next_free;;
689#if defined(RT_MEMHEAP_BEST_MODE)
690 rt_size_t blk_size = MEMITEM_SIZE(header_ptr);
691 for (;n != heap->free_list; n = n->next_free)
701 header_ptr->next_free = n;
702 header_ptr->prev_free = n->prev_free;
703 n->prev_free->next_free = header_ptr;
704 n->prev_free = header_ptr;
706 LOG_D(
"insert to free list: next_free 0x%08x, prev_free 0x%08x",
707 header_ptr->next_free, header_ptr->prev_free);
710#ifdef RT_USING_MEMTRACE
711 rt_memset(header_ptr->owner_thread_name,
' ',
sizeof(header_ptr->owner_thread_name));
735void rt_memheap_info(
struct rt_memheap *heap,
746 if (result != RT_EOK)
748 rt_set_errno(result);
754 *total = heap->pool_size;
757 *used = heap->pool_size - heap->available_size;
760 *max_used = heap->max_used_size;
769#ifdef RT_USING_MEMHEAP_AS_HEAP
773void *_memheap_alloc(
struct rt_memheap *heap,
rt_size_t size)
778 ptr = rt_memheap_alloc(heap, size);
779#ifdef RT_USING_MEMHEAP_AUTO_BINDING
784 struct rt_memheap *_heap;
795 _heap = (
struct rt_memheap *)
object;
801 ptr = rt_memheap_alloc(_heap, size);
813void _memheap_free(
void *rmem)
815 rt_memheap_free(rmem);
821void *_memheap_realloc(
struct rt_memheap *heap,
void *rmem,
rt_size_t newsize)
824 struct rt_memheap_item *header_ptr;
827 return _memheap_alloc(heap, newsize);
836 header_ptr = (
struct rt_memheap_item *)
839 new_ptr = rt_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
840 if (new_ptr ==
RT_NULL && newsize != 0)
843 new_ptr = _memheap_alloc(heap, newsize);
849 oldsize = MEMITEM_SIZE(header_ptr);
850 if (newsize > oldsize)
851 rt_memcpy(new_ptr, rmem, oldsize);
853 rt_memcpy(new_ptr, rmem, newsize);
863#ifdef RT_USING_MEMTRACE
864static int memheapcheck(
int argc,
char *argv[])
868 struct rt_memheap *heap;
870 struct rt_memheap_item *item;
875 name = argc > 1 ? argv[1] :
RT_NULL;
879 for (node = list->
next; node != list; node = node->
next)
883 if (name !=
RT_NULL && rt_strncmp(name, heap->parent.name, RT_NAME_MAX) != 0)
886 for (item = heap->block_list; item->next != heap->block_list; item = item->next)
889 if (!((item->magic & (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED)) == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED) ||
890 (item->magic & (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED)) == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED)))
896 if (heap != item->pool_ptr)
911 if (item->next == item->next->prev)
929static int memheaptrace(
int argc,
char *argv[])
933 struct rt_memheap *mh;
937 name = argc > 1 ? argv[1] :
RT_NULL;
940 for (node = list->
next; node != list; node = node->
next)
942 struct rt_memheap_item *header_ptr;
947 if (name !=
RT_NULL && rt_strncmp(name, mh->parent.name, RT_NAME_MAX) != 0)
952 rt_kprintf(
"heap_ptr: 0x%p\n", mh->start_addr);
953 rt_kprintf(
"free : 0x%08x\n", mh->available_size);
954 rt_kprintf(
"max_used: 0x%08x\n", mh->max_used_size);
956 rt_kprintf(
"\n--memory used information --\n");
958 for (header_ptr = mh->block_list;
959 header_ptr->next != mh->block_list;
960 header_ptr = header_ptr->next)
962 if ((header_ptr->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
964 rt_kprintf(
"[0x%p - incorrect magic: 0x%08x\n",
965 header_ptr, header_ptr->magic);
969 block_size = MEMITEM_SIZE(header_ptr);
974 if (block_size < 1024)
976 else if (block_size < 1024 * 1024)
978 else if (block_size < 1024 * 1024 * 100)
979 rt_kprintf(
"%2d.%dM", block_size / (1024 * 1024), (block_size % (1024 * 1024) * 10) / (1024 * 1024));
981 rt_kprintf(
"%4dM", block_size / (1024 * 1024));
984 header_ptr->owner_thread_name[0],
985 header_ptr->owner_thread_name[1],
986 header_ptr->owner_thread_name[2],
987 header_ptr->owner_thread_name[3]);
#define RT_ALIGN(size, align)
#define RT_ALIGN_DOWN(size, align)
#define RT_WAITING_FOREVER
void rt_object_init(struct rt_object *object, enum rt_object_class_type type, const char *name)
This function will initialize an object and add it to object system management.
rt_bool_t rt_object_is_systemobject(rt_object_t object)
This function will judge the object is system object or not.
struct rt_object_information * rt_object_get_information(enum rt_object_class_type type)
This function will return the specified type of object information.
rt_uint8_t rt_object_get_type(rt_object_t object)
This function will return the type of object without RT_Object_Class_Static flag.
void rt_object_detach(rt_object_t object)
This function will detach a static object from object system, and the memory of static object is not ...
@ RT_Object_Class_MemHeap
#define rt_list_entry(node, type, member)
get the struct for this entry
rt_thread_t rt_thread_self(void)
This function will return self thread object.
#define MSH_CMD_EXPORT(...)
rt_err_t rt_sem_init(rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag)
This function will initialize a static semaphore object.
rt_err_t rt_sem_detach(rt_sem_t sem)
This function will detach a static semaphore object.
rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
rt_err_t rt_sem_release(rt_sem_t sem)
This function will release a semaphore. If there is thread suspended on the semaphore,...
void rt_hw_interrupt_enable(rt_base_t level)
rt_base_t rt_hw_interrupt_disable(void)
#define RTM_EXPORT(symbol)
struct rt_list_node * next