diff options
| author | Tangyuxin <[email protected]> | 2021-12-16 16:23:58 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-12-16 16:23:58 +0800 |
| commit | d724eed9fc09269c3c6e921c1f8b2df573508419 (patch) | |
| tree | 92f8528e0efbe28d4632692896d0bcaa2e45b3b6 /src/mem.c | |
| parent | 874f6c84f19f8ca24ebd00a9a95e7af02afc49a0 (diff) | |
分离内存分配接口与内存分配算法 (#5175)
* [kernel][mem] Multiple instances of small memory allocation algorithm
* [kernel][mem] Change small memory management algorithm memory header flag
* [kernel][mem] Fix assertion problem
* [kernel][slab] Multiple instances of slab memory management algorithm
* [kernel][memheap] Remove rt_malloc/rt_free/rt_realloc and other related memory interfaces
* [kernel][mem] Clean up memory space of small memory management objects
* [kernel][kservice] Add memory application interface and thread protection interface
* [kernel][kservice] Fix function return value problem
* [kernel][memheap] Optimize memheaptrace print
* [kernel][memheap] Support best mode
* [kernel][memory] Remove semaphore lock
* [kernel][memheap] Add locked flag
* [kernel][memory] Support malloc memory in interrupt
* [kernel][memheap] Add 'memheapcheck' cmd
* [kernel][mem] Fix failure to request full memory
* [kernel][memheap] Fix compilation warning
* [kernel][mem] Fix mem realloc ASSERT
* [examples][testcases] Add small mem testcase
* [examples][mem_tc] Modify test memory size
* [examples][testcases] Add slab memory management algorithm test case
* [examples][testcases] fix small memory management algorithm test case
* [kernel][memory] Adjusting memory allocation algorithm object definition and interface
* [kernel][memory] Fix compilation warning
* [examples][utest] Fix mem test case
* [examples][utest] fix slab test case
* [utest][testcases] Shorten test time
* [kernel][memory] Formatting code
* [examples][utest] Adjust test run time
* [examples][utest] Formatting code
* [bsp] update all rtconfig.h
Diffstat (limited to 'src/mem.c')
| -rw-r--r-- | src/mem.c | 635 |
1 files changed, 289 insertions, 346 deletions
@@ -50,73 +50,40 @@ #include <rthw.h> #include <rtthread.h> -#ifndef RT_USING_MEMHEAP_AS_HEAP - -#define RT_MEM_STATS - -#if defined (RT_USING_HEAP) && defined (RT_USING_SMALL_MEM) -#ifdef RT_USING_HOOK -static void (*rt_malloc_hook)(void *ptr, rt_size_t size); -static void (*rt_free_hook)(void *ptr); - -/** - * @addtogroup Hook - */ - -/**@{*/ - -/** - * @brief This function will set a hook function, which will be invoked when a memory - * block is allocated from heap memory. - * - * @param hook the hook function. - */ -void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size)) -{ - rt_malloc_hook = hook; -} - -/** - * @brief This function will set a hook function, which will be invoked when a memory - * block is released to heap memory. - * - * @param hook the hook function - */ -void rt_free_sethook(void (*hook)(void *ptr)) -{ - rt_free_hook = hook; -} - -/**@}*/ - -#endif /* RT_USING_HOOK */ - -#define HEAP_MAGIC 0x1ea0 -struct heap_mem +#if defined (RT_USING_SMALL_MEM) + /** + * memory item on the small mem + */ +struct rt_small_mem_item { - /* magic and used flag */ - rt_uint16_t magic; - rt_uint16_t used; + rt_ubase_t pool_ptr; /**< small memory object addr */ #ifdef ARCH_CPU_64BIT - rt_uint32_t resv; + rt_uint32_t resv; #endif /* ARCH_CPU_64BIT */ - - rt_size_t next, prev; - + rt_size_t next; /**< next free item */ + rt_size_t prev; /**< prev free item */ #ifdef RT_USING_MEMTRACE #ifdef ARCH_CPU_64BIT - rt_uint8_t thread[8]; + rt_uint8_t thread[8]; /**< thread name */ #else - rt_uint8_t thread[4]; /* thread name */ + rt_uint8_t thread[4]; /**< thread name */ #endif /* ARCH_CPU_64BIT */ #endif /* RT_USING_MEMTRACE */ }; -/** pointer to the heap: for alignment, heap_ptr is now a pointer instead of an array */ -static rt_uint8_t *heap_ptr; +/** + * Base structure of small memory object + */ +struct rt_small_mem +{ + struct rt_memory parent; /**< inherit from rt_memory */ + rt_uint8_t *heap_ptr; /**< pointer to the heap */ + struct rt_small_mem_item *heap_end; + struct rt_small_mem_item *lfree; + rt_size_t mem_size_aligned; /**< aligned memory size */ +}; -/** the last entry, always unused! */ -static struct heap_mem *heap_end; +#define HEAP_MAGIC 0x1ea0 #ifdef ARCH_CPU_64BIT #define MIN_SIZE 24 @@ -124,20 +91,22 @@ static struct heap_mem *heap_end; #define MIN_SIZE 12 #endif /* ARCH_CPU_64BIT */ -#define MIN_SIZE_ALIGNED RT_ALIGN(MIN_SIZE, RT_ALIGN_SIZE) -#define SIZEOF_STRUCT_MEM RT_ALIGN(sizeof(struct heap_mem), RT_ALIGN_SIZE) +#define MEM_MASK 0xfffffffe +#define MEM_USED() ((((rt_base_t)(small_mem)) & MEM_MASK) | 0x1) +#define MEM_FREED() ((((rt_base_t)(small_mem)) & MEM_MASK) | 0x0) +#define MEM_ISUSED(_mem) \ + (((rt_base_t)(((struct rt_small_mem_item *)(_mem))->pool_ptr)) & (~MEM_MASK)) +#define MEM_POOL(_mem) \ + ((struct rt_small_mem *)(((rt_base_t)(((struct rt_small_mem_item *)(_mem))->pool_ptr)) & (MEM_MASK))) +#define MEM_SIZE(_heap, _mem) \ + (((struct rt_small_mem_item *)(_mem))->next - ((rt_ubase_t)(_mem) - \ + (rt_ubase_t)((_heap)->heap_ptr)) - RT_ALIGN(sizeof(struct rt_small_mem_item), RT_ALIGN_SIZE)) -static struct heap_mem *lfree; /* pointer to the lowest free block */ - -static struct rt_semaphore heap_sem; -static rt_size_t mem_size_aligned; - -#ifdef RT_MEM_STATS -static rt_size_t used_mem, max_mem; -#endif /* RT_MEM_STATS */ +#define MIN_SIZE_ALIGNED RT_ALIGN(MIN_SIZE, RT_ALIGN_SIZE) +#define SIZEOF_STRUCT_MEM RT_ALIGN(sizeof(struct rt_small_mem_item), RT_ALIGN_SIZE) #ifdef RT_USING_MEMTRACE -rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name) +rt_inline void rt_smem_setname(struct rt_small_mem_item *mem, const char *name) { int index; for (index = 0; index < sizeof(mem->thread); index ++) @@ -153,107 +122,144 @@ rt_inline void rt_mem_setname(struct heap_mem *mem, const char *name) } #endif /* RT_USING_MEMTRACE */ -static void plug_holes(struct heap_mem *mem) +static void plug_holes(struct rt_small_mem *m, struct rt_small_mem_item *mem) { - struct heap_mem *nmem; - struct heap_mem *pmem; + struct rt_small_mem_item *nmem; + struct rt_small_mem_item *pmem; - RT_ASSERT((rt_uint8_t *)mem >= heap_ptr); - RT_ASSERT((rt_uint8_t *)mem < (rt_uint8_t *)heap_end); - RT_ASSERT(mem->used == 0); + RT_ASSERT((rt_uint8_t *)mem >= m->heap_ptr); + RT_ASSERT((rt_uint8_t *)mem < (rt_uint8_t *)m->heap_end); /* plug hole forward */ - nmem = (struct heap_mem *)&heap_ptr[mem->next]; - if (mem != nmem && - nmem->used == 0 && - (rt_uint8_t *)nmem != (rt_uint8_t *)heap_end) + nmem = (struct rt_small_mem_item *)&m->heap_ptr[mem->next]; + if (mem != nmem && !MEM_ISUSED(nmem) && + (rt_uint8_t *)nmem != (rt_uint8_t *)m->heap_end) { - /* if mem->next is unused and not end of heap_ptr, + /* if mem->next is unused and not end of m->heap_ptr, * combine mem and mem->next */ - if (lfree == nmem) + if (m->lfree == nmem) { - lfree = mem; + m->lfree = mem; } + nmem->pool_ptr = 0; mem->next = nmem->next; - ((struct heap_mem *)&heap_ptr[nmem->next])->prev = (rt_uint8_t *)mem - heap_ptr; + ((struct rt_small_mem_item *)&m->heap_ptr[nmem->next])->prev = (rt_uint8_t *)mem - m->heap_ptr; } /* plug hole backward */ - pmem = (struct heap_mem *)&heap_ptr[mem->prev]; - if (pmem != mem && pmem->used == 0) + pmem = (struct rt_small_mem_item *)&m->heap_ptr[mem->prev]; + if (pmem != mem && !MEM_ISUSED(pmem)) { /* if mem->prev is unused, combine mem and mem->prev */ - if (lfree == mem) + if (m->lfree == mem) { - lfree = pmem; + m->lfree = pmem; } + mem->pool_ptr = 0; pmem->next = mem->next; - ((struct heap_mem *)&heap_ptr[mem->next])->prev = (rt_uint8_t *)pmem - heap_ptr; + ((struct rt_small_mem_item *)&m->heap_ptr[mem->next])->prev = (rt_uint8_t *)pmem - m->heap_ptr; } } /** - * @brief This function will initialize system heap memory. + * @brief This function will initialize small memory management algorithm. * - * @param begin_addr the beginning address of system heap memory. + * @param m the small memory management object. * - * @param end_addr the end address of system heap memory. + * @param name is the name of the small memory management object. + * + * @param begin_addr the beginning address of memory. + * + * @param size is the size of the memory. + * + * @return Return a pointer to the memory object. When the return value is RT_NULL, it means the init failed. */ -void rt_system_heap_init(void *begin_addr, void *end_addr) +rt_smem_t rt_smem_init(const char *name, + void *begin_addr, + rt_size_t size) { - struct heap_mem *mem; - rt_ubase_t begin_align = RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE); - rt_ubase_t end_align = RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_ALIGN_SIZE); + struct rt_small_mem_item *mem; + struct rt_small_mem *small_mem; + rt_ubase_t start_addr, begin_align, end_align, mem_size; - RT_DEBUG_NOT_IN_INTERRUPT; + small_mem = (struct rt_small_mem *)RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE); + start_addr = (rt_ubase_t)small_mem + sizeof(*small_mem); + begin_align = RT_ALIGN((rt_ubase_t)start_addr, RT_ALIGN_SIZE); + end_align = RT_ALIGN_DOWN((rt_ubase_t)begin_addr + size, RT_ALIGN_SIZE); /* alignment addr */ if ((end_align > (2 * SIZEOF_STRUCT_MEM)) && - ((end_align - 2 * SIZEOF_STRUCT_MEM) >= begin_align)) + ((end_align - 2 * SIZEOF_STRUCT_MEM) >= start_addr)) { /* calculate the aligned memory size */ - mem_size_aligned = end_align - begin_align - 2 * SIZEOF_STRUCT_MEM; + mem_size = end_align - begin_align - 2 * SIZEOF_STRUCT_MEM; } else { rt_kprintf("mem init, error begin address 0x%x, and end address 0x%x\n", - (rt_ubase_t)begin_addr, (rt_ubase_t)end_addr); + (rt_ubase_t)begin_addr, (rt_ubase_t)begin_addr + size); - return; + return RT_NULL; } + rt_memset(small_mem, 0, sizeof(*small_mem)); + /* initialize small memory object */ + rt_object_init(&(small_mem->parent.parent), RT_Object_Class_Memory, name); + small_mem->parent.algorithm = "small"; + small_mem->parent.address = begin_align; + small_mem->parent.total = mem_size; + small_mem->mem_size_aligned = mem_size; + /* point to begin address of heap */ - heap_ptr = (rt_uint8_t *)begin_align; + small_mem->heap_ptr = (rt_uint8_t *)begin_align; RT_DEBUG_LOG(RT_DEBUG_MEM, ("mem init, heap begin address 0x%x, size %d\n", - (rt_ubase_t)heap_ptr, mem_size_aligned)); + (rt_ubase_t)small_mem->heap_ptr, small_mem->mem_size_aligned)); /* initialize the start of the heap */ - mem = (struct heap_mem *)heap_ptr; - mem->magic = HEAP_MAGIC; - mem->next = mem_size_aligned + SIZEOF_STRUCT_MEM; + mem = (struct rt_small_mem_item *)small_mem->heap_ptr; + mem->pool_ptr = MEM_FREED(); + mem->next = small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM; mem->prev = 0; - mem->used = 0; #ifdef RT_USING_MEMTRACE - rt_mem_setname(mem, "INIT"); + rt_smem_setname(mem, "INIT"); #endif /* RT_USING_MEMTRACE */ /* initialize the end of the heap */ - heap_end = (struct heap_mem *)&heap_ptr[mem->next]; - heap_end->magic = HEAP_MAGIC; - heap_end->used = 1; - heap_end->next = mem_size_aligned + SIZEOF_STRUCT_MEM; - heap_end->prev = mem_size_aligned + SIZEOF_STRUCT_MEM; + small_mem->heap_end = (struct rt_small_mem_item *)&small_mem->heap_ptr[mem->next]; + small_mem->heap_end->pool_ptr = MEM_USED(); + small_mem->heap_end->next = small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM; + small_mem->heap_end->prev = small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM; #ifdef RT_USING_MEMTRACE - rt_mem_setname(heap_end, "INIT"); + rt_smem_setname(small_mem->heap_end, "INIT"); #endif /* RT_USING_MEMTRACE */ - rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO); - /* initialize the lowest-free pointer to the start of the heap */ - lfree = (struct heap_mem *)heap_ptr; + small_mem->lfree = (struct rt_small_mem_item *)small_mem->heap_ptr; + + return &small_mem->parent; } +RTM_EXPORT(rt_smem_init); + +/** + * @brief This function will remove a small mem from the system. + * + * @param m the small memory management object. + * + * @return RT_EOK + */ +rt_err_t rt_smem_detach(rt_smem_t m) +{ + RT_ASSERT(m != RT_NULL); + RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory); + RT_ASSERT(rt_object_is_systemobject(&m->parent)); + + rt_object_detach(&(m->parent)); + + return RT_EOK; +} +RTM_EXPORT(rt_smem_detach); /** * @addtogroup MM @@ -264,19 +270,24 @@ void rt_system_heap_init(void *begin_addr, void *end_addr) /** * @brief Allocate a block of memory with a minimum of 'size' bytes. * + * @param m the small memory management object. + * * @param size is the minimum size of the requested block in bytes. * * @return the pointer to allocated memory or NULL if no free memory was found. */ -void *rt_malloc(rt_size_t size) +void *rt_smem_alloc(rt_smem_t m, rt_size_t size) { rt_size_t ptr, ptr2; - struct heap_mem *mem, *mem2; + struct rt_small_mem_item *mem, *mem2; + struct rt_small_mem *small_mem; if (size == 0) return RT_NULL; - RT_DEBUG_NOT_IN_INTERRUPT; + RT_ASSERT(m != RT_NULL); + RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory); + RT_ASSERT(rt_object_is_systemobject(&m->parent)); if (size != RT_ALIGN(size, RT_ALIGN_SIZE)) RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d, but align to %d\n", @@ -284,10 +295,11 @@ void *rt_malloc(rt_size_t size) else RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d\n", size)); + small_mem = (struct rt_small_mem *)m; /* alignment size */ size = RT_ALIGN(size, RT_ALIGN_SIZE); - if (size > mem_size_aligned) + if (size > small_mem->mem_size_aligned) { RT_DEBUG_LOG(RT_DEBUG_MEM, ("no memory\n")); @@ -298,16 +310,13 @@ void *rt_malloc(rt_size_t size) if (size < MIN_SIZE_ALIGNED) size = MIN_SIZE_ALIGNED; - /* take memory semaphore */ - rt_sem_take(&heap_sem, RT_WAITING_FOREVER); - - for (ptr = (rt_uint8_t *)lfree - heap_ptr; - ptr < mem_size_aligned - size; - ptr = ((struct heap_mem *)&heap_ptr[ptr])->next) + for (ptr = (rt_uint8_t *)small_mem->lfree - small_mem->heap_ptr; + ptr <= small_mem->mem_size_aligned - size; + ptr = ((struct rt_small_mem_item *)&small_mem->heap_ptr[ptr])->next) { - mem = (struct heap_mem *)&heap_ptr[ptr]; + mem = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr]; - if ((!mem->used) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) + if ((!MEM_ISUSED(mem)) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { /* mem is not used and at least perfect fit is possible: * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ @@ -315,12 +324,12 @@ void *rt_malloc(rt_size_t size) if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { - /* (in addition to the above, we test if another struct heap_mem (SIZEOF_STRUCT_MEM) containing + /* (in addition to the above, we test if another struct rt_small_mem_item (SIZEOF_STRUCT_MEM) containing * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') * -> split large block, create empty remainder, * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, - * struct heap_mem would fit in but no data between mem2 and mem2->next + * struct rt_small_mem_item would fit in but no data between mem2 and mem2->next * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty * region that couldn't hold data, but when mem->next gets freed, * the 2 regions would be combined, resulting in more free memory @@ -328,28 +337,24 @@ void *rt_malloc(rt_size_t size) ptr2 = ptr + SIZEOF_STRUCT_MEM + size; /* create mem2 struct */ - mem2 = (struct heap_mem *)&heap_ptr[ptr2]; - mem2->magic = HEAP_MAGIC; - mem2->used = 0; + mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2]; + mem2->pool_ptr = MEM_FREED(); mem2->next = mem->next; mem2->prev = ptr; #ifdef RT_USING_MEMTRACE - rt_mem_setname(mem2, " "); + rt_smem_setname(mem2, " "); #endif /* RT_USING_MEMTRACE */ /* and insert it between mem and mem->next */ mem->next = ptr2; - mem->used = 1; - if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM) + if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM) { - ((struct heap_mem *)&heap_ptr[mem2->next])->prev = ptr2; + ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2; } -#ifdef RT_MEM_STATS - used_mem += (size + SIZEOF_STRUCT_MEM); - if (max_mem < used_mem) - max_mem = used_mem; -#endif /* RT_MEM_STATS */ + small_mem->parent.used += (size + SIZEOF_STRUCT_MEM); + if (small_mem->parent.max < small_mem->parent.used) + small_mem->parent.max = small_mem->parent.used; } else { @@ -360,76 +365,72 @@ void *rt_malloc(rt_size_t size) * also can't move mem->next directly behind mem, since mem->next * will always be used at this point! */ - mem->used = 1; -#ifdef RT_MEM_STATS - used_mem += mem->next - ((rt_uint8_t *)mem - heap_ptr); - if (max_mem < used_mem) - max_mem = used_mem; -#endif /* RT_MEM_STATS */ + small_mem->parent.used += mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr); + if (small_mem->parent.max < small_mem->parent.used) + small_mem->parent.max = small_mem->parent.used; } - /* set memory block magic */ - mem->magic = HEAP_MAGIC; + /* set small memory object */ + mem->pool_ptr = MEM_USED(); #ifdef RT_USING_MEMTRACE if (rt_thread_self()) - rt_mem_setname(mem, rt_thread_self()->name); + rt_smem_setname(mem, rt_thread_self()->name); else - rt_mem_setname(mem, "NONE"); + rt_smem_setname(mem, "NONE"); #endif /* RT_USING_MEMTRACE */ - if (mem == lfree) + if (mem == small_mem->lfree) { /* Find next free block after mem and update lowest free pointer */ - while (lfree->used && lfree != heap_end) - lfree = (struct heap_mem *)&heap_ptr[lfree->next]; + while (MEM_ISUSED(small_mem->lfree) && small_mem->lfree != small_mem->heap_end) + small_mem->lfree = (struct rt_small_mem_item *)&small_mem->heap_ptr[small_mem->lfree->next]; - RT_ASSERT(((lfree == heap_end) || (!lfree->used))); + RT_ASSERT(((small_mem->lfree == small_mem->heap_end) || (!MEM_ISUSED(small_mem->lfree)))); } - - rt_sem_release(&heap_sem); - RT_ASSERT((rt_ubase_t)mem + SIZEOF_STRUCT_MEM + size <= (rt_ubase_t)heap_end); + RT_ASSERT((rt_ubase_t)mem + SIZEOF_STRUCT_MEM + size <= (rt_ubase_t)small_mem->heap_end); RT_ASSERT((rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM) % RT_ALIGN_SIZE == 0); RT_ASSERT((((rt_ubase_t)mem) & (RT_ALIGN_SIZE - 1)) == 0); RT_DEBUG_LOG(RT_DEBUG_MEM, ("allocate memory at 0x%x, size: %d\n", (rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM), - (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - heap_ptr)))); - - RT_OBJECT_HOOK_CALL(rt_malloc_hook, - (((void *)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM)), size)); + (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr)))); /* return the memory data except mem struct */ return (rt_uint8_t *)mem + SIZEOF_STRUCT_MEM; } } - rt_sem_release(&heap_sem); - return RT_NULL; } -RTM_EXPORT(rt_malloc); +RTM_EXPORT(rt_smem_alloc); /** * @brief This function will change the size of previously allocated memory block. * - * @param rmem is the pointer to memory allocated by rt_malloc. + * @param m the small memory management object. + * + * @param rmem is the pointer to memory allocated by rt_mem_alloc. * * @param newsize is the required new size. * * @return the changed memory block address. */ -void *rt_realloc(void *rmem, rt_size_t newsize) +void *rt_smem_realloc(rt_smem_t m, void *rmem, rt_size_t newsize) { rt_size_t size; rt_size_t ptr, ptr2; - struct heap_mem *mem, *mem2; + struct rt_small_mem_item *mem, *mem2; + struct rt_small_mem *small_mem; void *nmem; - RT_DEBUG_NOT_IN_INTERRUPT; + RT_ASSERT(m != RT_NULL); + RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory); + RT_ASSERT(rt_object_is_systemobject(&m->parent)); + small_mem = (struct rt_small_mem *)m; /* alignment size */ newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE); - if (newsize > mem_size_aligned) + if (newsize > small_mem->mem_size_aligned) { RT_DEBUG_LOG(RT_DEBUG_MEM, ("realloc: out of memory\n")); @@ -437,243 +438,171 @@ void *rt_realloc(void *rmem, rt_size_t newsize) } else if (newsize == 0) { - rt_free(rmem); + rt_smem_free(rmem); return RT_NULL; } /* allocate a new memory block */ if (rmem == RT_NULL) - return rt_malloc(newsize); - - rt_sem_take(&heap_sem, RT_WAITING_FOREVER); + return rt_smem_alloc(&small_mem->parent, newsize); - if ((rt_uint8_t *)rmem < (rt_uint8_t *)heap_ptr || - (rt_uint8_t *)rmem >= (rt_uint8_t *)heap_end) - { - /* illegal memory */ - rt_sem_release(&heap_sem); - - return rmem; - } + RT_ASSERT((((rt_ubase_t)rmem) & (RT_ALIGN_SIZE - 1)) == 0); + RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)small_mem->heap_ptr); + RT_ASSERT((rt_uint8_t *)rmem < (rt_uint8_t *)small_mem->heap_end); - mem = (struct heap_mem *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM); + mem = (struct rt_small_mem_item *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM); - ptr = (rt_uint8_t *)mem - heap_ptr; + /* current memory block size */ + ptr = (rt_uint8_t *)mem - small_mem->heap_ptr; size = mem->next - ptr - SIZEOF_STRUCT_MEM; if (size == newsize) { /* the size is the same as */ - rt_sem_release(&heap_sem); - return rmem; } if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) { /* split memory block */ -#ifdef RT_MEM_STATS - used_mem -= (size - newsize); -#endif /* RT_MEM_STATS */ + small_mem->parent.used -= (size - newsize); ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - mem2 = (struct heap_mem *)&heap_ptr[ptr2]; - mem2->magic = HEAP_MAGIC; - mem2->used = 0; + mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2]; + mem2->pool_ptr = MEM_FREED(); mem2->next = mem->next; mem2->prev = ptr; #ifdef RT_USING_MEMTRACE - rt_mem_setname(mem2, " "); + rt_smem_setname(mem2, " "); #endif /* RT_USING_MEMTRACE */ mem->next = ptr2; - if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM) + if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM) { - ((struct heap_mem *)&heap_ptr[mem2->next])->prev = ptr2; + ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2; } - if (mem2 < lfree) + if (mem2 < small_mem->lfree) { /* the splited struct is now the lowest */ - lfree = mem2; + small_mem->lfree = mem2; } - plug_holes(mem2); - - rt_sem_release(&heap_sem); + plug_holes(small_mem, mem2); return rmem; } - rt_sem_release(&heap_sem); /* expand memory */ - nmem = rt_malloc(newsize); + nmem = rt_smem_alloc(&small_mem->parent, newsize); if (nmem != RT_NULL) /* check memory */ { rt_memcpy(nmem, rmem, size < newsize ? size : newsize); - rt_free(rmem); + rt_smem_free(rmem); } return nmem; } -RTM_EXPORT(rt_realloc); - -/** - * @brief This function will contiguously allocate enough space for count objects - * that are size bytes of memory each and returns a pointer to the allocated - * memory. - * - * @note The allocated memory is filled with bytes of value zero. - * - * @param count is the number of objects to allocate. - * - * @param size is the size of one object to allocate. - * - * @return pointer to allocated memory / NULL pointer if there is an error. - */ -void *rt_calloc(rt_size_t count, rt_size_t size) -{ - void *p; - - /* allocate 'count' objects of size 'size' */ - p = rt_malloc(count * size); - - /* zero the memory */ - if (p) - rt_memset(p, 0, count * size); - - return p; -} -RTM_EXPORT(rt_calloc); +RTM_EXPORT(rt_smem_realloc); /** * @brief This function will release the previously allocated memory block by - * rt_malloc. The released memory block is taken back to system heap. + * rt_mem_alloc. The released memory block is taken back to system heap. * * @param rmem the address of memory which will be released. */ -void rt_free(void *rmem) +void rt_smem_free(void *rmem) { - struct heap_mem *mem; + struct rt_small_mem_item *mem; + struct rt_small_mem *small_mem; if (rmem == RT_NULL) return; - RT_DEBUG_NOT_IN_INTERRUPT; - RT_ASSERT((((rt_ubase_t)rmem) & (RT_ALIGN_SIZE - 1)) == 0); - RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)heap_ptr && - (rt_uint8_t *)rmem < (rt_uint8_t *)heap_end); - - RT_OBJECT_HOOK_CALL(rt_free_hook, (rmem)); - - if ((rt_uint8_t *)rmem < (rt_uint8_t *)heap_ptr || - (rt_uint8_t *)rmem >= (rt_uint8_t *)heap_end) - { - RT_DEBUG_LOG(RT_DEBUG_MEM, ("illegal memory\n")); - return; - } - - /* Get the corresponding struct heap_mem ... */ - mem = (struct heap_mem *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM); + /* Get the corresponding struct rt_small_mem_item ... */ + mem = (struct rt_small_mem_item *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM); RT_DEBUG_LOG(RT_DEBUG_MEM, ("release memory 0x%x, size: %d\n", (rt_ubase_t)rmem, - (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - heap_ptr)))); - - - /* protect the heap from concurrent access */ - rt_sem_take(&heap_sem, RT_WAITING_FOREVER); + (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr)))); /* ... 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); + small_mem = MEM_POOL(mem); + RT_ASSERT(small_mem != RT_NULL); + RT_ASSERT(MEM_ISUSED(mem)); + RT_ASSERT(rt_object_get_type(&small_mem->parent.parent) == RT_Object_Class_Memory); + RT_ASSERT(rt_object_is_systemobject(&small_mem->parent.parent)); + RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)small_mem->heap_ptr && + (rt_uint8_t *)rmem < (rt_uint8_t *)small_mem->heap_end); + RT_ASSERT(MEM_POOL(&small_mem->heap_ptr[mem->next]) == small_mem); + /* ... and is now unused. */ - mem->used = 0; - mem->magic = HEAP_MAGIC; + mem->pool_ptr = MEM_FREED(); #ifdef RT_USING_MEMTRACE - rt_mem_setname(mem, " "); + rt_smem_setname(mem, " "); #endif /* RT_USING_MEMTRACE */ - if (mem < lfree) + if (mem < small_mem->lfree) { /* the newly freed struct is now the lowest */ - lfree = mem; + small_mem->lfree = mem; } -#ifdef RT_MEM_STATS - used_mem -= (mem->next - ((rt_uint8_t *)mem - heap_ptr)); -#endif /* RT_MEM_STATS */ + small_mem->parent.used -= (mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr)); /* finally, see if prev or next are free also */ - plug_holes(mem); - rt_sem_release(&heap_sem); -} -RTM_EXPORT(rt_free); - -#ifdef RT_MEM_STATS -/** -* @brief This function will caculate the total memory, the used memory, and -* the max used memory. -* -* @param total is a pointer to get the total size of the memory. -* -* @param used is a pointer to get the size of memory used. -* -* @param max_used is a pointer to get the maximum memory used. -*/ -void rt_memory_info(rt_uint32_t *total, - rt_uint32_t *used, - rt_uint32_t *max_used) -{ - if (total != RT_NULL) - *total = mem_size_aligned; - if (used != RT_NULL) - *used = used_mem; - if (max_used != RT_NULL) - *max_used = max_mem; + plug_holes(small_mem, mem); } +RTM_EXPORT(rt_smem_free); #ifdef RT_USING_FINSH #include <finsh.h> -void list_mem(void) -{ - rt_kprintf("total memory: %d\n", mem_size_aligned); - rt_kprintf("used memory : %d\n", used_mem); - rt_kprintf("maximum allocated memory: %d\n", max_mem); -} -FINSH_FUNCTION_EXPORT(list_mem, list memory usage information) - #ifdef RT_USING_MEMTRACE -int memcheck(void) +int memcheck(int argc, char *argv[]) { int position; rt_ubase_t level; - struct heap_mem *mem; + struct rt_small_mem_item *mem; + struct rt_small_mem *m; + struct rt_object_information *information; + struct rt_list_node *node; + struct rt_object *object; + char *name; + + name = argc > 1 ? argv[1] : RT_NULL; level = rt_hw_interrupt_disable(); - for (mem = (struct heap_mem *)heap_ptr; mem != heap_end; mem = (struct heap_mem *)&heap_ptr[mem->next]) + /* get mem object */ + information = rt_object_get_information(RT_Object_Class_Memory); + for (node = information->object_list.next; + node != &(information->object_list); + node = node->next) { - position = (rt_ubase_t)mem - (rt_ubase_t)heap_ptr; - if (position < 0) goto __exit; - if (position > (int)mem_size_aligned) goto __exit; - if (mem->magic != HEAP_MAGIC) goto __exit; - if (mem->used != 0 && mem->used != 1) goto __exit; + object = rt_list_entry(node, struct rt_object, list); + /* find the specified object */ + if (name != RT_NULL && rt_strncmp(name, object->name, RT_NAME_MAX) != 0) + continue; + /* mem object */ + m = (struct rt_small_mem *)object; + /* check mem */ + for (mem = (struct rt_small_mem_item *)m->heap_ptr; mem != m->heap_end; mem = (struct rt_small_mem_item *)&m->heap_ptr[mem->next]) + { + position = (rt_ubase_t)mem - (rt_ubase_t)m->heap_ptr; + if (position < 0) goto __exit; + if (position > (int)m->mem_size_aligned) goto __exit; + if (MEM_POOL(mem) != m) goto __exit; + } } rt_hw_interrupt_enable(level); return 0; __exit: rt_kprintf("Memory block wrong:\n"); + rt_kprintf(" name: %s\n", m->parent.parent.name); 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_kprintf(" pool: 0x%04x\n", mem->pool_ptr); + rt_kprintf(" size: %d\n", mem->next - position - SIZEOF_STRUCT_MEM); rt_hw_interrupt_enable(level); return 0; @@ -682,47 +611,61 @@ MSH_CMD_EXPORT(memcheck, check memory data); int memtrace(int argc, char **argv) { - struct heap_mem *mem; + struct rt_small_mem_item *mem; + struct rt_small_mem *m; + struct rt_object_information *information; + struct rt_list_node *node; + struct rt_object *object; + char *name; - 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]) + name = argc > 1 ? argv[1] : RT_NULL; + /* get mem object */ + information = rt_object_get_information(RT_Object_Class_Memory); + for (node = information->object_list.next; + node != &(information->object_list); + node = node->next) { - int position = (rt_ubase_t)mem - (rt_ubase_t)heap_ptr; - int size; - - rt_kprintf("[0x%08x - ", mem); + object = rt_list_entry(node, struct rt_object, list); + /* find the specified object */ + if (name != RT_NULL && rt_strncmp(name, object->name, RT_NAME_MAX) != 0) + continue; + /* mem object */ + m = (struct rt_small_mem *)object; + /* show memory information */ + rt_kprintf("\nmemory heap address:\n"); + rt_kprintf("name : %s\n", m->parent.parent.name); + rt_kprintf("total : 0x%d\n", m->parent.total); + rt_kprintf("used : 0x%d\n", m->parent.used); + rt_kprintf("max_used: 0x%d\n", m->parent.max); + rt_kprintf("heap_ptr: 0x%08x\n", m->heap_ptr); + rt_kprintf("lfree : 0x%08x\n", m->lfree); + rt_kprintf("heap_end: 0x%08x\n", m->heap_end); + rt_kprintf("\n--memory item information --\n"); + for (mem = (struct rt_small_mem_item *)m->heap_ptr; mem != m->heap_end; mem = (struct rt_small_mem_item *)&m->heap_ptr[mem->next]) + { + int size = MEM_SIZE(m, 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("[0x%08x - ", 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"); + rt_kprintf("] %c%c%c%c", mem->thread[0], mem->thread[1], mem->thread[2], mem->thread[3]); + if (MEM_POOL(mem) != m) + rt_kprintf(": ***\n"); + else + rt_kprintf("\n"); + } } - return 0; } MSH_CMD_EXPORT(memtrace, dump memory trace information); #endif /* RT_USING_MEMTRACE */ #endif /* RT_USING_FINSH */ -#endif /* defined (RT_USING_HEAP) && defined (RT_USING_SMALL_MEM) */ +#endif /* defined (RT_USING_SMALL_MEM) */ /**@}*/ - -#endif /* RT_MEM_STATS */ -#endif /* RT_USING_MEMHEAP_AS_HEAP */ |
