Skip to content

Commit 252e14c

Browse files
committed
Merge branch 'develop' into CMSIS-Pack
2 parents 1e27dd8 + 744c152 commit 252e14c

3 files changed

Lines changed: 230 additions & 46 deletions

File tree

core/fc_pool.c

Lines changed: 222 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ int fc_pool_init(fc_pool_t *pool, void *mem, size_t mem_size, size_t block_size)
9494
uint8_t *start_addr = (uint8_t *)mem;
9595
size_t align = sizeof(size_t);
9696
size_t per_block_size = block_size + sizeof(fc_pool_header_t);
97-
fc_pool_header_t *node = &(pool->list_free);
97+
fc_pool_header_t *node = NULL;
9898

9999
memset(pool, 0, sizeof(fc_pool_t));
100100

@@ -135,20 +135,18 @@ int fc_pool_init(fc_pool_t *pool, void *mem, size_t mem_size, size_t block_size)
135135
pool->list_free.record_now = 0; // 初始化空闲块数
136136

137137
{
138-
fc_pool_header_t *first_node = NULL;
138+
node = &(pool->list_free);
139139

140-
for (size_t i = (size_t)start_addr; i < (size_t)mem + mem_size - per_block_size; i += per_block_size)
140+
for (size_t i = (size_t)start_addr; i <= (size_t)mem + mem_size - per_block_size; i += per_block_size)
141141
{
142142
node->next = (fc_pool_header_t *)i; // 链接下一个节点
143143
node = node->next; // 移动到下一个节点
144144
node->next = NULL; // 初始化下一个节点指向NULL
145145
node->linear_last = node; // 指向自己,自旋指示当前处于连续内存块
146146
// pool->list_free.record_now++; // 统计内存块数
147-
148-
first_node = pool->list_free.next; // 永远指向第一个节点
149-
first_node->linear_last = node; // 第一个节点指向最后一个节点
150147
}
151148

149+
pool->list_free.next->linear_last = node; // 第一个节点线性节点指向最后一个节点
152150
pool->list_free.record_now = (((size_t)mem + mem_size) - (size_t)(start_addr)) / per_block_size;
153151

154152
pool->sort_free_enable = false; // 默认不启用排序释放内存
@@ -456,7 +454,7 @@ void *fc_pool_alloc(fc_pool_t *pool, size_t *size)
456454
pool->list_free.next = node->next; // 移动空闲链表头部
457455
pool->list_free.record_now--; // 统计空闲块数
458456
pool->record_min = MIN(pool->record_min, pool->list_free.record_now);
459-
if ((size_t)(node->linear_last) != (size_t)node) // 非自旋节点,证明下一个节点跟这个节点是连续的(一定存在下一个节点)
457+
if ((size_t)(node->linear_last) != (size_t)node) // 非自旋节点,证明下一个节点跟这个节点是连续的(一定存在下一个节点),无需判断(NULL != node->next)
460458
{
461459
node->next->linear_last = node->linear_last; // 使下一个节点指向连续内存块的最后一个节点
462460
}
@@ -581,23 +579,22 @@ void fc_pool_free(fc_pool_t *pool, void *ptr)
581579
node = node->next; // node移动到下一个节点
582580
static_tail->next = NULL; // 断开这个节点与后面链接
583581

582+
if (static_tail->block_count > 1)
584583
{ // 拆分节点
585584
link_node = static_tail;
586585

587586
link_count = link_node->block_count; // 先记录下来,节点自旋之后会覆盖
588587
block_count += link_count;
589588
link_node->linear_last = link_node; // 节点自旋
590-
if (link_count > 1) // 需要拆分节点
589+
590+
for (; link_count > 1; link_count--)
591591
{
592-
for (; link_count > 1; link_count--)
593-
{
594-
link_node->next = (fc_pool_header_t *)((uint8_t *)link_node + node_size); // 拆分节点
595-
link_node = link_node->next; // 移动到下一个节点
596-
link_node->linear_last = link_node; // 节点自旋
597-
link_node->next = NULL; // 初始化下一个节点指向NULL
598-
}
599-
static_tail->linear_last = link_node; // 指向最后一个连续节点
592+
link_node->next = (fc_pool_header_t *)((uint8_t *)link_node + node_size); // 拆分节点
593+
link_node = link_node->next; // 移动到下一个节点
594+
link_node->linear_last = link_node; // 节点自旋
595+
link_node->next = NULL; // 初始化下一个节点指向NULL
600596
}
597+
static_tail->linear_last = link_node; // 指向最后一个连续节点
601598

602599
static_tail = link_node; // 更新static_tail
603600
}
@@ -609,14 +606,18 @@ void fc_pool_free(fc_pool_t *pool, void *ptr)
609606
link_node = static_head; // 从头遍历
610607
do
611608
{
612-
static_tail = link_node; // 前面用tail做临时变量记录一下这一次起始的第一个节点
613-
node = link_node->next; // 记住下一个节点
614-
link_count = link_node->block_count; // 先记录下来,节点自旋之后会覆盖
609+
link_count = link_node->block_count;
615610
block_count += link_count;
616-
link_node->linear_last = link_node; // 节点自旋
617-
618-
if (link_count > 1) // 需要拆分节点
611+
if (link_count <= 1)
619612
{
613+
static_tail = link_node; // 更新static_tail,最后赋值保证tail是最后一个节点就行
614+
link_node->linear_last = link_node; // 节点自旋
615+
link_node = link_node->next; // 移动到下一个节点
616+
}
617+
else // 需要拆分节点
618+
{
619+
static_tail = link_node; // 前面用tail做临时变量记录一下这一次起始的第一个节点
620+
node = link_node->next; // 记住下一个节点
620621
for (; link_count > 1; link_count--)
621622
{
622623
link_node->next = (fc_pool_header_t *)((uint8_t *)link_node + node_size); // 拆分节点
@@ -626,33 +627,44 @@ void fc_pool_free(fc_pool_t *pool, void *ptr)
626627
}
627628
link_node->next = node; // 链接下一个节点
628629
static_tail->linear_last = link_node; // 这一次起始的第一个节点指向最后一个连续节点
630+
static_tail = link_node; // 更新static_tail,最后赋值保证tail是最后一个节点就行
631+
link_node = node;
629632
}
630-
631-
static_tail = link_node; // 更新static_tail,最后赋值保证tail是最后一个节点就行
632-
link_node = node;
633633
} while (link_node);
634634
}
635635
#endif
636636

637637
if (true == pool->sort_free_enable) // 排序释放
638638
{
639+
fc_pool_header_t *after = NULL;
640+
fc_pool_header_t *prev = NULL;
641+
fc_pool_header_t *prev_first = NULL;
639642
link_node = static_head;
640643
while (link_node)
641644
{
642645
node = link_node->next; // 记住下一个节点
643-
block_count = 0; // 用与指示连续块的个数
646+
block_count = 1; // 用与指示当前连续块的个数
644647

645648
static_tail = link_node; // tail指针这里用不到,用来当临时变量使用
646649
for (;;)
647650
{
648-
block_count++; // 在前面已经被拆分好了
649651
link_node->linear_last = static_tail; // 头节点始终指向最后连续的最后一个节点
650-
651652
if (node && (size_t)node == (size_t)static_tail + node_size)
652653
{
653654
// 后面的节点跟这里是连续的
654-
static_tail = node; // 移动到下一个节点
655-
node = node->next; // 记录下一个节点
655+
static_tail = node; // 移动到下一个节点
656+
if ((size_t)node->linear_last == (size_t)node) // 自旋节点
657+
{
658+
block_count++;
659+
node = node->next; // 记录下一个节点
660+
}
661+
else
662+
{
663+
block_count += ((size_t)node->linear_last - (size_t)node) / node_size + 1;
664+
static_tail = node->linear_last; // 移动到最后一个连续节点
665+
node->linear_last = node; // 节点自旋
666+
node = static_tail->next; // 记录下一个节点
667+
}
656668
continue;
657669
}
658670
else
@@ -664,35 +676,66 @@ void fc_pool_free(fc_pool_t *pool, void *ptr)
664676

665677
// 开始合并到空闲链表
666678
{
667-
fc_pool_header_t *now = NULL;
668-
fc_pool_header_t *prev = &(pool->list_free); // 直接取pool->list_free地址,优化循环中的判断
679+
after = NULL;
680+
prev = NULL;
681+
prev_first = NULL;
669682
FC_ATOMIC_SCOPE
670683
{
671-
now = pool->list_free.next;
684+
after = pool->list_free.next;
672685
// 找到合适的位置插入,并判断能否与前后节点合并
673686
for (;;) // 最坏情况O(n)
674687
{
675-
if (NULL == now || (size_t)now > (size_t)link_node) // 找到指定位置了
688+
if ((size_t)after > (size_t)link_node) // 找到指定位置了
676689
{
677690
pool->list_free.record_now += block_count; // 空闲块数更新
678-
static_tail->next = now; // 最后一块链接到当前块
679-
prev->next = link_node; // 利用第一次直接取pool->list_free地址,避免了判断prev为空的情况
691+
static_tail->next = after; // 最后一块链接到当前块
692+
680693
// 先判断跟后面是否连续
681-
if (NULL != now && (size_t)(now) == (size_t)static_tail + node_size)
694+
if ((size_t)(after) == (size_t)static_tail + node_size)
695+
{
696+
link_node->linear_last = after->linear_last; // 头结点指向新的最后一个连续节点
697+
after->linear_last = after; // 自旋
698+
}
699+
if (prev)
700+
{
701+
prev->next = link_node;
702+
// 后判断跟前面是否连续
703+
if (NULL != prev_first && (size_t)(link_node) == (size_t)prev + node_size)
704+
{
705+
prev_first->linear_last = link_node->linear_last; // 更新最前面节点指向的最后一个连续节点
706+
link_node->linear_last = link_node; // 自旋
707+
}
708+
}
709+
else
710+
{
711+
pool->list_free.next = link_node;
712+
}
713+
break; // 合并完了退出
714+
}
715+
else if (NULL == after) // 后面已经没有节点了,只能插入到最后
716+
{
717+
pool->list_free.record_now += block_count; // 空闲块数更新
718+
static_tail->next = after; // 最后一块链接到当前块
719+
if (prev)
682720
{
683-
link_node->linear_last = now->linear_last; // 头结点指向新的最后一个连续节点
684-
now->linear_last = now; // 自旋
721+
prev->next = link_node;
722+
// 判断是否与前一个节点连续
723+
if (NULL != prev_first && (size_t)(link_node) == (size_t)prev + node_size)
724+
{
725+
prev_first->linear_last = link_node->linear_last; // 更新最前面节点指向的最后一个连续节点
726+
link_node->linear_last = link_node; // 自旋
727+
}
685728
}
686-
// 后判断跟前面是否连续
687-
if (NULL != now && (size_t)prev != (size_t)&(pool->list_free) && (size_t)(link_node) == (size_t)now + node_size)
729+
else
688730
{
689-
prev->linear_last = link_node->linear_last; // 更新最前面节点指向的最后一个连续节点
690-
link_node->linear_last = link_node; // 自旋
731+
pool->list_free.next = link_node;
691732
}
692733
break; // 合并完了退出
693734
}
694-
prev = now->linear_last; // 跳到最后一个连续节点,必不为NULL
695-
now = prev->next; // 跳到最后一个连续节点的下一个节点
735+
736+
prev_first = after; // 记录前一个连续内存的第一个节点
737+
prev = after->linear_last; // 跳到最后一个连续节点,必不为NULL
738+
after = prev->next; // 跳到最后一个连续节点的下一个节点
696739
}
697740
}
698741
}
@@ -1180,6 +1223,140 @@ void *fc_header_fifo_pop(fc_pool_header_t *header)
11801223
return (void *)(node ? (uint8_t *)node + sizeof(fc_pool_header_t) : NULL);
11811224
}
11821225

1226+
#if 0
1227+
/**
1228+
* @brief 检查内存池是否正常
1229+
*
1230+
* @param pool
1231+
* @return true
1232+
* @return false
1233+
*/
1234+
bool fc_pool_check(fc_pool_t *pool)
1235+
{
1236+
fc_assert(pool != NULL);
1237+
bool ret = true;
1238+
fc_pool_header_t *node = NULL;
1239+
fc_pool_header_t *temp = NULL;
1240+
1241+
{
1242+
FC_ATOMIC_SCOPE
1243+
{
1244+
node = pool->fifo_used.next;
1245+
while (node != NULL)
1246+
{
1247+
temp = node;
1248+
if (pool->sort_free_enable)
1249+
{
1250+
// 排序还要看内存顺序是否正常
1251+
if (temp->linear_last != temp)
1252+
{
1253+
size_t size = (((size_t)(temp->linear_last) - (size_t)temp)) / fc_pool_node_size(pool);
1254+
size += 1;
1255+
for (size_t i = 0; i < size; i++)
1256+
{
1257+
ret = (temp->next == (fc_pool_header_t *)((uint8_t *)temp + fc_pool_node_size(pool)));
1258+
temp = temp->next;
1259+
1260+
if (!ret)
1261+
{
1262+
break;
1263+
}
1264+
}
1265+
}
1266+
1267+
if (ret && temp->next != NULL)
1268+
{
1269+
ret = ((size_t)temp->next > (size_t)temp) ? true : false;
1270+
}
1271+
}
1272+
else
1273+
{
1274+
// 不管排序,只需要看内存块线性链接是否正常
1275+
if (temp->linear_last != temp)
1276+
{
1277+
size_t size = (((size_t)(temp->linear_last) - (size_t)temp)) / fc_pool_node_size(pool);
1278+
size += 1;
1279+
for (size_t i = 0; i < size; i++)
1280+
{
1281+
ret = (temp->next == (fc_pool_header_t *)((uint8_t *)temp + fc_pool_node_size(pool)));
1282+
temp = temp->next;
1283+
1284+
if (!ret)
1285+
{
1286+
break;
1287+
}
1288+
}
1289+
}
1290+
}
1291+
1292+
if (!ret)
1293+
{
1294+
break;
1295+
}
1296+
1297+
node = node->next;
1298+
}
1299+
}
1300+
}
1301+
1302+
return ret;
1303+
}
1304+
#endif
1305+
1306+
/**
1307+
* @brief 统计fifo used链表中最大连续内存块数
1308+
*
1309+
* @param pool
1310+
* @return size_t
1311+
*/
1312+
size_t fc_pool_max_linear_count(fc_pool_t *pool)
1313+
{
1314+
fc_assert(pool != NULL);
1315+
1316+
fc_pool_header_t *node = NULL;
1317+
size_t max_count = 0;
1318+
size_t count = 0;
1319+
{
1320+
FC_ATOMIC_SCOPE
1321+
{
1322+
node = pool->list_free.next;
1323+
while (node != NULL)
1324+
{
1325+
if (node->linear_last != node)
1326+
{
1327+
count = (((size_t)(node->linear_last) - (size_t)node)) / fc_pool_node_size(pool);
1328+
count += 1;
1329+
}
1330+
else
1331+
{
1332+
count = 1;
1333+
}
1334+
1335+
if (count > max_count)
1336+
{
1337+
max_count = count;
1338+
}
1339+
1340+
node = node->linear_last->next;
1341+
// node = node->next;
1342+
}
1343+
}
1344+
}
1345+
1346+
return max_count;
1347+
}
1348+
1349+
/**
1350+
* @brief 统计fifo used链表中最大连续内存块大小
1351+
*
1352+
* @param pool
1353+
* @return size_t
1354+
*/
1355+
size_t fc_pool_max_linear_size(fc_pool_t *pool)
1356+
{
1357+
return (fc_pool_node_size(pool) * fc_pool_max_linear_count(pool) - sizeof(fc_pool_header_t));
1358+
}
1359+
11831360
//+********************************* 提供一份默认的动态内存申请 **********************************/
11841361

11851362
fc_weak bool fc_pool_dynamic_default(fc_pool_dynamic_type_t type, fc_pool_dynamic_mem_t *mem, size_t size)

core/fc_pool.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ extern "C"
146146
#define fc_pool_fifo_pop(pool) \
147147
fc_header_fifo_pop(&((pool)->fifo_used))
148148

149+
//+********************************* 其他 **********************************/
150+
// bool fc_pool_check(fc_pool_t *pool); // 检查内存池是否正常
151+
size_t fc_pool_max_linear_count(fc_pool_t *pool); // 内存池最大连续内存块数
152+
size_t fc_pool_max_linear_size(fc_pool_t *pool); // 内存池最大连续内存块大小(字节)
153+
149154
//+********************************* 动态内存支持使用 **********************************/
150155

151156
// 提供了一份默认的动态内存分配实现,需要开启FC_FOOL_ENABLE_DYNAMIC_POOL_ALLOC宏定义

core/utils/fc_fifo_vprintf.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ static int __fc_fifo_vprintf_write(FC_FILE *f, const void *buf, int len)
3434

3535
if (len >= (int)FC_IO_SWAP) // 只可能==FC_IO_SWAP
3636
{
37-
fc_fifo_linear_write_done((fc_fifo_t *)(f->user), (size_t)f->p_now - (size_t)f->p_start);
37+
// 不能使用p_now,调用write的时候p_now已经等于NULL了,只有连续内存写完的时候会尝试调用一次更新连续内存
38+
// fc_fifo_linear_write_done((fc_fifo_t *)(f->user), (size_t)f->p_now - (size_t)f->p_start);
39+
fc_fifo_linear_write_done((fc_fifo_t *)(f->user), (size_t)f->p_end - (size_t)f->p_start);
3840

3941
// 还有空间
4042
if (fc_fifo_get_free((fc_fifo_t *)(f->user)) >= 1)

0 commit comments

Comments
 (0)