(源码可私信)
线性地址连续的block通过prev_node连接。
struct tlsf_node_head {
uint32_t magic;
union {
struct tlsf_node_head *prev; /* The prev is used for current node points to the previous node */
struct tlsf_node_head *next; /* The next is used for last node points to the expand node */
} ptr;
uint32_t size_and_flag; /* used to store the block size and status */
};
struct tlsf_used_node_head {
struct tlsf_node_head header;
};
当前内存块找下一个地址连续的内存块:
#define tlsf_NEXT_NODE(node) \
((struct tlsf_node_head *)(void *)((uint8_t *)(node) + tlsf_NODE_GET_SIZE((node)->size_and_flag)))
当前内存块找上一个地址连续的内存块:
struct tlsf_node_head *prev_node = node->ptr.prev;
同属相同区间的空闲内存块通过内部指针相连:
struct tlsf_free_node_head {
struct tlsf_node_head header;
struct tlsf_free_node_head *prev; /* used to points to prev free node */
struct tlsf_free_node_head *next; /* used to points to next free node */
};
内存池最后设置哨兵块,用于内存块合并时判断结尾使用:
Two-level Segregate fit (两级分割算法):

#define tlsf_SLI 3 /* 2^3 = 8, 每一个size等级被分成8份, 比如2^7~2^8-1,被分成8份 */
#define tlsf_LARGE_START_BUCKET 7 /* 大桶起始size大小 = 2^7 = 128 */
#define tlsf_LARGE_BUCKET_COUNT 24 /* 大桶按照幂级数分成24个区间,从2^7~2^30 */
#define tlsf_SMALL_BUCKET_COUNT 31 /* 小桶数量 */
#define tlsf_SMALL_BUCKET_MAX_SIZE 128 /* 小桶的最大size */
一些计算公式:
struct tlsf_free_node_head *free_list[tlsf_FREE_LIST_COUNT];
tlsf_FREE_LIST_COUNT = tlsf_SMALL_BUCKET_COUNT + tlsf_LARGE_BUCKET_COUNT * 2tlsf_SLI
#define tlsf_FREE_LIST_COUNT (tlsf_SMALL_BUCKET_COUNT + (tlsf_LARGE_BUCKET_COUNT << tlsf_SLI))
uint32_t free_bitmap[tlsf_BITMAP_WORDS];
tlsf_BITMAP_WORDS = tlsf_FREE_LIST_COUNT/32 + 1
#define tlsf_BITMAP_WORDS ((tlsf_FREE_LIST_COUNT >> 5) + 1)
根据size找到对应的free_list :
- size < 128 bytes:index = size/4 - 1;
- size >=128 bytes: index = (tlsf_SMALL_BUCKET_COUNT) + (log2(size)取整 - tlsf_LARGE_START_BUCKET) * 23 + sl
sl = (size - 2fl) / (2fl / 2tlsf_SLI) = [(size << tlsf_SLI) >> fl] - (1 << tlsf_SLI)
Ex: size = 129, fl = 129>>4 - 1 = 7, sl = (129 - 128)/(128/8) = 0, index = (31 + (7-7)*8 + 0 = 31,为第一个大桶的index。
内存池头:
/* mem pool head info */
struct tlsf_head_info {
void *pool; /* record pool addr only */
uint32_t total_size;
};
/* mem pool head */
struct tlsf_head {
struct tlsf_head_info info;
uint32_t free_bitmap[tlsf_BITMAP_WORDS];
struct tlsf_free_node_head *free_list[tlsf_FREE_LIST_COUNT];
pthread_mutex_t head_lock;
};
内存池初始化:
动态内存申请:
动态内存申请分成3步:【根据申请的size获取空闲块】+ 【分离空闲块】+【返回用户地址】。
空闲块获取:
static uint32_t tlsf_not_empty_index_get(struct tlsf_head *pool_head, uint32_t index)
{
uint32_t mask;
mask = pool_head->free_bitmap[BITMAP_INDEX(index)];
mask &= ~((1 << (index & tlsf_BITMAP_MASK)) - 1);
if (mask != 0) {
index = tlsf_ffs(mask) + (index & ~tlsf_BITMAP_MASK);
return index;
}
/* if mask == 0, return the bigest index */
return tlsf_FREE_LIST_COUNT;
}
static struct tlsf_free_node_head *tlsf_find_next_suitable_block(void *pool, uint32_t size, uint32_t *outindex)
{
struct tlsf_head *pool_head = (struct tlsf_head *)pool;
uint32_t fl = tlsf_fl_get(size);
uint32_t sl;
uint32_t index, tmp;
uint32_t cur_index = tlsf_FREE_LIST_COUNT;
uint32_t mask;
if (size < tlsf_SMALL_BUCKET_MAX_SIZE) {
index = fl;
} else {
sl = tlsf_sl_get(size, fl);
cur_index = ((fl - tlsf_LARGE_START_BUCKET) << tlsf_SLI) + sl + tlsf_SMALL_BUCKET_COUNT;
/* Good-fit to find the free_list in index+1 */
index = cur_index + 1;
}
tmp = tlsf_not_empty_index_get(pool_head, index);
/* find the free node for the giving index */
if (tmp != tlsf_FREE_LIST_COUNT) {
index = tmp;
*outindex = index;
return pool_head->free_list[index];
}
/* find the free node for the giving index to the next 32-bit boundary, always searching upwards */
for (index = tlsf_ALIGN(index+1, 32); index < tlsf_FREE_LIST_COUNT; index += 32) {
mask = pool_head->free_bitmap[BITMAP_INDEX(index)];
if (mask != 0) {
index = tlsf_ffs(mask) + index;
*outindex = index;
return pool_head->free_list[index];
}
}
if (cur_index == tlsf_FREE_LIST_COUNT) {
return NULL;
}
/* only best-bit now, find the free node in current index */
*outindex = cur_index;
return tlsf_find_current_suitable_block(pool_head, cur_index, size);
}
空闲块分离:
static void tlsf_split_node(void *pool, struct tlsf_node_head *alloc_node, uint32_t alloc_size)
{
struct tlsf_free_node_head *new_free_node = NULL;
struct tlsf_node_head *next_node = NULL;
/* get the next free node */
new_free_node = (struct tlsf_free_node_head *)(void *)((uint8_t *)alloc_node + alloc_size);
/* set the next free node prev node addr */
new_free_node->header.ptr.prev = alloc_node;
/* set next free node size */
new_free_node->header.size_and_flag = alloc_node->size_and_flag - alloc_size;
/* set the current alloc node size */
alloc_node->size_and_flag = alloc_size;
next_node = tlsf_NEXT_NODE(&new_free_node->header);
/* next node is not last node */
if (!tlsf_NODE_GET_LAST_FLAG(next_node->size_and_flag)) {
/* set next node's prev mem node */
next_node->ptr.prev = &new_free_node->header;
/* How could next node is not a free node?, but it's ok to do that */
if (!tlsf_NODE_GET_USED_FLAG(next_node->size_and_flag)) {
tlsf_free_node_delete(pool, (struct tlsf_free_node_head *)next_node);
/* merge next_node to new_free_node */
tlsf_merge_node(next_node);
}
}
tlsf_free_node_add(pool, new_free_node);
}
返回用户地址:
static void *tlsf_create_used_node(void *addr)
{
struct tlsf_used_node_head *node = (struct tlsf_used_node_head *)addr;
/* return to the user addr */
return node + 1;
}
动态内存释放:
动态内存申请分成3步:【合并逻辑地址连续前空闲节点】+ 【合并逻辑地址连续后空闲节点】+【将空闲节点放入free list】。
static void tlsf_free(struct tlsf_head *pool, struct tlsf_node_head *node)
{
if (!tlsf_check_used_node(pool, node)) {
return;
}
/* clear the used flag */
node->size_and_flag = tlsf_NODE_GET_SIZE(node->size_and_flag);
/* merge prev node if prev is free */
struct tlsf_node_head *prev_node = node->ptr.prev;
if ((prev_node != NULL) && !tlsf_NODE_GET_USED_FLAG(prev_node->size_and_flag)) {
tlsf_free_node_delete(pool, (struct tlsf_free_node_head *)prev_node);
tlsf_merge_node(node);
node = prev_node;
}
/* merge next node if next is free */
struct tlsf_node_head *next_node = tlsf_NEXT_NODE(node);
if ((next_node != NULL) && !tlsf_NODE_GET_USED_FLAG(next_node->size_and_flag)) {
tlsf_free_node_delete(pool, (struct tlsf_free_node_head *)next_node);
tlsf_merge_node(next_node);
}
/* add the node to free node list */
tlsf_free_node_add(pool, (struct tlsf_free_node_head *)node);
return;
}