summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/Kconfig76
-rw-r--r--src/SConscript9
-rw-r--r--src/kservice.c313
-rw-r--r--src/mem.c635
-rw-r--r--src/memheap.c636
-rw-r--r--src/object.c7
-rw-r--r--src/slab.c597
7 files changed, 1157 insertions, 1116 deletions
diff --git a/src/Kconfig b/src/Kconfig
index 8647d35698..2bc37cf451 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -284,36 +284,67 @@ menu "Memory Management"
help
Using static memory fixed partition
+ config RT_USING_SMALL_MEM
+ bool "Using Small Memory Algorithm"
+ default n
+ help
+ Using Small Memory Algorithm
+
+ config RT_USING_SLAB
+ bool "Using SLAB Memory Algorithm"
+ default n
+ help
+ The slab allocator of RT-Thread is a memory allocation algorithm
+ optimizedfor embedded systems based on the slab allocator
+ implemented by Matthew Dillon, founder of dragonfly BSD.
+ The original slab algorithm is an efficient kernel memory
+ allocation algorithm introduced by Jeff bonwick for
+ Solaris Operating System.
+
menuconfig RT_USING_MEMHEAP
- bool "Using memory heap object"
+ bool "Using memheap Memory Algorithm"
default n
if RT_USING_MEMHEAP
+ choice
+ prompt "Memheap memory allocation mode"
+ default RT_MEMHEAP_FAST_MODE
- if RT_USING_MEMHEAP_AS_HEAP
- config RT_USING_MEMHEAP_AUTO_BINDING
- bool "Use all of memheap objects as heap"
- default y
- endif
+ config RT_MEMHEAP_FAST_MODE
+ bool "fast mode"
+ help
+ Speed priority mode.
+ As long as the memory block size meets the requirements, the search ends immediately.
+
+ config RT_MEMHEAP_BSET_MODE
+ bool "best mode"
+ help
+ Best size first.
+ The search does not end until the memory block of the most appropriate size is found
+ endchoice
endif
choice
- prompt "Dynamic Memory Management"
- default RT_USING_SMALL_MEM
+ prompt "System Heap Memory Management"
+ default RT_USING_SMALL_MEM_AS_HEAP
- config RT_USING_NOHEAP
- bool "Disable Heap"
-
- config RT_USING_SMALL_MEM
+ config RT_USING_SMALL_MEM_AS_HEAP
bool "Small Memory Algorithm"
+ select RT_USING_SMALL_MEM
- config RT_USING_SLAB
- bool "SLAB Algorithm for large memory"
-
- if RT_USING_MEMHEAP
config RT_USING_MEMHEAP_AS_HEAP
bool "Use memheap objects as heap"
- endif
+ select RT_USING_MEMHEAP
+
+ if RT_USING_MEMHEAP_AS_HEAP
+ config RT_USING_MEMHEAP_AUTO_BINDING
+ bool "Use all of memheap objects as heap"
+ default y
+ endif
+
+ config RT_USING_SLAB_AS_HEAP
+ bool "SLAB Algorithm for large memory"
+ select RT_USING_SLAB
config RT_USING_USERHEAP
bool "Use user heap"
@@ -322,10 +353,11 @@ menu "Memory Management"
rt_malloc(), rt_malloc_sethook()
rt_free(), rt_free_sethook()
rt_calloc(), rt_realloc()
+ rt_memory_info()
rt_system_heap_init()
- And if FinSH is used at the same time, please implement list_mem()
-
+ config RT_USING_NOHEAP
+ bool "Disable Heap"
endchoice
config RT_USING_MEMTRACE
@@ -342,6 +374,12 @@ menu "Memory Management"
to check memory block to find which thread has wrongly modified
memory.
+ config RT_USING_HEAP_ISR
+ bool "Using heap in ISR"
+ default n
+ help
+ When this option is enabled, the critical zone will be protected with disable interrupt.
+
config RT_USING_HEAP
bool
default n if RT_USING_NOHEAP
diff --git a/src/SConscript b/src/SConscript
index 68523978d6..3f014551f0 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -6,10 +6,10 @@ src = Glob('*.c')
CPPPATH = [RTT_ROOT + '/include']
-if GetDepend('RT_USING_HEAP') == False or GetDepend('RT_USING_SMALL_MEM') == False:
+if GetDepend('RT_USING_SMALL_MEM') == False:
SrcRemove(src, ['mem.c'])
-if GetDepend('RT_USING_HEAP') == False or GetDepend('RT_USING_SLAB') == False:
+if GetDepend('RT_USING_SLAB') == False:
SrcRemove(src, ['slab.c'])
if GetDepend('RT_USING_MEMPOOL') == False:
@@ -17,11 +17,6 @@ if GetDepend('RT_USING_MEMPOOL') == False:
if GetDepend('RT_USING_MEMHEAP') == False:
SrcRemove(src, ['memheap.c'])
- if GetDepend('RT_USING_MEMHEAP_AS_HEAP'):
- SrcRemove(src, ['mem.c'])
-
-if GetDepend('RT_USING_USERHEAP'):
- SrcRemove(src, ['mem.c', 'slab.c'])
if GetDepend('RT_USING_SIGNALS') == False:
SrcRemove(src, ['signal.c'])
diff --git a/src/kservice.c b/src/kservice.c
index 8b959cbd68..5d4311507d 100644
--- a/src/kservice.c
+++ b/src/kservice.c
@@ -1276,7 +1276,318 @@ RT_WEAK int rt_kprintf(const char *fmt, ...)
RTM_EXPORT(rt_kprintf);
#endif /* RT_USING_CONSOLE */
-#ifdef RT_USING_HEAP
+#if defined(RT_USING_HEAP) && !defined(RT_USING_USERHEAP)
+#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 */
+
+#if defined(RT_USING_HEAP_ISR)
+#elif defined(RT_USING_MUTEX)
+static struct rt_mutex _lock;
+#endif
+
+rt_inline void _heap_lock_init(void)
+{
+#if defined(RT_USING_HEAP_ISR)
+#elif defined(RT_USING_MUTEX)
+ rt_mutex_init(&_lock, "heap", RT_IPC_FLAG_PRIO);
+#endif
+}
+
+rt_inline rt_base_t _heap_lock(void)
+{
+#if defined(RT_USING_HEAP_ISR)
+ return rt_hw_interrupt_disable();
+#elif defined(RT_USING_MUTEX)
+ if (rt_thread_self())
+ return rt_mutex_take(&_lock, RT_WAITING_FOREVER);
+ else
+ return RT_EOK;
+#else
+ rt_enter_critical();
+ return RT_EOK;
+#endif
+}
+
+rt_inline void _heap_unlock(rt_base_t level)
+{
+#if defined(RT_USING_HEAP_ISR)
+ rt_hw_interrupt_enable(level);
+#elif defined(RT_USING_MUTEX)
+ RT_ASSERT(level == RT_EOK);
+ if (rt_thread_self())
+ rt_mutex_release(&_lock);
+#else
+ rt_exit_critical();
+#endif
+}
+
+#if defined(RT_USING_SMALL_MEM_AS_HEAP)
+static rt_smem_t system_heap;
+rt_inline void _smem_info(rt_uint32_t *total,
+ rt_uint32_t *used, rt_uint32_t *max_used)
+{
+ if (total)
+ *total = system_heap->total;
+ if (used)
+ *used = system_heap->used;
+ if (max_used)
+ *max_used = system_heap->max;
+}
+#define _MEM_INIT(_name, _start, _size) \
+ system_heap = rt_smem_init(_name, _start, _size)
+#define _MEM_MALLOC(_size) \
+ rt_smem_alloc(system_heap, _size)
+#define _MEM_REALLOC(_ptr, _newsize)\
+ rt_smem_realloc(system_heap, _ptr, _newsize)
+#define _MEM_FREE(_ptr) \
+ rt_smem_free(_ptr)
+#define _MEM_INFO(_total, _used, _max) \
+ _smem_info(_total, _used, _max)
+#elif defined(RT_USING_MEMHEAP_AS_HEAP)
+static struct rt_memheap system_heap;
+void *_memheap_alloc(struct rt_memheap *heap, rt_size_t size);
+void _memheap_free(void *rmem);
+void *_memheap_realloc(struct rt_memheap *heap, void *rmem, rt_size_t newsize);
+#define _MEM_INIT(_name, _start, _size) \
+ rt_memheap_init(&system_heap, _name, _start, _size)
+#define _MEM_MALLOC(_size) \
+ _memheap_alloc(&system_heap, _size)
+#define _MEM_REALLOC(_ptr, _newsize) \
+ _memheap_realloc(&system_heap, _ptr, _newsize)
+#define _MEM_FREE(_ptr) \
+ _memheap_free(_ptr)
+#define _MEM_INFO(_total, _used, _max) \
+ rt_memheap_info(&system_heap, _total, _used, _max)
+#elif defined(RT_USING_SLAB_AS_HEAP)
+static rt_slab_t system_heap;
+rt_inline void _slab_info(rt_uint32_t *total,
+ rt_uint32_t *used, rt_uint32_t *max_used)
+{
+ if (total)
+ *total = system_heap->total;
+ if (used)
+ *used = system_heap->used;
+ if (max_used)
+ *max_used = system_heap->max;
+}
+#define _MEM_INIT(_name, _start, _size) \
+ system_heap = rt_slab_init(_name, _start, _size)
+#define _MEM_MALLOC(_size) \
+ rt_slab_alloc(system_heap, _size)
+#define _MEM_REALLOC(_ptr, _newsize) \
+ rt_slab_realloc(system_heap, _ptr, _newsize)
+#define _MEM_FREE(_ptr) \
+ rt_slab_free(system_heap, _ptr)
+#define _MEM_INFO _slab_info
+#else
+#define _MEM_INIT(...)
+#define _MEM_MALLOC(...) RT_NULL
+#define _MEM_REALLOC(...) RT_NULL
+#define _MEM_FREE(...)
+#define _MEM_INFO(...)
+#endif
+
+/**
+ * @brief This function will init system heap.
+ *
+ * @param begin_addr the beginning address of system page.
+ *
+ * @param end_addr the end address of system page.
+ */
+RT_WEAK void rt_system_heap_init(void *begin_addr, void *end_addr)
+{
+ 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);
+
+ RT_ASSERT(end_align > begin_align);
+
+ /* Initialize system memory heap */
+ _MEM_INIT("heap", begin_addr, end_align - begin_align);
+ /* Initialize multi thread contention lock */
+ _heap_lock_init();
+}
+
+/**
+ * @brief Allocate a block of memory with a minimum of 'size' bytes.
+ *
+ * @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.
+ */
+RT_WEAK void *rt_malloc(rt_size_t size)
+{
+ rt_base_t level;
+ void *ptr;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* allocate memory block from system heap */
+ ptr = _MEM_MALLOC(size);
+ /* Exit critical zone */
+ _heap_unlock(level);
+ /* call 'rt_malloc' hook */
+ RT_OBJECT_HOOK_CALL(rt_malloc_hook, (ptr, size));
+ return ptr;
+}
+RTM_EXPORT(rt_malloc);
+
+/**
+ * @brief This function will change the size of previously allocated memory block.
+ *
+ * @param rmem is the pointer to memory allocated by rt_malloc.
+ *
+ * @param newsize is the required new size.
+ *
+ * @return the changed memory block address.
+ */
+RT_WEAK void *rt_realloc(void *rmem, rt_size_t newsize)
+{
+ rt_base_t level;
+ void *nptr;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* Change the size of previously allocated memory block */
+ nptr = _MEM_REALLOC(rmem, newsize);
+ /* Exit critical zone */
+ _heap_unlock(level);
+ return nptr;
+}
+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.
+ */
+RT_WEAK 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);
+
+/**
+ * @brief This function will release the previously allocated memory block by
+ * rt_malloc. The released memory block is taken back to system heap.
+ *
+ * @param rmem the address of memory which will be released.
+ */
+RT_WEAK void rt_free(void *rmem)
+{
+ rt_base_t level;
+
+ /* call 'rt_free' hook */
+ RT_OBJECT_HOOK_CALL(rt_free_hook, (rmem));
+ /* Enter critical zone */
+ level = _heap_lock();
+ _MEM_FREE(rmem);
+ /* Exit critical zone */
+ _heap_unlock(level);
+}
+RTM_EXPORT(rt_free);
+
+/**
+* @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.
+*/
+RT_WEAK void rt_memory_info(rt_uint32_t *total,
+ rt_uint32_t *used,
+ rt_uint32_t *max_used)
+{
+ rt_base_t level;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ _MEM_INFO(total, used, max_used);
+ /* Exit critical zone */
+ _heap_unlock(level);
+}
+RTM_EXPORT(rt_memory_info);
+
+#if defined(RT_USING_SLAB) && defined(RT_USING_SLAB_AS_HEAP)
+void *rt_page_alloc(rt_size_t npages)
+{
+ rt_base_t level;
+ void *ptr;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* alloc page */
+ ptr = rt_slab_page_alloc(system_heap, npages);
+ /* Exit critical zone */
+ _heap_unlock(level);
+ return ptr;
+}
+
+void rt_page_free(void *addr, rt_size_t npages)
+{
+ rt_base_t level;
+
+ /* Enter critical zone */
+ level = _heap_lock();
+ /* free page */
+ rt_slab_page_free(system_heap, addr, npages);
+ /* Exit critical zone */
+ _heap_unlock(level);
+}
+#endif
+
/**
* This function allocates a memory block, which address is aligned to the
* specified alignment size.
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 */
diff --git a/src/memheap.c b/src/memheap.c
index e96b402bcf..62b42f73ed 100644
--- a/src/memheap.c
+++ b/src/memheap.c
@@ -38,58 +38,6 @@
#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
-/**
- * @brief This function will set a new name for memheap.
- *
- * @param item is a pointer point to a memheap object.
- *
- * @param name is the new name to be set.
- */
-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';
- }
-}
-
-/**
- * @brief This function will set a new name for memheap.
- *
- * @param ptr is a pointer point to a memheap object.
- *
- * @param name is the new name to be set.
- */
-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 /* RT_USING_MEMTRACE */
-
/**
* @brief This function initializes a piece of memory called memheap.
*
@@ -182,6 +130,7 @@ rt_err_t rt_memheap_init(struct rt_memheap *memheap,
/* initialize semaphore lock */
rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_PRIO);
+ memheap->locked = RT_FALSE;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n",
@@ -244,12 +193,15 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
free_size = 0;
/* lock memheap */
- result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
- if (result != RT_EOK)
+ if (heap->locked == RT_FALSE)
{
- rt_set_errno(result);
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
- return RT_NULL;
+ return RT_NULL;
+ }
}
/* get the first free memory block */
@@ -354,8 +306,11 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
rt_memcpy(header_ptr->owner_thread_name, "NONE", sizeof(header_ptr->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
- /* release lock */
- rt_sem_release(&(heap->lock));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
/* Return a memory address to the caller. */
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
@@ -367,8 +322,11 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE);
}
- /* release lock */
- rt_sem_release(&(heap->lock));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
}
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed\n"));
@@ -427,12 +385,15 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
/* Fix the crash problem after opening Oz optimization on ac6 */
volatile struct rt_memheap_item *next_ptr;
- /* lock memheap */
- result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
- if (result != RT_EOK)
+ if (heap->locked == RT_FALSE)
{
- rt_set_errno(result);
- return RT_NULL;
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
+ return RT_NULL;
+ }
}
next_ptr = header_ptr->next;
@@ -508,16 +469,21 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x",
next_ptr->next_free,
next_ptr->prev_free));
-
- /* release lock */
- rt_sem_release(&(heap->lock));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
return ptr;
}
}
- /* release lock */
- rt_sem_release(&(heap->lock));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
/* re-allocate a memory block */
new_ptr = (void *)rt_memheap_alloc(heap, newsize);
@@ -534,13 +500,16 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
if (newsize + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC >= oldsize)
return ptr;
- /* lock memheap */
- result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
- if (result != RT_EOK)
+ if (heap->locked == RT_FALSE)
{
- rt_set_errno(result);
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
- return RT_NULL;
+ return RT_NULL;
+ }
}
/* split the block. */
@@ -602,8 +571,11 @@ void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
/* increment the available byte count. */
heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr);
- /* release lock */
- rt_sem_release(&(heap->lock));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
/* return the old memory block */
return ptr;
@@ -636,14 +608,15 @@ void rt_memheap_free(void *ptr)
ptr, header_ptr));
/* check magic */
- if (header_ptr->magic != (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED))
+ if (header_ptr->magic != (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED) ||
+ (header_ptr->next->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
{
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);
}
- 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);
/* get pool ptr */
heap = header_ptr->pool_ptr;
@@ -651,13 +624,16 @@ void rt_memheap_free(void *ptr)
RT_ASSERT(heap);
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
- /* lock memheap */
- result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
- if (result != RT_EOK)
+ if (heap->locked == RT_FALSE)
{
- rt_set_errno(result);
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
+ {
+ rt_set_errno(result);
- return ;
+ return ;
+ }
}
/* Mark the memory as available. */
@@ -707,11 +683,23 @@ void rt_memheap_free(void *ptr)
if (insert_header)
{
+ struct rt_memheap_item *n = heap->free_list->next_free;;
+#if defined(RT_MEMHEAP_BSET_MODE)
+ rt_uint32_t blk_size = MEMITEM_SIZE(header_ptr);
+ for (;n != heap->free_list; n = n->next_free)
+ {
+ rt_uint32_t m = MEMITEM_SIZE(n);
+ if (blk_size <= m)
+ {
+ break;
+ }
+ }
+#endif
/* no left merge, insert to free list */
- header_ptr->next_free = heap->free_list->next_free;
- header_ptr->prev_free = heap->free_list;
- heap->free_list->next_free->prev_free = header_ptr;
- heap->free_list->next_free = header_ptr;
+ header_ptr->next_free = n;
+ header_ptr->prev_free = n->prev_free;
+ n->prev_free->next_free = header_ptr;
+ n->prev_free = header_ptr;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("insert to free list: next_free 0x%08x, prev_free 0x%08x\n",
@@ -722,149 +710,77 @@ void rt_memheap_free(void *ptr)
rt_memset(header_ptr->owner_thread_name, ' ', sizeof(header_ptr->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
- /* release lock */
- rt_sem_release(&(heap->lock));
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
+ }
}
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);
-}
/**
- * @brief This function will print the memheap infomation.
- *
- * @param heap is the pointer to the memheap to get information.
- *
- * @return 0
- */
-int rt_memheap_dump(struct rt_memheap *heap)
+* @brief This function will caculate the total memory, the used memory, and
+* the max used memory.
+*
+* @param heap is a pointer to the memheap object, which will reallocate
+* memory from the block
+*
+* @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_memheap_info(struct rt_memheap *heap,
+ rt_uint32_t *total,
+ rt_uint32_t *used,
+ rt_uint32_t *max_used)
{
- 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);
+ rt_err_t result;
- /* for each memory block */
- while ((rt_ubase_t)item < ((rt_ubase_t)end))
+ if (heap->locked == RT_FALSE)
{
- 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
+ /* lock memheap */
+ result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+ if (result != RT_EOK)
{
- rt_kprintf("0x%08x: %-8d <F>\n", item + 1, MEMITEM_SIZE(item));
+ rt_set_errno(result);
+ return;
}
-
- 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 (total != RT_NULL)
+ *total = heap->pool_size;
- if (count > 0)
- {
- int index;
-#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
- extern int list_memheap(void);
-#endif
+ if (used != RT_NULL)
+ *used = heap->pool_size - heap->available_size;
- heaps = (struct rt_memheap **)rt_malloc(sizeof(struct rt_memheap *) * count);
- if (heaps == RT_NULL) return 0;
-#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
- list_memheap();
-#endif
- 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]);
- }
+ if (max_used != RT_NULL)
+ *max_used = heap->max_used_size;
- rt_free(heaps);
+ if (heap->locked == RT_FALSE)
+ {
+ /* release lock */
+ rt_sem_release(&(heap->lock));
}
-
- return 0;
}
-MSH_CMD_EXPORT(memheaptrace, dump memory trace information);
-#endif /* RT_USING_FINSH */
#ifdef RT_USING_MEMHEAP_AS_HEAP
-static struct rt_memheap _heap;
-
-/**
- * @brief This function initializes a heap for system.
- *
- * @param begin_addr is the start address of the memory.
- *
- * @param end_addr is the end address of the memory.
- */
-void rt_system_heap_init(void *begin_addr, void *end_addr)
-{
- RT_ASSERT((rt_size_t)end_addr > (rt_size_t)begin_addr);
-
- rt_size_t begin_align = RT_ALIGN((rt_size_t)begin_addr, RT_ALIGN_SIZE);
- rt_size_t end_align = RT_ALIGN_DOWN((rt_size_t)end_addr, RT_ALIGN_SIZE);
-
- /* initialize a default heap in the system */
- rt_memheap_init(&_heap,
- "heap",
- (void *)begin_align,
- end_align - begin_align);
-}
-
-/**
- * @brief Allocate a block of memory with a minimum of 'size' bytes.
- *
- * @param size is the minimum size of the requested block in bytes.
- */
-void *rt_malloc(rt_size_t size)
+/*
+ * rt_malloc port function
+*/
+void *_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
{
void *ptr;
- /* zero size, return RT_NULL */
- if (size == 0)
- return RT_NULL;
-
/* try to allocate in system heap */
- ptr = rt_memheap_alloc(&_heap, size);
+ ptr = rt_memheap_alloc(heap, size);
#ifdef RT_USING_MEMHEAP_AUTO_BINDING
if (ptr == RT_NULL)
{
struct rt_object *object;
struct rt_list_node *node;
- struct rt_memheap *heap;
+ struct rt_memheap *_heap;
struct rt_object_information *information;
/* try to allocate on other memory heap */
@@ -875,75 +791,43 @@ void *rt_malloc(rt_size_t size)
node = node->next)
{
object = rt_list_entry(node, struct rt_object, list);
- heap = (struct rt_memheap *)object;
-
- RT_ASSERT(heap);
- RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
+ _heap = (struct rt_memheap *)object;
/* not allocate in the default system heap */
- if (heap == &_heap)
+ if (heap == _heap)
continue;
- ptr = rt_memheap_alloc(heap, size);
+ ptr = rt_memheap_alloc(_heap, size);
if (ptr != RT_NULL)
break;
}
}
#endif /* RT_USING_MEMHEAP_AUTO_BINDING */
-
-#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 /* RT_USING_MEMTRACE */
-
return ptr;
}
-RTM_EXPORT(rt_malloc);
-/**
- * @brief This function will release the previously allocated memory block by
- * rt_malloc. 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)
+/*
+ * rt_free port function
+*/
+void _memheap_free(void *rmem)
{
rt_memheap_free(rmem);
}
-RTM_EXPORT(rt_free);
-/**
- * @brief This function will change the size of previously allocated memory block.
- *
- * @param rmem is the pointer to memory allocated by rt_malloc.
- *
- * @param newsize is the required new size.
- *
- * @return the changed memory block address.
- */
-void *rt_realloc(void *rmem, rt_size_t newsize)
+/*
+ * rt_realloc port function
+*/
+void *_memheap_realloc(struct rt_memheap *heap, void *rmem, rt_size_t newsize)
{
void *new_ptr;
struct rt_memheap_item *header_ptr;
if (rmem == RT_NULL)
- return rt_malloc(newsize);
+ return _memheap_alloc(heap, newsize);
if (newsize == 0)
{
- rt_free(rmem);
+ _memheap_free(rmem);
return RT_NULL;
}
@@ -955,7 +839,7 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
if (new_ptr == RT_NULL && newsize != 0)
{
/* allocate memory block from other memheap */
- new_ptr = rt_malloc(newsize);
+ new_ptr = _memheap_alloc(heap, newsize);
if (new_ptr != RT_NULL && rmem != RT_NULL)
{
rt_size_t oldsize;
@@ -967,177 +851,145 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
else
rt_memcpy(new_ptr, rmem, newsize);
- rt_free(rmem);
+ _memheap_free(rmem);
}
}
-#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 /* RT_USING_MEMTRACE */
-
return new_ptr;
}
-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 pointer.
- */
-void *rt_calloc(rt_size_t count, rt_size_t size)
-{
- void *ptr;
- rt_size_t total_size;
-
- total_size = count * size;
- ptr = rt_malloc(total_size);
- if (ptr != RT_NULL)
- {
- /* clean memory */
- 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 /* RT_USING_MEMTRACE */
-
- return ptr;
-}
-RTM_EXPORT(rt_calloc);
-
-/**
-* @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 = _heap.pool_size;
-
- if (used != RT_NULL)
- *used = _heap.pool_size - _heap.available_size;
-
- if (max_used != RT_NULL)
- *max_used = _heap.max_used_size;
-}
-
-#endif /* RT_USING_MEMHEAP_AS_HEAP */
+#endif
#ifdef RT_USING_MEMTRACE
-
-/**
- * @brief This function will print the used memheap infomation.
- *
- * @param mh is a pointer of the memheap object.
- */
-void dump_used_memheap(struct rt_memheap *mh)
+int memheapcheck(int argc, char *argv[])
{
- struct rt_memheap_item *header_ptr;
- rt_uint32_t block_size;
-
- rt_kprintf("\nmemory heap address:\n");
- rt_kprintf("heap_ptr: 0x%08x\n", mh->start_addr);
- rt_kprintf("free : 0x%08x\n", mh->available_size);
- rt_kprintf("max_used: 0x%08x\n", mh->max_used_size);
- rt_kprintf("size : 0x%08x\n", mh->pool_size);
-
- rt_kprintf("\n--memory used information --\n");
+ struct rt_object_information *info;
+ struct rt_list_node *list;
+ struct rt_memheap *heap;
+ struct rt_list_node *node;
+ struct rt_memheap_item *item;
+ rt_bool_t has_bad = RT_FALSE;
+ rt_base_t level;
+ char *name;
- header_ptr = mh->block_list;
- while (header_ptr->next != mh->block_list)
+ name = argc > 1 ? argv[1] : RT_NULL;
+ level = rt_hw_interrupt_disable();
+ info = rt_object_get_information(RT_Object_Class_MemHeap);
+ list = &info->object_list;
+ for (node = list->next; node != list; node = node->next)
{
- if ((header_ptr->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
+ heap = (struct rt_memheap *)rt_list_entry(node, struct rt_object, list);
+ /* find the specified object */
+ if (name != RT_NULL && rt_strncmp(name, heap->parent.name, RT_NAME_MAX) != 0)
+ continue;
+ /* check memheap */
+ for (item = heap->block_list; item->next != heap->block_list; item = item->next)
{
- rt_kprintf("[0x%08x - incorrect magic: 0x%08x\n", header_ptr, header_ptr->magic);
- break;
- }
-
- /* get current memory block size */
- block_size = MEMITEM_SIZE(header_ptr);
- if (block_size < 0)
- break;
-
- if (RT_MEMHEAP_IS_USED(header_ptr))
- {
- /* dump information */
- rt_kprintf("[0x%08x - %d - %c%c%c%c] used\n", header_ptr, block_size,
- header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1],
- header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]);
- }
- else
- {
- /* dump information */
- rt_kprintf("[0x%08x - %d - %c%c%c%c] free\n", header_ptr, block_size,
- header_ptr->owner_thread_name[0], header_ptr->owner_thread_name[1],
- header_ptr->owner_thread_name[2], header_ptr->owner_thread_name[3]);
+ /* check magic */
+ if (!((item->magic & (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED)) == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED) ||
+ (item->magic & (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED)) == (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED)))
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ /* check pool_ptr */
+ if (heap != item->pool_ptr)
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ /* check next and prev */
+ if (!((rt_uint32_t)item->next <= (rt_uint32_t)((rt_uint32_t)heap->start_addr + heap->pool_size) &&
+ (rt_uint32_t)item->prev >= (rt_uint32_t)heap->start_addr) &&
+ (rt_uint32_t)item->next == RT_ALIGN((rt_uint32_t)item->next, RT_ALIGN_SIZE) &&
+ (rt_uint32_t)item->prev == RT_ALIGN((rt_uint32_t)item->prev, RT_ALIGN_SIZE))
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
+ /* check item */
+ if (item->next == item->next->prev)
+ {
+ has_bad = RT_TRUE;
+ break;
+ }
}
-
- /* move to next used memory block */
- header_ptr = header_ptr->next;
}
+ rt_hw_interrupt_enable(level);
+ if (has_bad)
+ {
+ rt_kprintf("Memory block wrong:\n");
+ rt_kprintf("name: %s\n", heap->parent.name);
+ rt_kprintf("item: 0x%08x\n", item);
+ }
+ return 0;
}
+MSH_CMD_EXPORT(memheapcheck, check memory for memheap);
-void memtrace_heap()
+int memheaptrace(int argc, char *argv[])
{
struct rt_object_information *info;
struct rt_list_node *list;
struct rt_memheap *mh;
struct rt_list_node *node;
+ char *name;
+ name = argc > 1 ? argv[1] : RT_NULL;
info = rt_object_get_information(RT_Object_Class_MemHeap);
list = &info->object_list;
-
for (node = list->next; node != list; node = node->next)
{
+ struct rt_memheap_item *header_ptr;
+ long block_size;
+
mh = (struct rt_memheap *)rt_list_entry(node, struct rt_object, list);
- dump_used_memheap(mh);
+ /* find the specified object */
+ if (name != RT_NULL && rt_strncmp(name, mh->parent.name, RT_NAME_MAX) != 0)
+ continue;
+ /* memheap dump */
+ rt_kprintf("\nmemory heap address:\n");
+ rt_kprintf("name : %s\n", mh->parent.name);
+ rt_kprintf("heap_ptr: 0x%08x\n", mh->start_addr);
+ rt_kprintf("free : 0x%08x\n", mh->available_size);
+ rt_kprintf("max_used: 0x%08x\n", mh->max_used_size);
+ rt_kprintf("size : 0x%08x\n", mh->pool_size);
+ rt_kprintf("\n--memory used information --\n");
+ /* memheap item */
+ for (header_ptr = mh->block_list;
+ header_ptr->next != mh->block_list;
+ header_ptr = header_ptr->next)
+ {
+ if ((header_ptr->magic & RT_MEMHEAP_MASK) != RT_MEMHEAP_MAGIC)
+ {
+ rt_kprintf("[0x%08x - incorrect magic: 0x%08x\n",
+ header_ptr, header_ptr->magic);
+ break;
+ }
+ /* get current memory block size */
+ block_size = MEMITEM_SIZE(header_ptr);
+ if (block_size < 0)
+ break;
+
+ rt_kprintf("[0x%08x - ", header_ptr);
+ if (block_size < 1024)
+ rt_kprintf("%5d", block_size);
+ else if (block_size < 1024 * 1024)
+ rt_kprintf("%4dK", block_size / 1024);
+ else
+ rt_kprintf("%4dM", block_size / (1024 * 1024));
+ /* dump thread name */
+ rt_kprintf("] %c%c%c%c\n",
+ header_ptr->owner_thread_name[0],
+ header_ptr->owner_thread_name[1],
+ header_ptr->owner_thread_name[2],
+ header_ptr->owner_thread_name[3]);
+ }
}
+ return 0;
}
#ifdef RT_USING_FINSH
#include <finsh.h>
-MSH_CMD_EXPORT(memtrace_heap, dump memory trace for heap);
+MSH_CMD_EXPORT(memheaptrace, dump memory trace for memheap);
#endif /* RT_USING_FINSH */
-
#endif /* RT_USING_MEMTRACE */
-
#endif /* RT_USING_MEMHEAP */
diff --git a/src/object.c b/src/object.c
index 66d5775bd7..76534f4566 100644
--- a/src/object.c
+++ b/src/object.c
@@ -56,6 +56,9 @@ enum rt_object_info_type
#ifdef RT_USING_MODULE
RT_Object_Info_Module, /**< The object is a module. */
#endif
+#ifdef RT_USING_HEAP
+ RT_Object_Info_Memory, /**< The object is a memory. */
+#endif
RT_Object_Info_Unknown, /**< The object is unknown. */
};
@@ -104,6 +107,10 @@ static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
/* initialize object container - module */
{RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
#endif
+#ifdef RT_USING_HEAP
+ /* initialize object container - small memory */
+ {RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory)},
+#endif
};
#ifdef RT_USING_HOOK
diff --git a/src/slab.c b/src/slab.c
index 8e0ce7bc83..f48179afaf 100644
--- a/src/slab.c
+++ b/src/slab.c
@@ -55,52 +55,7 @@
#include <rthw.h>
#include <rtthread.h>
-#define RT_MEM_STATS
-
-#if defined (RT_USING_HEAP) && defined (RT_USING_SLAB)
-/* some statistical variable */
-#ifdef RT_MEM_STATS
-static rt_size_t used_mem, max_mem;
-#endif /* RT_MEM_STATS */
-
-#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;
-}
-RTM_EXPORT(rt_malloc_sethook);
-
-/**
- * @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;
-}
-RTM_EXPORT(rt_free_sethook);
-
-/**@}*/
-
-#endif /* RT_USING_HOOK */
-
+#if defined (RT_USING_SLAB)
/*
* slab allocator implementation
*
@@ -155,48 +110,12 @@ RTM_EXPORT(rt_free_sethook);
* + ability to allocate arbitrarily large chunks of memory
*/
-/*
- * Chunk structure for free elements
- */
-typedef struct slab_chunk
-{
- struct slab_chunk *c_next;
-} slab_chunk;
-
-/*
- * The IN-BAND zone header is placed at the beginning of each zone.
- */
-typedef struct slab_zone
-{
- rt_int32_t z_magic; /* magic number for sanity check */
- rt_int32_t z_nfree; /* total free chunks / ualloc space in zone */
- rt_int32_t z_nmax; /* maximum free chunks */
-
- struct slab_zone *z_next; /* zoneary[] link if z_nfree non-zero */
- rt_uint8_t *z_baseptr; /* pointer to start of chunk array */
-
- rt_int32_t z_uindex; /* current initial allocation index */
- rt_int32_t z_chunksize; /* chunk size for validation */
-
- rt_int32_t z_zoneindex; /* zone index */
- slab_chunk *z_freechunk; /* free chunk list */
-} slab_zone;
-
#define ZALLOC_SLAB_MAGIC 0x51ab51ab
#define ZALLOC_ZONE_LIMIT (16 * 1024) /* max slab-managed alloc */
#define ZALLOC_MIN_ZONE_SIZE (32 * 1024) /* minimum zone size */
#define ZALLOC_MAX_ZONE_SIZE (128 * 1024) /* maximum zone size */
-#define NZONES 72 /* number of zones */
#define ZONE_RELEASE_THRESH 2 /* threshold number of zones */
-static slab_zone *zone_array[NZONES]; /* linked list of zones NFree > 0 */
-static slab_zone *zone_free; /* whole zones that have become free */
-
-static int zone_free_cnt;
-static int zone_size;
-static int zone_limit;
-static int zone_page_cnt;
-
/*
* Misc constants. Note that allocations that are exact multiples of
* RT_MM_PAGE_SIZE, or exceed the zone limit, fall through to the kmem module.
@@ -210,45 +129,95 @@ static int zone_page_cnt;
#define PAGE_TYPE_FREE 0x00
#define PAGE_TYPE_SMALL 0x01
#define PAGE_TYPE_LARGE 0x02
-struct memusage
+
+#define btokup(addr) \
+ (&slab->memusage[((rt_ubase_t)(addr) - slab->heap_start) >> RT_MM_PAGE_BITS])
+
+/**
+ * Base structure of slab memory object
+ */
+
+/*
+ * The IN-BAND zone header is placed at the beginning of each zone.
+ */
+struct rt_slab_zone
{
- rt_uint32_t type: 2 ; /* page type */
- rt_uint32_t size: 30; /* pages allocated or offset from zone */
+ rt_uint32_t z_magic; /**< magic number for sanity check */
+ rt_uint32_t z_nfree; /**< total free chunks / ualloc space in zone */
+ rt_uint32_t z_nmax; /**< maximum free chunks */
+ struct rt_slab_zone *z_next; /**< zoneary[] link if z_nfree non-zero */
+ rt_uint8_t *z_baseptr; /**< pointer to start of chunk array */
+
+ rt_uint32_t z_uindex; /**< current initial allocation index */
+ rt_uint32_t z_chunksize; /**< chunk size for validation */
+
+ rt_uint32_t z_zoneindex; /**< zone index */
+ struct rt_slab_chunk *z_freechunk; /**< free chunk list */
+};
+
+/*
+ * Chunk structure for free elements
+ */
+struct rt_slab_chunk
+{
+ struct rt_slab_chunk *c_next;
};
-static struct memusage *memusage = RT_NULL;
-#define btokup(addr) \
- (&memusage[((rt_ubase_t)(addr) - heap_start) >> RT_MM_PAGE_BITS])
-static rt_ubase_t heap_start, heap_end;
+struct rt_slab_memusage
+{
+ rt_uint32_t type: 2 ; /**< page type */
+ rt_uint32_t size: 30; /**< pages allocated or offset from zone */
+};
-/* page allocator */
-struct rt_page_head
+/*
+ * slab page allocator
+ */
+struct rt_slab_page
{
- struct rt_page_head *next; /* next valid page */
- rt_size_t page; /* number of page */
+ struct rt_slab_page *next; /**< next valid page */
+ rt_size_t page; /**< number of page */
/* dummy */
- char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_page_head *) + sizeof(rt_size_t))];
+ char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_slab_page *) + sizeof(rt_size_t))];
+};
+
+#define RT_SLAB_NZONES 72 /* number of zones */
+
+/*
+ * slab object
+ */
+struct rt_slab
+{
+ struct rt_memory parent; /**< inherit from rt_memory */
+ rt_ubase_t heap_start; /**< memory start address */
+ rt_ubase_t heap_end; /**< memory end address */
+ struct rt_slab_memusage *memusage;
+ struct rt_slab_zone *zone_array[RT_SLAB_NZONES]; /* linked list of zones NFree > 0 */
+ struct rt_slab_zone *zone_free; /* whole zones that have become free */
+ rt_uint32_t zone_free_cnt;
+ rt_uint32_t zone_size;
+ rt_uint32_t zone_limit;
+ rt_uint32_t zone_page_cnt;
+ struct rt_slab_page *page_list;
};
-static struct rt_page_head *rt_page_list;
-static struct rt_semaphore heap_sem;
/**
* @brief Alloc memory size by page.
*
+ * @param slab the slab memory management object.
+ *
* @param npages the number of pages.
*/
-void *rt_page_alloc(rt_size_t npages)
+void *rt_slab_page_alloc(rt_slab_t m, rt_size_t npages)
{
- struct rt_page_head *b, *n;
- struct rt_page_head **prev;
+ struct rt_slab_page *b, *n;
+ struct rt_slab_page **prev;
+ struct rt_slab *slab = (struct rt_slab *)m;
if (npages == 0)
return RT_NULL;
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
- for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
+ for (prev = &slab->page_list; (b = *prev) != RT_NULL; prev = &(b->next))
{
if (b->page > npages)
{
@@ -268,34 +237,31 @@ void *rt_page_alloc(rt_size_t npages)
}
}
- /* unlock heap */
- rt_sem_release(&heap_sem);
-
return b;
}
/**
* @brief Free memory by page.
*
+ * @param slab the slab memory management object.
+ *
* @param addr is the head address of first page.
*
* @param npages is the number of pages.
*/
-void rt_page_free(void *addr, rt_size_t npages)
+void rt_slab_page_free(rt_slab_t m, void *addr, rt_size_t npages)
{
- struct rt_page_head *b, *n;
- struct rt_page_head **prev;
+ struct rt_slab_page *b, *n;
+ struct rt_slab_page **prev;
+ struct rt_slab *slab = (struct rt_slab *)m;
RT_ASSERT(addr != RT_NULL);
RT_ASSERT((rt_ubase_t)addr % RT_MM_PAGE_SIZE == 0);
RT_ASSERT(npages != 0);
- n = (struct rt_page_head *)addr;
+ n = (struct rt_slab_page *)addr;
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
-
- for (prev = &rt_page_list; (b = *prev) != RT_NULL; prev = &(b->next))
+ for (prev = &slab->page_list; (b = *prev) != RT_NULL; prev = &(b->next))
{
RT_ASSERT(b->page > 0);
RT_ASSERT(b > n || b + b->page <= n);
@@ -307,8 +273,7 @@ void rt_page_free(void *addr, rt_size_t npages)
b->page += b->next->page;
b->next = b->next->next;
}
-
- goto _return;
+ return;
}
if (b == n + npages)
@@ -316,8 +281,7 @@ void rt_page_free(void *addr, rt_size_t npages)
n->page = b->page + npages;
n->next = b->next;
*prev = n;
-
- goto _return;
+ return;
}
if (b > n + npages)
@@ -327,83 +291,115 @@ void rt_page_free(void *addr, rt_size_t npages)
n->page = npages;
n->next = b;
*prev = n;
-
-_return:
- /* unlock heap */
- rt_sem_release(&heap_sem);
}
/*
* Initialize the page allocator
*/
-static void rt_page_init(void *addr, rt_size_t npages)
+static void rt_slab_page_init(struct rt_slab *slab, void *addr, rt_size_t npages)
{
RT_ASSERT(addr != RT_NULL);
RT_ASSERT(npages != 0);
- rt_page_list = RT_NULL;
- rt_page_free(addr, npages);
+ slab->page_list = RT_NULL;
+ rt_slab_page_free((rt_slab_t)(&slab->parent), addr, npages);
}
/**
- * @brief This function will init system heap.
+ * @brief This function will init slab memory management algorithm
+ *
+ * @param slab the slab memory management object.
+ *
+ * @param name is the name of the slab memory management object.
*
* @param begin_addr the beginning address of system page.
*
- * @param end_addr the end address of system page.
+ * @param size is the size of the memory.
+ *
+ * @return Return a pointer to the slab memory object.
*/
-void rt_system_heap_init(void *begin_addr, void *end_addr)
+rt_slab_t rt_slab_init(const char *name, void *begin_addr, rt_size_t size)
{
rt_uint32_t limsize, npages;
+ rt_ubase_t start_addr, begin_align, end_align;
+ struct rt_slab *slab;
- RT_DEBUG_NOT_IN_INTERRUPT;
-
+ slab = (struct rt_slab *)RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);
+ start_addr = (rt_ubase_t)slab + sizeof(*slab);
/* align begin and end addr to page */
- heap_start = RT_ALIGN((rt_ubase_t)begin_addr, RT_MM_PAGE_SIZE);
- heap_end = RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_MM_PAGE_SIZE);
-
- if (heap_start >= heap_end)
+ begin_align = RT_ALIGN((rt_ubase_t)start_addr, RT_MM_PAGE_SIZE);
+ end_align = RT_ALIGN_DOWN((rt_ubase_t)begin_addr + size, RT_MM_PAGE_SIZE);
+ if (begin_align >= end_align)
{
- rt_kprintf("rt_system_heap_init, wrong address[0x%x - 0x%x]\n",
- (rt_ubase_t)begin_addr, (rt_ubase_t)end_addr);
-
- return;
+ rt_kprintf("slab init errr. wrong address[0x%x - 0x%x]\n",
+ (rt_ubase_t)begin_addr, (rt_ubase_t)begin_addr + size);
+ return RT_NULL;
}
- limsize = heap_end - heap_start;
+ limsize = end_align - begin_align;
npages = limsize / RT_MM_PAGE_SIZE;
-
- /* initialize heap semaphore */
- rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO);
-
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("heap[0x%x - 0x%x], size 0x%x, 0x%x pages\n",
- heap_start, heap_end, limsize, npages));
+ begin_align, end_align, limsize, npages));
+
+ rt_memset(slab, 0, sizeof(*slab));
+ /* initialize slab memory object */
+ rt_object_init(&(slab->parent.parent), RT_Object_Class_Memory, name);
+ slab->parent.algorithm = "slab";
+ slab->parent.address = begin_align;
+ slab->parent.total = limsize;
+ slab->parent.used = 0;
+ slab->parent.max = 0;
+ slab->heap_start = begin_align;
+ slab->heap_end = end_align;
/* init pages */
- rt_page_init((void *)heap_start, npages);
+ rt_slab_page_init(slab, (void *)slab->heap_start, npages);
/* calculate zone size */
- zone_size = ZALLOC_MIN_ZONE_SIZE;
- while (zone_size < ZALLOC_MAX_ZONE_SIZE && (zone_size << 1) < (limsize / 1024))
- zone_size <<= 1;
+ slab->zone_size = ZALLOC_MIN_ZONE_SIZE;
+ while (slab->zone_size < ZALLOC_MAX_ZONE_SIZE && (slab->zone_size << 1) < (limsize / 1024))
+ slab->zone_size <<= 1;
- zone_limit = zone_size / 4;
- if (zone_limit > ZALLOC_ZONE_LIMIT)
- zone_limit = ZALLOC_ZONE_LIMIT;
+ slab->zone_limit = slab->zone_size / 4;
+ if (slab->zone_limit > ZALLOC_ZONE_LIMIT)
+ slab->zone_limit = ZALLOC_ZONE_LIMIT;
- zone_page_cnt = zone_size / RT_MM_PAGE_SIZE;
+ slab->zone_page_cnt = slab->zone_size / RT_MM_PAGE_SIZE;
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("zone size 0x%x, zone page count 0x%x\n",
- zone_size, zone_page_cnt));
+ slab->zone_size, slab->zone_page_cnt));
- /* allocate memusage array */
- limsize = npages * sizeof(struct memusage);
+ /* allocate slab->memusage array */
+ limsize = npages * sizeof(struct rt_slab_memusage);
limsize = RT_ALIGN(limsize, RT_MM_PAGE_SIZE);
- memusage = rt_page_alloc(limsize / RT_MM_PAGE_SIZE);
+ slab->memusage = rt_slab_page_alloc((rt_slab_t)(&slab->parent), limsize / RT_MM_PAGE_SIZE);
- RT_DEBUG_LOG(RT_DEBUG_SLAB, ("memusage 0x%x, size 0x%x\n",
- (rt_ubase_t)memusage, limsize));
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("slab->memusage 0x%x, size 0x%x\n",
+ (rt_ubase_t)slab->memusage, limsize));
+ return &slab->parent;
}
+RTM_EXPORT(rt_slab_init);
+
+/**
+ * @brief This function will remove a slab object from the system.
+ *
+ * @param m the slab memory management object.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_slab_detach(rt_slab_t m)
+{
+ struct rt_slab *slab = (struct rt_slab *)m;
+
+ RT_ASSERT(slab != RT_NULL);
+ RT_ASSERT(rt_object_get_type(&slab->parent.parent) == RT_Object_Class_Memory);
+ RT_ASSERT(rt_object_is_systemobject(&slab->parent.parent));
+
+ rt_object_detach(&(slab->parent.parent));
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_slab_detach);
/*
* Calculate the zone index for the allocation request size and set the
@@ -476,22 +472,25 @@ rt_inline int zoneindex(rt_size_t *bytes)
/**@{*/
/**
- * @brief This function will allocate a block from system heap memory.
+ * @brief This function will allocate a block from slab object.
*
* @note the RT_NULL is returned if
* - the nbytes is less than zero.
* - there is no nbytes sized memory valid in system.
*
+ * @param m the slab memory management object.
+ *
* @param size is the size of memory to be allocated.
*
* @return the allocated memory.
*/
-void *rt_malloc(rt_size_t size)
+void *rt_slab_alloc(rt_slab_t m, rt_size_t size)
{
- slab_zone *z;
+ struct rt_slab_zone *z;
rt_int32_t zi;
- slab_chunk *chunk;
- struct memusage *kup;
+ struct rt_slab_chunk *chunk;
+ struct rt_slab_memusage *kup;
+ struct rt_slab *slab = (struct rt_slab *)m;
/* zero size, return RT_NULL */
if (size == 0)
@@ -501,11 +500,11 @@ void *rt_malloc(rt_size_t size)
* Handle large allocations directly. There should not be very many of
* these so performance is not a big issue.
*/
- if (size >= zone_limit)
+ if (size >= slab->zone_limit)
{
size = RT_ALIGN(size, RT_MM_PAGE_SIZE);
- chunk = rt_page_alloc(size >> RT_MM_PAGE_BITS);
+ chunk = rt_slab_page_alloc(m, size >> RT_MM_PAGE_BITS);
if (chunk == RT_NULL)
return RT_NULL;
@@ -515,25 +514,17 @@ void *rt_malloc(rt_size_t size)
kup->size = size >> RT_MM_PAGE_BITS;
RT_DEBUG_LOG(RT_DEBUG_SLAB,
- ("malloc a large memory 0x%x, page cnt %d, kup %d\n",
+ ("alloc a large memory 0x%x, page cnt %d, kup %d\n",
size,
size >> RT_MM_PAGE_BITS,
- ((rt_ubase_t)chunk - heap_start) >> RT_MM_PAGE_BITS));
-
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
-
-#ifdef RT_MEM_STATS
- used_mem += size;
- if (used_mem > max_mem)
- max_mem = used_mem;
-#endif /* RT_MEM_STATS */
- goto done;
+ ((rt_ubase_t)chunk - slab->heap_start) >> RT_MM_PAGE_BITS));
+ /* mem stat */
+ slab->parent.used += size;
+ if (slab->parent.used > slab->parent.max)
+ slab->parent.max = slab->parent.used;
+ return chunk;
}
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
-
/*
* Attempt to allocate out of an existing zone. First try the free list,
* then allocate out of unallocated space. If we find a good zone move
@@ -543,18 +534,18 @@ void *rt_malloc(rt_size_t size)
* Note: zoneindex() will panic of size is too large.
*/
zi = zoneindex(&size);
- RT_ASSERT(zi < NZONES);
+ RT_ASSERT(zi < RT_SLAB_NZONES);
- RT_DEBUG_LOG(RT_DEBUG_SLAB, ("try to malloc 0x%x on zone: %d\n", size, zi));
+ RT_DEBUG_LOG(RT_DEBUG_SLAB, ("try to alloc 0x%x on zone: %d\n", size, zi));
- if ((z = zone_array[zi]) != RT_NULL)
+ if ((z = slab->zone_array[zi]) != RT_NULL)
{
RT_ASSERT(z->z_nfree > 0);
/* Remove us from the zone_array[] when we become full */
if (--z->z_nfree == 0)
{
- zone_array[zi] = z->z_next;
+ slab->zone_array[zi] = z->z_next;
z->z_next = RT_NULL;
}
@@ -567,7 +558,7 @@ void *rt_malloc(rt_size_t size)
if (z->z_uindex + 1 != z->z_nmax)
{
z->z_uindex = z->z_uindex + 1;
- chunk = (slab_chunk *)(z->z_baseptr + z->z_uindex * size);
+ chunk = (struct rt_slab_chunk *)(z->z_baseptr + z->z_uindex * size);
}
else
{
@@ -577,14 +568,12 @@ void *rt_malloc(rt_size_t size)
/* remove this chunk from list */
z->z_freechunk = z->z_freechunk->c_next;
}
+ /* mem stats */
+ slab->parent.used += z->z_chunksize;
+ if (slab->parent.used > slab->parent.max)
+ slab->parent.max = slab->parent.used;
-#ifdef RT_MEM_STATS
- used_mem += z->z_chunksize;
- if (used_mem > max_mem)
- max_mem = used_mem;
-#endif /* RT_MEM_STATS */
-
- goto done;
+ return chunk;
}
/*
@@ -596,35 +585,28 @@ void *rt_malloc(rt_size_t size)
* adjusting the base offset below.
*/
{
- rt_int32_t off;
+ rt_uint32_t off;
- if ((z = zone_free) != RT_NULL)
+ if ((z = slab->zone_free) != RT_NULL)
{
/* remove zone from free zone list */
- zone_free = z->z_next;
- -- zone_free_cnt;
+ slab->zone_free = z->z_next;
+ -- slab->zone_free_cnt;
}
else
{
- /* unlock heap, since page allocator will think about lock */
- rt_sem_release(&heap_sem);
-
/* allocate a zone from page */
- z = rt_page_alloc(zone_size / RT_MM_PAGE_SIZE);
+ z = rt_slab_page_alloc(m, slab->zone_size / RT_MM_PAGE_SIZE);
if (z == RT_NULL)
{
- chunk = RT_NULL;
- goto __exit;
+ return RT_NULL;
}
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
-
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("alloc a new zone: 0x%x\n",
(rt_ubase_t)z));
/* set message usage */
- for (off = 0, kup = btokup(z); off < zone_page_cnt; off ++)
+ for (off = 0, kup = btokup(z); off < slab->zone_page_cnt; off ++)
{
kup->type = PAGE_TYPE_SMALL;
kup->size = off;
@@ -634,10 +616,10 @@ void *rt_malloc(rt_size_t size)
}
/* clear to zero */
- rt_memset(z, 0, sizeof(slab_zone));
+ rt_memset(z, 0, sizeof(struct rt_slab_zone));
/* offset of slab zone struct in zone */
- off = sizeof(slab_zone);
+ off = sizeof(struct rt_slab_zone);
/*
* Guarentee power-of-2 alignment for power-of-2-sized chunks.
@@ -650,55 +632,51 @@ void *rt_malloc(rt_size_t size)
z->z_magic = ZALLOC_SLAB_MAGIC;
z->z_zoneindex = zi;
- z->z_nmax = (zone_size - off) / size;
+ z->z_nmax = (slab->zone_size - off) / size;
z->z_nfree = z->z_nmax - 1;
z->z_baseptr = (rt_uint8_t *)z + off;
z->z_uindex = 0;
z->z_chunksize = size;
- chunk = (slab_chunk *)(z->z_baseptr + z->z_uindex * size);
+ chunk = (struct rt_slab_chunk *)(z->z_baseptr + z->z_uindex * size);
/* link to zone array */
- z->z_next = zone_array[zi];
- zone_array[zi] = z;
-
-#ifdef RT_MEM_STATS
- used_mem += z->z_chunksize;
- if (used_mem > max_mem)
- max_mem = used_mem;
-#endif /* RT_MEM_STATS */
+ z->z_next = slab->zone_array[zi];
+ slab->zone_array[zi] = z;
+ /* mem stats */
+ slab->parent.used += z->z_chunksize;
+ if (slab->parent.used > slab->parent.max)
+ slab->parent.max = slab->parent.used;
}
-done:
- rt_sem_release(&heap_sem);
- RT_OBJECT_HOOK_CALL(rt_malloc_hook, ((char *)chunk, size));
-
-__exit:
return chunk;
}
-RTM_EXPORT(rt_malloc);
+RTM_EXPORT(rt_slab_alloc);
/**
* @brief This function will change the size of previously allocated memory block.
*
+ * @param m the slab memory management object.
+ *
* @param ptr is the previously allocated memory block.
*
* @param size is the new size of memory block.
*
* @return the allocated memory.
*/
-void *rt_realloc(void *ptr, rt_size_t size)
+void *rt_slab_realloc(rt_slab_t m, void *ptr, rt_size_t size)
{
void *nptr;
- slab_zone *z;
- struct memusage *kup;
+ struct rt_slab_zone *z;
+ struct rt_slab_memusage *kup;
+ struct rt_slab *slab = (struct rt_slab *)m;
if (ptr == RT_NULL)
- return rt_malloc(size);
+ return rt_slab_alloc(m, size);
+
if (size == 0)
{
- rt_free(ptr);
-
+ rt_slab_free(m, ptr);
return RT_NULL;
}
@@ -712,16 +690,16 @@ void *rt_realloc(void *ptr, rt_size_t size)
rt_size_t osize;
osize = kup->size << RT_MM_PAGE_BITS;
- if ((nptr = rt_malloc(size)) == RT_NULL)
+ if ((nptr = rt_slab_alloc(m, size)) == RT_NULL)
return RT_NULL;
rt_memcpy(nptr, ptr, size > osize ? osize : size);
- rt_free(ptr);
+ rt_slab_free(m, ptr);
return nptr;
}
else if (kup->type == PAGE_TYPE_SMALL)
{
- z = (slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
+ z = (struct rt_slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
kup->size * RT_MM_PAGE_SIZE);
RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
@@ -734,66 +712,38 @@ void *rt_realloc(void *ptr, rt_size_t size)
* already adjusted the request size to the appropriate chunk size, which
* should optimize our bcopy(). Then copy and return the new pointer.
*/
- if ((nptr = rt_malloc(size)) == RT_NULL)
+ if ((nptr = rt_slab_alloc(m, size)) == RT_NULL)
return RT_NULL;
rt_memcpy(nptr, ptr, size > z->z_chunksize ? z->z_chunksize : size);
- rt_free(ptr);
+ rt_slab_free(m, ptr);
return nptr;
}
return RT_NULL;
}
-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 the objects 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_slab_realloc);
/**
- * @brief This function will release the previous allocated memory block by rt_malloc.
+ * @brief This function will release the previous allocated memory block by rt_slab_alloc.
*
* @note The released memory block is taken back to system heap.
*
+ * @param m the slab memory management object.
* @param ptr is the address of memory which will be released
*/
-void rt_free(void *ptr)
+void rt_slab_free(rt_slab_t m, void *ptr)
{
- slab_zone *z;
- slab_chunk *chunk;
- struct memusage *kup;
+ struct rt_slab_zone *z;
+ struct rt_slab_chunk *chunk;
+ struct rt_slab_memusage *kup;
+ struct rt_slab *slab = (struct rt_slab *)m;
/* free a RT_NULL pointer */
if (ptr == RT_NULL)
return ;
- RT_OBJECT_HOOK_CALL(rt_free_hook, (ptr));
-
/* get memory usage */
#if RT_DEBUG_SLAB
{
@@ -802,7 +752,7 @@ void rt_free(void *ptr)
("free a memory 0x%x and align to 0x%x, kup index %d\n",
(rt_ubase_t)ptr,
(rt_ubase_t)addr,
- ((rt_ubase_t)(addr) - heap_start) >> RT_MM_PAGE_BITS));
+ ((rt_ubase_t)(addr) - slab->heap_start) >> RT_MM_PAGE_BITS));
}
#endif /* RT_DEBUG_SLAB */
@@ -812,42 +762,32 @@ void rt_free(void *ptr)
{
rt_ubase_t size;
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* clear page counter */
size = kup->size;
kup->size = 0;
-
-#ifdef RT_MEM_STATS
- used_mem -= size * RT_MM_PAGE_SIZE;
-#endif /* RT_MEM_STATS */
- rt_sem_release(&heap_sem);
+ /* mem stats */
+ slab->parent.used -= size * RT_MM_PAGE_SIZE;
RT_DEBUG_LOG(RT_DEBUG_SLAB,
("free large memory block 0x%x, page count %d\n",
(rt_ubase_t)ptr, size));
/* free this page */
- rt_page_free(ptr, size);
+ rt_slab_page_free(m, ptr, size);
return;
}
- /* lock heap */
- rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
-
/* zone case. get out zone. */
- z = (slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
+ z = (struct rt_slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
kup->size * RT_MM_PAGE_SIZE);
RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
- chunk = (slab_chunk *)ptr;
+ chunk = (struct rt_slab_chunk *)ptr;
chunk->c_next = z->z_freechunk;
z->z_freechunk = chunk;
-
-#ifdef RT_MEM_STATS
- used_mem -= z->z_chunksize;
-#endif /* RT_MEM_STATS */
+ /* mem stats */
+ slab->parent.used -= z->z_chunksize;
/*
* Bump the number of free chunks. If it becomes non-zero the zone
@@ -855,8 +795,8 @@ void rt_free(void *ptr)
*/
if (z->z_nfree++ == 0)
{
- z->z_next = zone_array[z->z_zoneindex];
- zone_array[z->z_zoneindex] = z;
+ z->z_next = slab->zone_array[z->z_zoneindex];
+ slab->zone_array[z->z_zoneindex] = z;
}
/*
@@ -866,96 +806,51 @@ void rt_free(void *ptr)
* with kernel_map here. Hysteresis will be performed at malloc() time.
*/
if (z->z_nfree == z->z_nmax &&
- (z->z_next || zone_array[z->z_zoneindex] != z))
+ (z->z_next || slab->zone_array[z->z_zoneindex] != z))
{
- slab_zone **pz;
+ struct rt_slab_zone **pz;
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("free zone 0x%x\n",
(rt_ubase_t)z, z->z_zoneindex));
/* remove zone from zone array list */
- for (pz = &zone_array[z->z_zoneindex]; z != *pz; pz = &(*pz)->z_next)
+ for (pz = &slab->zone_array[z->z_zoneindex]; z != *pz; pz = &(*pz)->z_next)
;
*pz = z->z_next;
/* reset zone */
- z->z_magic = -1;
+ z->z_magic = RT_UINT32_MAX;
/* insert to free zone list */
- z->z_next = zone_free;
- zone_free = z;
+ z->z_next = slab->zone_free;
+ slab->zone_free = z;
- ++ zone_free_cnt;
+ ++ slab->zone_free_cnt;
/* release zone to page allocator */
- if (zone_free_cnt > ZONE_RELEASE_THRESH)
+ if (slab->zone_free_cnt > ZONE_RELEASE_THRESH)
{
- register rt_base_t i;
+ register rt_uint32_t i;
- z = zone_free;
- zone_free = z->z_next;
- -- zone_free_cnt;
+ z = slab->zone_free;
+ slab->zone_free = z->z_next;
+ -- slab->zone_free_cnt;
/* set message usage */
- for (i = 0, kup = btokup(z); i < zone_page_cnt; i ++)
+ for (i = 0, kup = btokup(z); i < slab->zone_page_cnt; i ++)
{
kup->type = PAGE_TYPE_FREE;
kup->size = 0;
kup ++;
}
- /* unlock heap */
- rt_sem_release(&heap_sem);
-
/* release pages */
- rt_page_free(z, zone_size / RT_MM_PAGE_SIZE);
+ rt_slab_page_free(m, z, slab->zone_size / RT_MM_PAGE_SIZE);
return;
}
}
- /* unlock heap */
- 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 = heap_end - heap_start;
-
- if (used != RT_NULL)
- *used = used_mem;
-
- if (max_used != RT_NULL)
- *max_used = max_mem;
-}
-
-#ifdef RT_USING_FINSH
-#include <finsh.h>
-
-void list_mem(void)
-{
- rt_kprintf("total memory: %d\n", heap_end - heap_start);
- 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)
-#endif /* RT_USING_FINSH */
-#endif /* RT_MEM_STATS */
-
-/**@}*/
+RTM_EXPORT(rt_slab_free);
-#endif /* defined (RT_USING_HEAP) && defined (RT_USING_SLAB) */
+#endif /* defined (RT_USING_SLAB) */