153 Star 687 Fork 533

OpenHarmony / kernel_liteos_m

 / 详情

基于TLSF的内存分配算法相关bug反馈与修正

待办的
缺陷
创建于  
2023-10-19 21:20

【模块名】:
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;
}

评论 (4)

xianbing256 创建了缺陷
xianbing256 修改了描述
展开全部操作日志

感谢提交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.

openharmony_ci 添加了
 
waiting_for_assign
标签
xianbing256 修改了标题
xianbing256 修改了描述
xianbing256 修改了描述
xianbing256 修改了描述
xianbing256 修改了描述

厉害,之前压测的时候就遇到过通过free命令查看内存明明有剩余但是申请内存失败的情况。大佬提一下PR吧 @xianbing256

xianbing256 修改了描述

麻烦大佬提交一下PR, @xianbing256

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(5)
7387629 openharmony ci 1656582662 13210807 hdyfzu 1691058178 1789850 fangye945a 1637807682
C
1
https://gitee.com/openharmony/kernel_liteos_m.git
git@gitee.com:openharmony/kernel_liteos_m.git
openharmony
kernel_liteos_m
kernel_liteos_m

搜索帮助