summaryrefslogtreecommitdiff
path: root/src/mem.c
diff options
context:
space:
mode:
authorTangyuxin <[email protected]>2021-12-16 16:23:58 +0800
committerGitHub <[email protected]>2021-12-16 16:23:58 +0800
commitd724eed9fc09269c3c6e921c1f8b2df573508419 (patch)
tree92f8528e0efbe28d4632692896d0bcaa2e45b3b6 /src/mem.c
parent874f6c84f19f8ca24ebd00a9a95e7af02afc49a0 (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.c635
1 files changed, 289 insertions, 346 deletions
diff --git a/src/mem.c b/src/mem.c
index 3c0816748e..f1e1eeba55 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -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 */