一、目的
在上一篇《RT-Thread系列--内存池MEMPOOL源码分析》我们介绍了RT-Thread的内存池MEMPOOL实现细节,包括内存池结构和内存块管理。
本篇我们来分析一下RT-Thread的内存堆MEMHEAP的实现原理。
内存堆MEMHEAP的特点:
按需分配,需要多少内存就分配多少内存(存在最小内存块限制);
内存回收时一般会进行头部和尾部拼接,尽量减少内存碎片
内存容易碎片化
实现较为复杂
支持多内存堆
在实际应用中我们可以创建多个MEMHEAP,例如memheap A的内存是noncached的,memheap B的内存是DMA属性类型的。
二、介绍
在分析实现原理之前,我们首先分析一下MEMHEAP两个重要的数据结构,分别为:
struct rt_memheap
struct rt_memheap_item
struct rt_memheap
{
struct rt_object parent; /**< inherit from rt_object */
void *start_addr; /**< pool start address and size */
rt_size_t pool_size; /**< pool size */
rt_size_t available_size; /**< available size */
rt_size_t max_used_size; /**< maximum allocated size */
struct rt_memheap_item *block_list; /**< used block list */
struct rt_memheap_item *free_list; /**< free block list */
struct rt_memheap_item free_header; /**< free block list header */
struct rt_semaphore lock; /**< semaphore lock */
rt_bool_t locked; /**< External lock mark */
};
各个字段的含义:
parent:每个memheap对象都是一个struct rt_object类型的对象(基类),通过parent字段可以将memheap统一管理;
start_addr:当前内存堆所管理的整个内存的首地址
pool_size:当前内存堆所管理的整个内存的大小
available_size:可分配的内存大小
max_used_size:已经使用的内存大小
block_list:指向当前已使用内存块
free_list:指向当前未使用内存块
free_header:空闲内存块的链表头
lock:互斥锁
locked:是否已经上锁
内存堆虽然是按需分配,但是每块分配出来的内存都需要一个数据结构用于管理此内存块;实际每次分配占用的内存大小为:所需内存大小(对齐)+内存块头部结构(对齐)两者之和。
struct rt_memheap_item
{
rt_uint32_t magic; /**< magic number for memheap */
struct rt_memheap *pool_ptr; /**< point of pool */
struct rt_memheap_item *next; /**< next memheap item */
struct rt_memheap_item *prev; /**< prev memheap item */
struct rt_memheap_item *next_free; /**< next free memheap item */
struct rt_memheap_item *prev_free; /**< prev free memheap item */
#ifdef RT_USING_MEMTRACE
rt_uint8_t owner_thread_name[4]; /**< owner thread name */
#endif
};
各字段含义:
magic:用于标记此块内存是内存块首部
pool_ptr:指向此内存块从属的堆对象
next:指向下一个memheap item
prev:指向上一个memheap item
next_free:指向下一个空闲内存块
prev_free:指向上一次空闲内存块
通过next/prev指针将已经分配的内存块连接成链表;通过next_free/prev_free指针将未分配的内存连接成空闲内存链表
宏定义说明
#define RT_MEMHEAP_MINIALLOC 12
#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
#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)
RT_MEMHEAP_MINIALLOC定义最小的内存分配大小
RT_MEMHEAP_SIZE定义每个内存块管理结构的大小(对齐)
MEMITEM_SIZE(item)获取当前内存块管理的内存大小
MEMITEM(ptr) 通过ptr获取当前内存块头的地址
内存堆的初始化,内存堆在分配之前必须对此内存堆管理的内存进行初始化,主要包括空闲链表的初始化、各个指针的初始化等
rt_err_t rt_memheap_init(struct rt_memheap *memheap,
const char *name,
void *start_addr,
rt_size_t size)
{
struct rt_memheap_item *item;
RT_ASSERT(memheap != RT_NULL);
/* initialize pool object */
rt_object_init(&(memheap->parent), RT_Object_Class_MemHeap, name);
memheap->start_addr = start_addr; //内存首地址
memheap->pool_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); //对齐
// 此处减去(2 * RT_MEMHEAP_SIZE)的目的是第一个空闲块需要一个头部,最后一个内存块(实际内存长度为0)也需要一个管理头部
memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE);
memheap->max_used_size = memheap->pool_size - memheap->available_size;
// 对free_header进行初始化
// next_free/prev_free指向自身
// prev/next指向NULL
/* initialize the free list header */
item = &(memheap->free_header);
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
item->pool_ptr = memheap;
item->next = RT_NULL;
item->prev = RT_NULL;
item->next_free = item;
item->prev_free = item;
/* set the free list to free list header */
memheap->free_list = item;
/* initialize the first big memory block */
item = (struct rt_memheap_item *)start_addr; //指向内存首地址
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
item->pool_ptr = memheap;
item->next = RT_NULL;
item->prev = RT_NULL;
item->next_free = item;
item->prev_free = item;
#ifdef RT_USING_MEMTRACE
rt_memset(item->owner_thread_name, ' ', sizeof(item->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
item->next = (struct rt_memheap_item *)
((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE); //指向最后一个内存块
item->prev = item->next; //指向最后一个内存块
/* block list header */
memheap->block_list = item;
/* place the big memory block to free list */
item->next_free = memheap->free_list->next_free;
item->prev_free = memheap->free_list;
memheap->free_list->next_free->prev_free = item;
memheap->free_list->next_free = item;
/* move to the end of memory pool to build a small tailer block,
* which prevents block merging
*/
item = item->next;
/* it's a used memory block */
item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
item->pool_ptr = memheap;
item->next = (struct rt_memheap_item *)start_addr;
item->prev = (struct rt_memheap_item *)start_addr;
/* not in free list */
item->next_free = item->prev_free = RT_NULL;
/* 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",
start_addr, size, &(memheap->free_header)));
return RT_EOK;
}
初始化后内存堆内部结构如下图
从上图我们可以清晰看到,内存堆中最大的可分配的内存块为蓝色的块结构A管理的内存(内存状态为RT_MEMHEAP_FREED),大小为available_size;
其next/prev指向黄色内存块B(内存状态为RT_MEMHEAP_USED);并且rt_memheap_item B的next/prev也指向内存块A;
其next_free/prev_free指向rt_memheap_item C块结构,也就是free_header;并且free_header的next_free/prev_free也指向内存块A
内存的分配
void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
{
rt_err_t result;
rt_size_t free_size;
struct rt_memheap_item *header_ptr;
RT_ASSERT(heap != RT_NULL);
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
// 最小内存块大小判断
/* align allocated size */
size = RT_ALIGN(size, RT_ALIGN_SIZE);
if (size < RT_MEMHEAP_MINIALLOC)
size = RT_MEMHEAP_MINIALLOC;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate %d on heap:%8.*s",
size, RT_NAME_MAX, heap->parent.name));
if (size < heap->available_size)
{
/* search on free list */
free_size = 0;
/* lock memheap */
if (heap->locked == RT_FALSE)
{
result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
if (result != RT_EOK)
{
rt_set_errno(result);
return RT_NULL;
}
}
/* get the first free memory block */
header_ptr = heap->free_list->next_free;
while (header_ptr != heap->free_list && free_size < size)
{
/* get current freed memory block size */
free_size = MEMITEM_SIZE(header_ptr);
if (free_size < size)
{
/* move to next free memory block */
header_ptr = header_ptr->next_free;
}
}
/* determine if the memory is available. */
if (free_size >= size)
{
/* a block that satisfies the request has been found. */
/* determine if the block needs to be split. */
if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC))
{
struct rt_memheap_item *new_ptr;
/* split the block. */
new_ptr = (struct rt_memheap_item *)
(((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
header_ptr,
header_ptr->next,
header_ptr->prev,
new_ptr));
/* mark the new block as a memory block and freed. */
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
#ifdef RT_USING_MEMTRACE
rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
/* break down the block list */
new_ptr->prev = header_ptr;
new_ptr->next = header_ptr->next;
header_ptr->next->prev = new_ptr;
header_ptr->next = new_ptr;
/* remove header ptr from free list */
header_ptr->next_free->prev_free = header_ptr->prev_free;
header_ptr->prev_free->next_free = header_ptr->next_free;
header_ptr->next_free = RT_NULL;
header_ptr->prev_free = RT_NULL;
/* insert new_ptr to free list */
new_ptr->next_free = heap->free_list->next_free;
new_ptr->prev_free = heap->free_list;
heap->free_list->next_free->prev_free = new_ptr;
heap->free_list->next_free = new_ptr;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x\n",
new_ptr->next_free,
new_ptr->prev_free));
/* decrement the available byte count. */
heap->available_size = heap->available_size -
size -
RT_MEMHEAP_SIZE;
if (heap->pool_size - heap->available_size > heap->max_used_size)
heap->max_used_size = heap->pool_size - heap->available_size;
}
else
{
/* decrement the entire free size from the available bytes count. */
heap->available_size = heap->available_size - free_size;
if (heap->pool_size - heap->available_size > heap->max_used_size)
heap->max_used_size = heap->pool_size - heap->available_size;
/* remove header_ptr from free list */
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("one block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x\n",
header_ptr,
header_ptr->next_free,
header_ptr->prev_free));
header_ptr->next_free->prev_free = header_ptr->prev_free;
header_ptr->prev_free->next_free = header_ptr->next_free;
header_ptr->next_free = RT_NULL;
header_ptr->prev_free = RT_NULL;
}
/* Mark the allocated block as not available. */
header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED);
#ifdef RT_USING_MEMTRACE
if (rt_thread_self())
rt_memcpy(header_ptr->owner_thread_name, rt_thread_self()->name, sizeof(header_ptr->owner_thread_name));
else
rt_memcpy(header_ptr->owner_thread_name, "NONE", sizeof(header_ptr->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
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,
("alloc mem: memory[0x%08x], heap[0x%08x], size: %d\n",
(void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE),
header_ptr,
size));
return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE);
}
if (heap->locked == RT_FALSE)
{
/* release lock */
rt_sem_release(&(heap->lock));
}
}
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed\n"));
/* Return the completion status. */
return RT_NULL;
}
首先对需要的内存的size进行大小限定,然后判断是否小于heap->available_size;否则直接返回NULL
/* get the first free memory block */
header_ptr = heap->free_list->next_free;
while (header_ptr != heap->free_list && free_size < size)
{
/* get current freed memory block size */
free_size = MEMITEM_SIZE(header_ptr);
if (free_size < size)
{
/* move to next free memory block */
header_ptr = header_ptr->next_free;
}
}
获取空闲内存块的首地址,然后遍历空闲内存块,找到空闲内存块大小不小于size的内存块的地址(注意此处从头往后找,只要找到大小足够大的内存块就认为找到,但未必是大小相匹配的,所以存在内存碎片的问题)。
if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC)) {
} else {
}
判断当前空闲块的内存减去size后是否仍然足够放下最小内存块(RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC),如果足够则需要对此块内存进行切割;否则直接将这块内存分配出来。
下面我们分析一下切割操作:
struct rt_memheap_item *new_ptr;
/* split the block. */
new_ptr = (struct rt_memheap_item *)
(((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
header_ptr,
header_ptr->next,
header_ptr->prev,
new_ptr));
/* mark the new block as a memory block and freed. */
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
#ifdef RT_USING_MEMTRACE
rt_memset(new_ptr->owner_thread_name, ' ', sizeof(new_ptr->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
/* break down the block list */
new_ptr->prev = header_ptr;
new_ptr->next = header_ptr->next;
header_ptr->next->prev = new_ptr;
header_ptr->next = new_ptr;
/* remove header ptr from free list */
header_ptr->next_free->prev_free = header_ptr->prev_free;
header_ptr->prev_free->next_free = header_ptr->next_free;
header_ptr->next_free = RT_NULL;
header_ptr->prev_free = RT_NULL;
/* insert new_ptr to free list */
new_ptr->next_free = heap->free_list->next_free;
new_ptr->prev_free = heap->free_list;
heap->free_list->next_free->prev_free = new_ptr;
heap->free_list->next_free = new_ptr;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x\n",
new_ptr->next_free,
new_ptr->prev_free));
/* decrement the available byte count. */
heap->available_size = heap->available_size -
size -
RT_MEMHEAP_SIZE;
if (heap->pool_size - heap->available_size > heap->max_used_size)
heap->max_used_size = heap->pool_size - heap->available_size;
获取切割后剩余块的首地址并设置内存状态为RT_MEMHEAP_FREED
new_ptr = (struct rt_memheap_item *)
(((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
/* mark the new block as a memory block and freed. */
new_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* put the pool pointer into the new block. */
new_ptr->pool_ptr = heap;
切割后new_ptr是新的空闲内存块,需要挂载到空闲链表中
/* break down the block list */
new_ptr->prev = header_ptr;
new_ptr->next = header_ptr->next;
header_ptr->next->prev = new_ptr;
header_ptr->next = new_ptr;
/* remove header ptr from free list */
header_ptr->next_free->prev_free = header_ptr->prev_free;
header_ptr->prev_free->next_free = header_ptr->next_free;
header_ptr->next_free = RT_NULL;
header_ptr->prev_free = RT_NULL;
/* insert new_ptr to free list */
new_ptr->next_free = heap->free_list->next_free;
new_ptr->prev_free = heap->free_list;
heap->free_list->next_free->prev_free = new_ptr;
heap->free_list->next_free = new_ptr;
内存分配后的数据结构如下
最后我们再来分析一下rt_memheap_free的实现
void rt_memheap_free(void *ptr)
{
rt_err_t result;
struct rt_memheap *heap;
struct rt_memheap_item *header_ptr, *new_ptr;
rt_bool_t insert_header;
/* NULL check */
if (ptr == RT_NULL) return;
/* set initial status as OK */
insert_header = RT_TRUE;
new_ptr = RT_NULL;
header_ptr = (struct rt_memheap_item *)
((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: memory[0x%08x], block[0x%08x]\n",
ptr, header_ptr));
/* check magic */
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);
}
/* get pool ptr */
heap = header_ptr->pool_ptr;
RT_ASSERT(heap);
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
if (heap->locked == RT_FALSE)
{
/* lock memheap */
result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
if (result != RT_EOK)
{
rt_set_errno(result);
return ;
}
}
/* Mark the memory as available. */
header_ptr->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED);
/* Adjust the available number of bytes. */
heap->available_size += MEMITEM_SIZE(header_ptr);
/* Determine if the block can be merged with the previous neighbor. */
if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x\n",
header_ptr->prev));
/* adjust the available number of bytes. */
heap->available_size += RT_MEMHEAP_SIZE;
/* yes, merge block with previous neighbor. */
(header_ptr->prev)->next = header_ptr->next;
(header_ptr->next)->prev = header_ptr->prev;
/* move header pointer to previous. */
header_ptr = header_ptr->prev;
/* don't insert header to free list */
insert_header = RT_FALSE;
}
/* determine if the block can be merged with the next neighbor. */
if (!RT_MEMHEAP_IS_USED(header_ptr->next))
{
/* adjust the available number of bytes. */
heap->available_size += RT_MEMHEAP_SIZE;
/* merge block with next neighbor. */
new_ptr = header_ptr->next;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
new_ptr, new_ptr->next_free, new_ptr->prev_free));
new_ptr->next->prev = header_ptr;
header_ptr->next = new_ptr->next;
/* remove new ptr from free list */
new_ptr->next_free->prev_free = new_ptr->prev_free;
new_ptr->prev_free->next_free = new_ptr->next_free;
}
if (insert_header)
{
struct rt_memheap_item *n = heap->free_list->next_free;;
#if defined(RT_MEMHEAP_BSET_MODE)
rt_size_t blk_size = MEMITEM_SIZE(header_ptr);
for (;n != heap->free_list; n = n->next_free)
{
rt_size_t m = MEMITEM_SIZE(n);
if (blk_size <= m)
{
break;
}
}
#endif
/* no left merge, insert to free list */
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",
header_ptr->next_free, header_ptr->prev_free));
}
#ifdef RT_USING_MEMTRACE
rt_memset(header_ptr->owner_thread_name, ' ', sizeof(header_ptr->owner_thread_name));
#endif /* RT_USING_MEMTRACE */
if (heap->locked == RT_FALSE)
{
/* release lock */
rt_sem_release(&(heap->lock));
}
}
其中代码片段用于判断需要释放的内存是否是合法内存
header_ptr = (struct rt_memheap_item *)
((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: memory[0x%08x], block[0x%08x]\n",
ptr, header_ptr));
/* check magic */
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);
}
判断当前释放的内存块前一个内存块是否是空闲内存块,如果是则拼接在一起
/* Determine if the block can be merged with the previous neighbor. */
if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
{
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x\n",
header_ptr->prev));
/* adjust the available number of bytes. */
heap->available_size += RT_MEMHEAP_SIZE;
/* yes, merge block with previous neighbor. */
(header_ptr->prev)->next = header_ptr->next;
(header_ptr->next)->prev = header_ptr->prev;
/* move header pointer to previous. */
header_ptr = header_ptr->prev;
/* don't insert header to free list */
insert_header = RT_FALSE;
}
判断当前释放的内存块下一个内存块是否是空闲内存块,如果是则拼接在一起
/* determine if the block can be merged with the next neighbor. */
if (!RT_MEMHEAP_IS_USED(header_ptr->next))
{
/* adjust the available number of bytes. */
heap->available_size += RT_MEMHEAP_SIZE;
/* merge block with next neighbor. */
new_ptr = header_ptr->next;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
new_ptr, new_ptr->next_free, new_ptr->prev_free));
new_ptr->next->prev = header_ptr;
header_ptr->next = new_ptr->next;
/* remove new ptr from free list */
new_ptr->next_free->prev_free = new_ptr->prev_free;
new_ptr->prev_free->next_free = new_ptr->next_free;
}
如果当前的内存块前一个内存块非空闲,那么当前释放的内存块是需要放到空闲链表中
if (insert_header)
{
struct rt_memheap_item *n = heap->free_list->next_free;;
#if defined(RT_MEMHEAP_BSET_MODE)
rt_size_t blk_size = MEMITEM_SIZE(header_ptr);
for (;n != heap->free_list; n = n->next_free)
{
rt_size_t m = MEMITEM_SIZE(n);
if (blk_size <= m)
{
break;
}
}
#endif
/* no left merge, insert to free list */
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",
header_ptr->next_free, header_ptr->prev_free));
}
至此,我们基本就分析完MEMHEAP的实现。