【模块名】:
kernel/src/mm/los_memory.c
OsMemFindNextSuitableBlock
【问题描述】:
UINT32 fl = OsMemFlGet(size);
if (fl < OS_MEM_SMALL_BUCKET_COUNT) {
index = fl;
} else {
sl = OsMemSlGet(size, fl);
curIndex = ((fl - OS_MEM_SMALL_BUCKET_COUNT) << OS_MEM_SLI) + sl + OS_MEM_SMALL_BUCKET_COUNT;
// 基于TLSF的内存分配算法实现,在遇到size>=128的内存分配时,index+1,向上一级申请更大的内存。
index = curIndex + 1;
}
会出现2个问题:
1、size=128的内存,在free后,空闲内存会被一直雪藏在freelist[31]。
如果用户申请size=128的内存,是不能直接从freelist[31]提取的,会从freelist[32,33,...,n]提取。
当且仅当freelist[32,33,...,n]均无可用节点时,才会从freelist[31]提取的内存。
这加剧了内存碎片化,并且产生了类似内存泄漏的风险。
2、freelist[32]存储size在[144,160)的节点。假定freelist[32]中有空闲内存,长度156。
用户申请内存size=[144,156]时,同问题1,并不会直接从freelist[32]提取,而是从freelist[33,34,...,n]提取。
如果匹配到size较大的freelist[64],size[2304,2560),会触发内存切割,导致内存分配的整体效率上降低。
并且,加剧内存碎片化。
【修正算法与实现】:
STATIC INLINE UINT32 OsMemSlGet(UINT32 size, UINT32 fl)
{
if ((fl < OS_MEM_SMALL_BUCKET_COUNT) || (size < OS_MEM_SMALL_BUCKET_MAX_SIZE)) {
PRINT_ERR("fl or size is too small, fl = %u, size = %u\n", fl, size);
return 0;
}
UINT32 add = size & ((1 << (fl - OS_MEM_SMALL_BUCKET_COUNT + OS_MEM_SLI + 1)) - 1) ? 1 : 0;
UINT32 sl = (size << OS_MEM_SLI) >> (fl - OS_MEM_SMALL_BUCKET_COUNT + OS_MEM_LARGE_START_BUCKET);
return (sl - (1 << OS_MEM_SLI) + add);
}
STATIC INLINE struct OsMemFreeNodeHead *OsMemFindNextSuitableBlock(VOID *pool, UINT32 size, UINT32 *outIndex)
{
struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
struct OsMemFreeNodeHead *node = NULL;
UINT32 index, curIndex;
// check every freeListBitmap.32bit, if greater or equal bit valid, match success.
for (curIndex = OsMemFreeListIndexGet(size);
curIndex < OS_MEM_FREE_LIST_COUNT;
curIndex = LOS_Align(curIndex + 1, 32)) {
for (index = curIndex; index < LOS_Align(curIndex + 1, 32); ++index) {
if (((index = OsMemNotEmptyIndexGet(poolHead, index)) != OS_MEM_FREE_LIST_COUNT) &&
((node = OsMemFindCurSuitableBlock(poolHead, index, size)) != NULL)) {
*outIndex = index;
return node;
}
}
}
// all freeListBitmap.32bit match failed.
return NULL;
}
感谢提交Issue!关于Issue的交互操作,请访问OpenHarmony社区支持命令清单。如果有问题,请联系 @zhushengle @LeonChan @JerryH 。如果需要调整订阅PR、Issue的变更状态,请访问链接。
Thanks for submitting the issue. For more commands, please visit OpenHarmony Command List. If you have any questions, please refer to committer @zhushengle @LeonChan @JerryH for help. If you need to change the subscription of a Pull Request or Issue, please visit the link.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
登录 后才可以发表评论