@@ -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
11851362fc_weak bool fc_pool_dynamic_default (fc_pool_dynamic_type_t type , fc_pool_dynamic_mem_t * mem , size_t size )
0 commit comments