diff --git a/src/kernel_liteos_a/kernel/base/mem/common/los_memstat.c b/src/kernel_liteos_a/kernel/base/mem/common/los_memstat.c index 91164b4c..03815a3f 100644 --- a/src/kernel_liteos_a/kernel/base/mem/common/los_memstat.c +++ b/src/kernel_liteos_a/kernel/base/mem/common/los_memstat.c @@ -32,9 +32,9 @@ #include "los_memstat_pri.h" #include "los_task_pri.h" - +/// 记录每个任务对内存的使用情况 LITE_OS_SEC_BSS_MINOR STATIC TskMemUsedInfo g_tskMemUsedInfo[LOSCFG_BASE_CORE_TSK_LIMIT]; - +/// 计算指定任务对内存使用增加量 LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID) { if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) { @@ -43,9 +43,9 @@ LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID) if (OS_INT_ACTIVE) { return; } - g_tskMemUsedInfo[taskID].memUsed += usedSize; + g_tskMemUsedInfo[taskID].memUsed += usedSize; ///< 叠加 } - +/// 计算指定任务对内存使用减少量 LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedDec(UINT32 usedSize, UINT32 taskID) { if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) { @@ -59,9 +59,9 @@ LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedDec(UINT32 usedSize, UINT32 taskID) OsCurrTaskGet()->taskName, g_tskMemUsedInfo[taskID].memUsed, usedSize); return; } - g_tskMemUsedInfo[taskID].memUsed -= usedSize; + g_tskMemUsedInfo[taskID].memUsed -= usedSize; ///< 递减 } - +/// 获取指定任务对内存的使用情况 LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskMemUsage(UINT32 taskID) { if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) { @@ -70,7 +70,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskMemUsage(UINT32 taskID) return g_tskMemUsedInfo[taskID].memUsed; } - +/// 清空任务内存使用记录 LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemClear(UINT32 taskID) { if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) { @@ -82,8 +82,8 @@ LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemClear(UINT32 taskID) } g_tskMemUsedInfo[taskID].memUsed = 0; } - -#ifdef LOS_MEM_SLAB +// Slab是一种内存分配器,通过将内存划分不同大小的空间分配给对象使用来进行缓存管理,应用于内核对象的缓存。 +#ifdef LOS_MEM_SLAB // LITE_OS_SEC_BSS_MINOR STATIC TskSlabUsedInfo g_tskSlabUsedInfo[LOSCFG_BASE_CORE_TSK_LIMIT]; LITE_OS_SEC_TEXT_MINOR VOID OsTaskSlabUsedInc(UINT32 usedSize, UINT32 taskID) diff --git a/src/kernel_liteos_a/kernel/base/mem/membox/los_membox.c b/src/kernel_liteos_a/kernel/base/mem/membox/los_membox.c index 7a4b66de..4180d3bd 100644 --- a/src/kernel_liteos_a/kernel/base/mem/membox/los_membox.c +++ b/src/kernel_liteos_a/kernel/base/mem/membox/los_membox.c @@ -1,4 +1,22 @@ /* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CON/* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. * @@ -33,6 +51,211 @@ #include "los_hwi.h" #include "los_spinlock.h" +#ifdef LOSCFG_AARCH64 +#define OS_MEMBOX_MAGIC 0xa55a5aa5a55a5aa5 +#else +#define OS_MEMBOX_MAGIC 0xa55a5aa5 +#endif +#define OS_MEMBOX_SET_MAGIC(addr) \ + ((LOS_MEMBOX_NODE *)(addr))->pstNext = (LOS_MEMBOX_NODE *)OS_MEMBOX_MAGIC //设置魔法数字 +#define OS_MEMBOX_CHECK_MAGIC(addr) \ + ((((LOS_MEMBOX_NODE *)(addr))->pstNext == (LOS_MEMBOX_NODE *)OS_MEMBOX_MAGIC) ? LOS_OK : LOS_NOK) + +#define OS_MEMBOX_USER_ADDR(addr) \ + ((VOID *)((UINT8 *)(addr) + OS_MEMBOX_NODE_HEAD_SIZE)) +#define OS_MEMBOX_NODE_ADDR(addr) \ + ((LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) - OS_MEMBOX_NODE_HEAD_SIZE)) //节块 = (节头 + 节体) addr = 节体 +/* spinlock for mem module, only available on SMP mode */ +LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_memboxSpin); +#define MEMBOX_LOCK(state) LOS_SpinLockSave(&g_memboxSpin, &(state)) ///< 获取静态内存池自旋锁 +#define MEMBOX_UNLOCK(state) LOS_SpinUnlockRestore(&g_memboxSpin, (state))///< 释放静态内存池自旋锁 +/// 检查静态内存块 +STATIC INLINE UINT32 OsCheckBoxMem(const LOS_MEMBOX_INFO *boxInfo, const VOID *node) +{ + UINT32 offset; + + if (boxInfo->uwBlkSize == 0) { + return LOS_NOK; + } + + offset = (UINT32)((UINTPTR)node - (UINTPTR)(boxInfo + 1)); + if ((offset % boxInfo->uwBlkSize) != 0) { + return LOS_NOK; + } + + if ((offset / boxInfo->uwBlkSize) >= boxInfo->uwBlkNum) { + return LOS_NOK; + } + + return OS_MEMBOX_CHECK_MAGIC(node);//检查魔法数字是否被修改过了 +} +/// 初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小 +LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemboxInit(VOID *pool, UINT32 poolSize, UINT32 blkSize) +{ + LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;//在内存起始处安置池头 + LOS_MEMBOX_NODE *node = NULL; + UINT32 index; + UINT32 intSave; + + if (pool == NULL) { + return LOS_NOK; + } + + if (blkSize == 0) { + return LOS_NOK; + } + + if (poolSize < sizeof(LOS_MEMBOX_INFO)) { + return LOS_NOK; + } + + MEMBOX_LOCK(intSave); + boxInfo->uwBlkSize = LOS_MEMBOX_ALIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE); //节块总大小(节头+节体) + boxInfo->uwBlkNum = (poolSize - sizeof(LOS_MEMBOX_INFO)) / boxInfo->uwBlkSize;//总节块数量 + boxInfo->uwBlkCnt = 0; //已分配的数量 + if (boxInfo->uwBlkNum == 0) {//只有0块的情况 + MEMBOX_UNLOCK(intSave); + return LOS_NOK; + } + + node = (LOS_MEMBOX_NODE *)(boxInfo + 1);//去除池头,找到第一个节块位置 + + boxInfo->stFreeList.pstNext = node;//池头空闲链表指向第一个节块 + + for (index = 0; index < boxInfo->uwBlkNum - 1; ++index) {//切割节块,挂入空闲链表 + node->pstNext = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize);//按块大小切割好,统一由pstNext指向 + node = node->pstNext;//node存储了下一个节点的地址信息 + } + + node->pstNext = NULL;//最后一个为null + + MEMBOX_UNLOCK(intSave); + + return LOS_OK; +} +/// 从指定的静态内存池中申请一块静态内存块,整个内核源码只有 OsSwtmrScan中用到了静态内存. +LITE_OS_SEC_TEXT VOID *LOS_MemboxAlloc(VOID *pool) +{ + LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; + LOS_MEMBOX_NODE *node = NULL; + LOS_MEMBOX_NODE *nodeTmp = NULL; + UINT32 intSave; + + if (pool == NULL) { + return NULL; + } + + MEMBOX_LOCK(intSave); + node = &(boxInfo->stFreeList);//拿到空闲单链表 + if (node->pstNext != NULL) {//不需要遍历链表,因为这是空闲链表 + nodeTmp = node->pstNext;//先记录要使用的节点 + node->pstNext = nodeTmp->pstNext;//不再空闲了,把节点摘出去了. + OS_MEMBOX_SET_MAGIC(nodeTmp);//为已使用的节块设置魔法数字 + boxInfo->uwBlkCnt++;//已使用块数增加 + } + MEMBOX_UNLOCK(intSave); + + return (nodeTmp == NULL) ? NULL : OS_MEMBOX_USER_ADDR(nodeTmp);//返回可用的虚拟地址 +} +/// 释放指定的一块静态内存块 +LITE_OS_SEC_TEXT UINT32 LOS_MemboxFree(VOID *pool, VOID *box) +{ + LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; + UINT32 ret = LOS_NOK; + UINT32 intSave; + + if ((pool == NULL) || (box == NULL)) { + return LOS_NOK; + } + + MEMBOX_LOCK(intSave); + do { + LOS_MEMBOX_NODE *node = OS_MEMBOX_NODE_ADDR(box);//通过节体获取节块首地址 + if (OsCheckBoxMem(boxInfo, node) != LOS_OK) { + break; + } + + node->pstNext = boxInfo->stFreeList.pstNext;//节块指向空闲链表表头 + boxInfo->stFreeList.pstNext = node;//空闲链表表头反指向它,意味节块排到第一,下次申请将首个分配它 + boxInfo->uwBlkCnt--;//已经使用的内存块减一 + ret = LOS_OK; + } while (0);//将被编译时优化 + MEMBOX_UNLOCK(intSave); + + return ret; +} +/// 清零指定静态内存块的内容 +LITE_OS_SEC_TEXT_MINOR VOID LOS_MemboxClr(VOID *pool, VOID *box) +{ + LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; + + if ((pool == NULL) || (box == NULL)) { + return; + } + //将魔法数字一并清除了. + (VOID)memset_s(box, (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE), 0, + (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE)); +} +/// 打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、 +/// 内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址 +LITE_OS_SEC_TEXT_MINOR VOID LOS_ShowBox(VOID *pool) +{ + UINT32 index; + UINT32 intSave; + LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; + LOS_MEMBOX_NODE *node = NULL; + + if (pool == NULL) { + return; + } + MEMBOX_LOCK(intSave); + PRINT_INFO("membox(%p,0x%x,0x%x):\r\n", pool, boxInfo->uwBlkSize, boxInfo->uwBlkNum); + PRINT_INFO("free node list:\r\n"); + + for (node = boxInfo->stFreeList.pstNext, index = 0; node != NULL; + node = node->pstNext, ++index) { + PRINT_INFO("(%u,%p)\r\n", index, node); + } + + PRINT_INFO("all node list:\r\n"); + node = (LOS_MEMBOX_NODE *)(boxInfo + 1); + for (index = 0; index < boxInfo->uwBlkNum; ++index, node = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize)) { + PRINT_INFO("(%u,%p,%p)\r\n", index, node, node->pstNext); + } + MEMBOX_UNLOCK(intSave); +} +/// 获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小 +LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MemboxStatisticsGet(const VOID *boxMem, UINT32 *maxBlk, + UINT32 *blkCnt, UINT32 *blkSize) +{ + if ((boxMem == NULL) || (maxBlk == NULL) || (blkCnt == NULL) || (blkSize == NULL)) { + return LOS_NOK; + } + + *maxBlk = ((OS_MEMBOX_S *)boxMem)->uwBlkNum; + *blkCnt = ((OS_MEMBOX_S *)boxMem)->uwBlkCnt; + *blkSize = ((OS_MEMBOX_S *)boxMem)->uwBlkSize; + + return LOS_OK; +} + +TRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_membox.h" +#include "los_hwi.h" +#include "los_spinlock.h" + #ifdef LOSCFG_AARCH64 #define OS_MEMBOX_MAGIC 0xa55a5aa5a55a5aa5 diff --git a/src/kernel_liteos_a/kernel/base/mem/tlsf/los_memory.c b/src/kernel_liteos_a/kernel/base/mem/tlsf/los_memory.c index 3441b613..5086ca7b 100644 --- a/src/kernel_liteos_a/kernel/base/mem/tlsf/los_memory.c +++ b/src/kernel_liteos_a/kernel/base/mem/tlsf/los_memory.c @@ -43,7 +43,7 @@ #include "los_lms_pri.h" #endif -/* Used to cut non-essential functions. */ +/* Used to cut non-essential functions. | 用于削减非必要功能 */ #define OS_MEM_FREE_BY_TASKID 0 #ifdef LOSCFG_KERNEL_VM #define OS_MEM_EXPAND_ENABLE 1 @@ -56,32 +56,32 @@ /* column num of the output info of mem node */ #define OS_MEM_COLUMN_NUM 8 -UINT8 *m_aucSysMem0 = NULL; -UINT8 *m_aucSysMem1 = NULL; +UINT8 *m_aucSysMem0 = NULL; ///< 异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。 +UINT8 *m_aucSysMem1 = NULL; ///< (内核态)系统动态内存池地址的起始地址 #ifdef LOSCFG_MEM_MUL_POOL -VOID *g_poolHead = NULL; +VOID *g_poolHead = NULL; ///内存池头,由它牵引多个内存池 #endif /* The following is the macro definition and interface implementation related to the TLSF. */ /* Supposing a Second Level Index: SLI = 3. */ -#define OS_MEM_SLI 3 +#define OS_MEM_SLI 3 ///< 二级小区间级数, /* Giving 1 free list for each small bucket: 4, 8, 12, up to 124. */ -#define OS_MEM_SMALL_BUCKET_COUNT 31 -#define OS_MEM_SMALL_BUCKET_MAX_SIZE 128 -/* Giving OS_MEM_FREE_LIST_NUM free lists for each large bucket. */ -#define OS_MEM_LARGE_BUCKET_COUNT 24 -#define OS_MEM_FREE_LIST_NUM (1 << OS_MEM_SLI) +#define OS_MEM_SMALL_BUCKET_COUNT 31 ///< 小桶的偏移单位 从 4 ~ 124 ,共32级 +#define OS_MEM_SMALL_BUCKET_MAX_SIZE 128 ///< 小桶的最大数量 +/* Giving OS_MEM_FREE_LIST_NUM free lists for each large bucket. */ +#define OS_MEM_LARGE_BUCKET_COUNT 24 /// 为每个大存储桶空闲列表数量 大桶范围: [2^7, 2^31] ,每个小区间有分为 2^3个小区间 +#define OS_MEM_FREE_LIST_NUM (1 << OS_MEM_SLI) ///< 2^3 = 8 个,即大桶的每个区间又分为8个小区间 /* OS_MEM_SMALL_BUCKET_MAX_SIZE to the power of 2 is 7. */ -#define OS_MEM_LARGE_START_BUCKET 7 +#define OS_MEM_LARGE_START_BUCKET 7 /// 大桶的开始下标 /* The count of free list. */ -#define OS_MEM_FREE_LIST_COUNT (OS_MEM_SMALL_BUCKET_COUNT + (OS_MEM_LARGE_BUCKET_COUNT << OS_MEM_SLI)) +#define OS_MEM_FREE_LIST_COUNT (OS_MEM_SMALL_BUCKET_COUNT + (OS_MEM_LARGE_BUCKET_COUNT << OS_MEM_SLI)) ///< 总链表的数量 32 + 24 * 8 = 224 /* The bitmap is used to indicate whether the free list is empty, 1: not empty, 0: empty. */ -#define OS_MEM_BITMAP_WORDS ((OS_MEM_FREE_LIST_COUNT >> 5) + 1) - -#define OS_MEM_BITMAP_MASK 0x1FU +#define OS_MEM_BITMAP_WORDS ((OS_MEM_FREE_LIST_COUNT >> 5) + 1) ///< 224 >> 5 + 1 = 7 ,为什么要右移 5 因为 2^5 = 32 是一个32位整型的大小 + ///< 而 32 * 7 = 224 ,也就是说用 int[7]当位图就能表示完 224个链表 ,此处,一定要理解好,因为这是理解 TLSF 算法的关键. +#define OS_MEM_BITMAP_MASK 0x1FU ///< 因为一个int型为 32位, 2^5 = 32,所以此处 0x1FU = 5个1 足以. /* Used to find the first bit of 1 in bitmap. */ STATIC INLINE UINT16 OsMemFFS(UINT32 bitmap) @@ -101,7 +101,7 @@ STATIC INLINE UINT32 OsMemLog2(UINT32 size) return OsMemFLS(size); } -/* Get the first level: f = log2(size). */ +/* Get the first level: f = log2(size). | 获取第一级*/ STATIC INLINE UINT32 OsMemFlGet(UINT32 size) { if (size < OS_MEM_SMALL_BUCKET_MAX_SIZE) { @@ -110,56 +110,56 @@ STATIC INLINE UINT32 OsMemFlGet(UINT32 size) return OsMemLog2(size); } -/* Get the second level: s = (size - 2^f) * 2^SLI / 2^f. */ +/* Get the second level: s = (size - 2^f) * 2^SLI / 2^f. | 获取第二级 */ STATIC INLINE UINT32 OsMemSlGet(UINT32 size, UINT32 fl) { return (((size << OS_MEM_SLI) >> fl) - OS_MEM_FREE_LIST_NUM); } /* The following is the memory algorithm related macro definition and interface implementation. */ - +/// 内存池节点 struct OsMemNodeHead { - UINT32 magic; - union { - struct OsMemNodeHead *prev; /* The prev is used for current node points to the previous node */ - struct OsMemNodeHead *next; /* The next is used for last node points to the expand node */ + UINT32 magic; ///< 魔法数字 0xABCDDCBA + union {//注意这里的前后指向的是连续的地址节点,用于分割和合并 + struct OsMemNodeHead *prev; /* The prev is used for current node points to the previous node | prev 用于当前节点指向前一个节点*/ + struct OsMemNodeHead *next; /* The next is used for last node points to the expand node | next 用于最后一个节点指向展开节点*/ } ptr; -#ifdef LOSCFG_MEM_LEAKCHECK - UINTPTR linkReg[LOS_RECORD_LR_CNT]; +#ifdef LOSCFG_MEM_LEAKCHECK //内存泄漏检测 + UINTPTR linkReg[LOS_RECORD_LR_CNT];///< 存放左右节点地址,用于检测 #endif - UINT32 sizeAndFlag; + UINT32 sizeAndFlag; ///< 节点总大小+标签 }; - +/// 已使用内存池节点 struct OsMemUsedNodeHead { - struct OsMemNodeHead header; + struct OsMemNodeHead header;///< 已被使用节点 #if OS_MEM_FREE_BY_TASKID - UINT32 taskID; + UINT32 taskID; ///< 使用节点的任务ID #endif }; - +/// 内存池空闲节点 struct OsMemFreeNodeHead { - struct OsMemNodeHead header; - struct OsMemFreeNodeHead *prev; - struct OsMemFreeNodeHead *next; + struct OsMemNodeHead header; ///< 内存池节点 + struct OsMemFreeNodeHead *prev; ///< 前一个空闲前驱节点 + struct OsMemFreeNodeHead *next; ///< 后一个空闲后继节点 }; - +/// 内存池信息 struct OsMemPoolInfo { - VOID *pool; - UINT32 totalSize; - UINT32 attr; + VOID *pool; ///< 指向内存块基地址,仅做记录而已,真正的分配内存跟它没啥关系 + UINT32 totalSize; ///< 总大小,确定了内存池的边界 + UINT32 attr; ///< 属性 default attr: lock, not expand. #ifdef LOSCFG_MEM_WATERLINE - UINT32 waterLine; /* Maximum usage size in a memory pool */ - UINT32 curUsedSize; /* Current usage size in a memory pool */ + UINT32 waterLine; /* Maximum usage size in a memory pool | 内存吃水线*/ + UINT32 curUsedSize; /* Current usage size in a memory pool | 当前已使用大小*/ #endif }; - +/// 内存池头信息 struct OsMemPoolHead { - struct OsMemPoolInfo info; - UINT32 freeListBitmap[OS_MEM_BITMAP_WORDS]; - struct OsMemFreeNodeHead *freeList[OS_MEM_FREE_LIST_COUNT]; - SPIN_LOCK_S spinlock; + struct OsMemPoolInfo info; ///< 记录内存池的信息 + UINT32 freeListBitmap[OS_MEM_BITMAP_WORDS]; ///< 空闲位图 int[7] = 32 * 7 = 224 > 223 + struct OsMemFreeNodeHead *freeList[OS_MEM_FREE_LIST_COUNT];///< 空闲节点链表 32 + 24 * 8 = 224 + SPIN_LOCK_S spinlock; ///< 操作本池的自旋锁,涉及CPU多核竞争,所以必须得是自旋锁 #ifdef LOSCFG_MEM_MUL_POOL - VOID *nextPool; + VOID *nextPool; ///< 指向下一个内存池 OsMemPoolHead 类型 #endif }; @@ -168,16 +168,16 @@ struct OsMemPoolHead { #define MEM_UNLOCK(pool, state) LOS_SpinUnlockRestore(&(pool)->spinlock, (state)) /* The memory pool support expand. */ -#define OS_MEM_POOL_EXPAND_ENABLE 0x01 +#define OS_MEM_POOL_EXPAND_ENABLE 0x01 ///< 支持扩展 /* The memory pool support no lock. */ -#define OS_MEM_POOL_LOCK_ENABLE 0x02 - -#define OS_MEM_NODE_MAGIC 0xABCDDCBA -#define OS_MEM_MIN_ALLOC_SIZE (sizeof(struct OsMemFreeNodeHead) - sizeof(struct OsMemUsedNodeHead)) - -#define OS_MEM_NODE_USED_FLAG 0x80000000U -#define OS_MEM_NODE_ALIGNED_FLAG 0x40000000U -#define OS_MEM_NODE_LAST_FLAG 0x20000000U /* Sentinel Node */ +#define OS_MEM_POOL_LOCK_ENABLE 0x02 ///< 加锁 + +#define OS_MEM_NODE_MAGIC 0xABCDDCBA ///< 内存节点的魔法数字 +#define OS_MEM_MIN_ALLOC_SIZE (sizeof(struct OsMemFreeNodeHead) - sizeof(struct OsMemUsedNodeHead)) //最小分配空间 +// 必须给指向空闲块的指针留位置 +#define OS_MEM_NODE_USED_FLAG 0x80000000U ///< 已使用标签 +#define OS_MEM_NODE_ALIGNED_FLAG 0x40000000U ///< 对齐标签 +#define OS_MEM_NODE_LAST_FLAG 0x20000000U /* Sentinel Node | 哨兵节点标签*/ #define OS_MEM_NODE_ALIGNED_AND_USED_FLAG (OS_MEM_NODE_USED_FLAG | OS_MEM_NODE_ALIGNED_FLAG | OS_MEM_NODE_LAST_FLAG) #define OS_MEM_NODE_GET_ALIGNED_FLAG(sizeAndFlag) \ @@ -226,32 +226,33 @@ STATIC INLINE UINT32 OsMemAllocCheck(struct OsMemPoolHead *pool, UINT32 intSave) #if OS_MEM_FREE_BY_TASKID STATIC INLINE VOID OsMemNodeSetTaskID(struct OsMemUsedNodeHead *node) { - node->taskID = LOS_CurTaskIDGet(); + node->taskID = LOS_CurTaskIDGet();//将当前任务ID绑定到内存池节点上 } #endif #ifdef LOSCFG_MEM_WATERLINE STATIC INLINE VOID OsMemWaterUsedRecord(struct OsMemPoolHead *pool, UINT32 size) { - pool->info.curUsedSize += size; + pool->info.curUsedSize += size; //延长可使用空间 if (pool->info.curUsedSize > pool->info.waterLine) { - pool->info.waterLine = pool->info.curUsedSize; + pool->info.waterLine = pool->info.curUsedSize; //警戒线加高 } } #else STATIC INLINE VOID OsMemWaterUsedRecord(struct OsMemPoolHead *pool, UINT32 size) { - (VOID)pool; - (VOID)size; + (VOID)pool; + (VOID)size; } #endif #if OS_MEM_EXPAND_ENABLE +/// 更新哨兵节点内容 STATIC INLINE struct OsMemNodeHead *OsMemLastSentinelNodeGet(const struct OsMemNodeHead *sentinelNode) { struct OsMemNodeHead *node = NULL; - VOID *ptr = sentinelNode->ptr.next; - UINT32 size = OS_MEM_NODE_GET_SIZE(sentinelNode->sizeAndFlag); + VOID *ptr = sentinelNode->ptr.next;//返回不连续的内存块 + UINT32 size = OS_MEM_NODE_GET_SIZE(sentinelNode->sizeAndFlag); // 获取大小 while ((ptr != NULL) && (size != 0)) { node = OS_MEM_END_NODE(ptr, size); @@ -261,7 +262,7 @@ STATIC INLINE struct OsMemNodeHead *OsMemLastSentinelNodeGet(const struct OsMemN return node; } - +/// 检查哨兵节点 STATIC INLINE BOOL OsMemSentinelNodeCheck(struct OsMemNodeHead *sentinelNode) { if (!OS_MEM_NODE_GET_USED_FLAG(sentinelNode->sizeAndFlag)) { @@ -274,7 +275,7 @@ STATIC INLINE BOOL OsMemSentinelNodeCheck(struct OsMemNodeHead *sentinelNode) return TRUE; } - +/// 是否为最后一个哨兵节点 STATIC INLINE BOOL OsMemIsLastSentinelNode(struct OsMemNodeHead *sentinelNode) { if (OsMemSentinelNodeCheck(sentinelNode) == FALSE) { @@ -289,11 +290,11 @@ STATIC INLINE BOOL OsMemIsLastSentinelNode(struct OsMemNodeHead *sentinelNode) return FALSE; } - +/// 设置哨兵节点内容 STATIC INLINE VOID OsMemSentinelNodeSet(struct OsMemNodeHead *sentinelNode, VOID *newNode, UINT32 size) { - if (sentinelNode->ptr.next != NULL) { - sentinelNode = OsMemLastSentinelNodeGet(sentinelNode); + if (sentinelNode->ptr.next != NULL) { //哨兵节点有 逻辑地址不连续的衔接内存块 + sentinelNode = OsMemLastSentinelNodeGet(sentinelNode);//更新哨兵节点内容 } sentinelNode->sizeAndFlag = size; @@ -329,14 +330,14 @@ STATIC INLINE struct OsMemNodeHead *PreSentinelNodeGet(const VOID *pool, const s return NULL; } - +/// 大内存释放 UINT32 OsMemLargeNodeFree(const VOID *ptr) { - LosVmPage *page = OsVmVaddrToPage((VOID *)ptr); + LosVmPage *page = OsVmVaddrToPage((VOID *)ptr);//获取物理页 if ((page == NULL) || (page->nPages == 0)) { return LOS_NOK; } - LOS_PhysPagesFreeContiguous((VOID *)ptr, page->nPages); + LOS_PhysPagesFreeContiguous((VOID *)ptr, page->nPages);//释放连续的几个物理页 return LOS_OK; } @@ -375,7 +376,7 @@ STATIC INLINE BOOL TryShrinkPool(const VOID *pool, const struct OsMemNodeHead *n #endif return TRUE; } - +/// 内存池扩展实现 STATIC INLINE INT32 OsMemPoolExpandSub(VOID *pool, UINT32 size, UINT32 intSave) { UINT32 tryCount = MAX_SHRINK_PAGECACHE_TRY; @@ -383,11 +384,11 @@ STATIC INLINE INT32 OsMemPoolExpandSub(VOID *pool, UINT32 size, UINT32 intSave) struct OsMemNodeHead *newNode = NULL; struct OsMemNodeHead *endNode = NULL; - size = ROUNDUP(size + OS_MEM_NODE_HEAD_SIZE, PAGE_SIZE); - endNode = OS_MEM_END_NODE(pool, poolInfo->info.totalSize); + size = ROUNDUP(size + OS_MEM_NODE_HEAD_SIZE, PAGE_SIZE);//圆整 + endNode = OS_MEM_END_NODE(pool, poolInfo->info.totalSize);//获取哨兵节点 RETRY: - newNode = (struct OsMemNodeHead *)LOS_PhysPagesAllocContiguous(size >> PAGE_SHIFT); + newNode = (struct OsMemNodeHead *)LOS_PhysPagesAllocContiguous(size >> PAGE_SHIFT);//申请新的内存池 | 物理内存 if (newNode == NULL) { if (tryCount > 0) { tryCount--; @@ -411,26 +412,26 @@ RETRY: size = (resize == 0) ? size : resize; } #endif - newNode->sizeAndFlag = (size - OS_MEM_NODE_HEAD_SIZE); - newNode->ptr.prev = OS_MEM_END_NODE(newNode, size); - OsMemSentinelNodeSet(endNode, newNode, size); - OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode); + newNode->sizeAndFlag = (size - OS_MEM_NODE_HEAD_SIZE);//设置新节点大小 + newNode->ptr.prev = OS_MEM_END_NODE(newNode, size);//新节点的前节点指向新节点的哨兵节点 + OsMemSentinelNodeSet(endNode, newNode, size);//设置老内存池的哨兵节点信息,其实就是指向新内存块 + OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode);//将新节点加入空闲链表 - endNode = OS_MEM_END_NODE(newNode, size); - (VOID)memset(endNode, 0, sizeof(*endNode)); - endNode->ptr.next = NULL; - endNode->magic = OS_MEM_NODE_MAGIC; - OsMemSentinelNodeSet(endNode, NULL, 0); - OsMemWaterUsedRecord(poolInfo, OS_MEM_NODE_HEAD_SIZE); + endNode = OS_MEM_END_NODE(newNode, size);//获取新节点的哨兵节点 + (VOID)memset(endNode, 0, sizeof(*endNode));//清空内存 + endNode->ptr.next = NULL;//新哨兵节点没有后续指向,因为它已成为最后 + endNode->magic = OS_MEM_NODE_MAGIC;//设置新哨兵节的魔法数字 + OsMemSentinelNodeSet(endNode, NULL, 0); //设置新哨兵节点内容 + OsMemWaterUsedRecord(poolInfo, OS_MEM_NODE_HEAD_SIZE);//更新内存池警戒线 return 0; } - +/// 扩展内存池 STATIC INLINE INT32 OsMemPoolExpand(VOID *pool, UINT32 allocSize, UINT32 intSave) { - UINT32 expandDefault = MEM_EXPAND_SIZE(LOS_MemPoolSizeGet(pool)); + UINT32 expandDefault = MEM_EXPAND_SIZE(LOS_MemPoolSizeGet(pool));//至少要扩展现有内存池的 1/8 大小 UINT32 expandSize = MAX(expandDefault, allocSize); - UINT32 tryCount = 1; + UINT32 tryCount = 1;//尝试次数 UINT32 ret; do { @@ -447,7 +448,7 @@ STATIC INLINE INT32 OsMemPoolExpand(VOID *pool, UINT32 allocSize, UINT32 intSave return -1; } - +///< 允许指定内存池扩展 VOID LOS_MemExpandEnable(VOID *pool) { if (pool == NULL) { @@ -486,7 +487,7 @@ STATIC INLINE VOID OsLmsAllocAlignMark(VOID *ptr, VOID *alignedPtr, UINT32 size) g_lms->simpleMark((UINTPTR)ptr + sizeof(UINT32), (UINTPTR)alignedPtr, LMS_SHADOW_REDZONE_U8); } - /* mark remaining as redzone */ + /* mark remining as redzone */ g_lms->simpleMark(LMS_ADDR_ALIGN((UINTPTR)alignedPtr + size), (UINTPTR)OS_MEM_NEXT_NODE(allocNode), LMS_SHADOW_REDZONE_U8); } @@ -522,8 +523,7 @@ STATIC INLINE VOID OsLmsReallocResizeMark(struct OsMemNodeHead *node, UINT32 res g_lms->simpleMark((UINTPTR)node + resize, (UINTPTR)OS_MEM_NEXT_NODE(node), LMS_SHADOW_REDZONE_U8); } #endif - -#ifdef LOSCFG_MEM_LEAKCHECK +#ifdef LOSCFG_MEM_LEAKCHECK //内存泄漏检查 STATIC INLINE VOID OsMemLinkRegisterRecord(struct OsMemNodeHead *node) { LOS_RecordLR(node->linkReg, LOS_RECORD_LR_CNT, LOS_RECORD_LR_CNT, LOS_OMIT_LR_CNT); @@ -549,7 +549,7 @@ STATIC INLINE VOID OsMemUsedNodePrint(struct OsMemNodeHead *node) PRINTK("\n"); } } - +/// 打印已使用的节点 VOID OsMemUsedNodeShow(VOID *pool) { if (pool == NULL) { @@ -626,17 +626,17 @@ STATIC VOID OsMemNodeBacktraceInfo(const struct OsMemNodeHead *tmpNode, STATIC INLINE UINT32 OsMemFreeListIndexGet(UINT32 size) { - UINT32 fl = OsMemFlGet(size); + UINT32 fl = OsMemFlGet(size);//获取一级位图 if (size < OS_MEM_SMALL_BUCKET_MAX_SIZE) { return fl; } - UINT32 sl = OsMemSlGet(size, fl); + UINT32 sl = OsMemSlGet(size, fl);//获取二级位图 return (OS_MEM_SMALL_BUCKET_COUNT + ((fl - OS_MEM_LARGE_START_BUCKET) << OS_MEM_SLI) + sl); } STATIC INLINE struct OsMemFreeNodeHead *OsMemFindCurSuitableBlock(struct OsMemPoolHead *poolHead, - UINT32 index, UINT32 size) + UINT32 index, UINT32 size) { struct OsMemFreeNodeHead *node = NULL; @@ -663,7 +663,7 @@ STATIC INLINE UINT32 OsMemNotEmptyIndexGet(struct OsMemPoolHead *poolHead, UINT3 return OS_MEM_FREE_LIST_COUNT; } - +/// 找到下一个合适的块 STATIC INLINE struct OsMemFreeNodeHead *OsMemFindNextSuitableBlock(VOID *pool, UINT32 size, UINT32 *outIndex) { struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool; @@ -730,13 +730,13 @@ STATIC INLINE VOID OsMemListAdd(struct OsMemPoolHead *pool, UINT32 listIndex, st OsMemSetFreeListBit(pool, listIndex); node->header.magic = OS_MEM_NODE_MAGIC; } - +/// 从空闲链表中删除 STATIC INLINE VOID OsMemListDelete(struct OsMemPoolHead *pool, UINT32 listIndex, struct OsMemFreeNodeHead *node) { if (node == pool->freeList[listIndex]) { pool->freeList[listIndex] = node->next; - if (node->next == NULL) { - OsMemClearFreeListBit(pool, listIndex); + if (node->next == NULL) {//如果链表空了 + OsMemClearFreeListBit(pool, listIndex);//将位图位 置为 0 } else { node->next->prev = NULL; } @@ -748,27 +748,27 @@ STATIC INLINE VOID OsMemListDelete(struct OsMemPoolHead *pool, UINT32 listIndex, } node->header.magic = OS_MEM_NODE_MAGIC; } - +/// 添加一个空闲节点 STATIC INLINE VOID OsMemFreeNodeAdd(VOID *pool, struct OsMemFreeNodeHead *node) { - UINT32 index = OsMemFreeListIndexGet(node->header.sizeAndFlag); + UINT32 index = OsMemFreeListIndexGet(node->header.sizeAndFlag);//根据大小定位索引位 if (index >= OS_MEM_FREE_LIST_COUNT) { LOS_Panic("The index of free lists is error, index = %u\n", index); return; } - OsMemListAdd(pool, index, node); + OsMemListAdd(pool, index, node);//挂入链表 } - +/// 从空闲链表上摘除节点 STATIC INLINE VOID OsMemFreeNodeDelete(VOID *pool, struct OsMemFreeNodeHead *node) { - UINT32 index = OsMemFreeListIndexGet(node->header.sizeAndFlag); + UINT32 index = OsMemFreeListIndexGet(node->header.sizeAndFlag);//根据大小定位索引位 if (index >= OS_MEM_FREE_LIST_COUNT) { LOS_Panic("The index of free lists is error, index = %u\n", index); return; } OsMemListDelete(pool, index, node); } - +//获取一个空闲的节点 STATIC INLINE struct OsMemNodeHead *OsMemFreeNodeGet(VOID *pool, UINT32 size) { struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool; @@ -782,56 +782,67 @@ STATIC INLINE struct OsMemNodeHead *OsMemFreeNodeGet(VOID *pool, UINT32 size) return &firstNode->header; } - +/// 合并节点,和前面的节点合并 node 消失 STATIC INLINE VOID OsMemMergeNode(struct OsMemNodeHead *node) { struct OsMemNodeHead *nextNode = NULL; - node->ptr.prev->sizeAndFlag += node->sizeAndFlag; - nextNode = (struct OsMemNodeHead *)((UINTPTR)node + node->sizeAndFlag); - if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) { - nextNode->ptr.prev = node->ptr.prev; + node->ptr.prev->sizeAndFlag += node->sizeAndFlag; //前节点长度变长 + nextNode = (struct OsMemNodeHead *)((UINTPTR)node + node->sizeAndFlag); // 下一个节点位置 + if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) {//不是哨兵节点 + nextNode->ptr.prev = node->ptr.prev;//后一个节点的前节点变成前前节点 } } - +/// 切割节点 STATIC INLINE VOID OsMemSplitNode(VOID *pool, struct OsMemNodeHead *allocNode, UINT32 allocSize) { struct OsMemFreeNodeHead *newFreeNode = NULL; struct OsMemNodeHead *nextNode = NULL; - newFreeNode = (struct OsMemFreeNodeHead *)(VOID *)((UINT8 *)allocNode + allocSize); - newFreeNode->header.ptr.prev = allocNode; - newFreeNode->header.sizeAndFlag = allocNode->sizeAndFlag - allocSize; - allocNode->sizeAndFlag = allocSize; - nextNode = OS_MEM_NEXT_NODE(&newFreeNode->header); - if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) { - nextNode->ptr.prev = &newFreeNode->header; - if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->sizeAndFlag)) { - OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode); - OsMemMergeNode(nextNode); + newFreeNode = (struct OsMemFreeNodeHead *)(VOID *)((UINT8 *)allocNode + allocSize);//切割后出现的新空闲节点,在分配节点的右侧 + newFreeNode->header.ptr.prev = allocNode;//新节点指向前节点,说明是从左到右切割 + newFreeNode->header.sizeAndFlag = allocNode->sizeAndFlag - allocSize;//新空闲节点大小 + allocNode->sizeAndFlag = allocSize;//分配节点大小 + nextNode = OS_MEM_NEXT_NODE(&newFreeNode->header);//获取新节点的下一个节点 + if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) {//如果下一个节点不是哨兵节点(末尾节点) + nextNode->ptr.prev = &newFreeNode->header;//下一个节点的前节点为新空闲节点 + if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->sizeAndFlag)) {//如果下一个节点也是空闲的 + OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode);//删除下一个节点信息 + OsMemMergeNode(nextNode);//下一个节点和新空闲节点 合并成一个新节点 } } - OsMemFreeNodeAdd(pool, newFreeNode); + OsMemFreeNodeAdd(pool, newFreeNode);//挂入空闲链表 } - +// STATIC INLINE VOID *OsMemCreateUsedNode(VOID *addr) { - struct OsMemUsedNodeHead *node = (struct OsMemUsedNodeHead *)addr; - + struct OsMemUsedNodeHead *node = (struct OsMemUsedNodeHead *)addr;//直接将地址转成使用节点,说明节点信息也存在内存池中 + //这种用法是非常巧妙的 #if OS_MEM_FREE_BY_TASKID - OsMemNodeSetTaskID(node); + OsMemNodeSetTaskID(node);//设置使用内存节点的任务 #endif -#ifdef LOSCFG_KERNEL_LMS +#ifdef LOSCFG_KERNEL_LMS //检测内存泄漏 struct OsMemNodeHead *newNode = (struct OsMemNodeHead *)node; if (g_lms != NULL) { g_lms->mallocMark(newNode, OS_MEM_NEXT_NODE(newNode), OS_MEM_NODE_HEAD_SIZE); } #endif - return node + 1; + return node + 1; //@note_good 这个地方挺有意思的,只是将结构体扩展下,留一个 int 位 ,变成了已使用节点,返回的地址正是要分配给应用的地址 } +/*! + * @brief OsMemPoolInit 内存池初始化 + * 内存池节点部分包含3种类型节点:未使用空闲内存节点(OsMemFreeNodeHead),已使用内存节点(OsMemUsedNodeHead) 和 尾节点(OsMemNodeHead)。 + * \n 每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。 + * \n 空闲内存节点和已使用内存节点后面的内存区域是数据域 + * @param pool + * @param size + * @return + * + * @see + */ STATIC UINT32 OsMemPoolInit(VOID *pool, UINT32 size) { struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool; @@ -853,30 +864,32 @@ STATIC UINT32 OsMemPoolInit(VOID *pool, UINT32 size) #endif LOS_SpinInit(&poolHead->spinlock); - poolHead->info.pool = pool; - poolHead->info.totalSize = size; - poolHead->info.attr = OS_MEM_POOL_LOCK_ENABLE; /* default attr: lock, not expand. */ + poolHead->info.pool = pool; //内存池的起始地址,但注意真正的内存并不是从此处分配,它只是用来记录这个内存块的开始位置而已. + poolHead->info.totalSize = size;//内存池总大小 + poolHead->info.attr = OS_MEM_POOL_LOCK_ENABLE; /* default attr: lock, not expand. | 默认是上锁,不支持扩展,需扩展得另外设置*/ - newNode = OS_MEM_FIRST_NODE(pool); - newNode->sizeAndFlag = (size - sizeof(struct OsMemPoolHead) - OS_MEM_NODE_HEAD_SIZE); - newNode->ptr.prev = NULL; - newNode->magic = OS_MEM_NODE_MAGIC; - OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode); + newNode = OS_MEM_FIRST_NODE(pool);//跳到第一个节点位置,即跳过结构体本身位置,真正的分配内存是从newNode开始的. + newNode->sizeAndFlag = (size - sizeof(struct OsMemPoolHead) - OS_MEM_NODE_HEAD_SIZE);//这才是可供分配给外界使用的总内存块大小,即数据域 + //OS_MEM_NODE_HEAD_SIZE 叫当前使用节点,即指 newNode占用的空间 + newNode->ptr.prev = NULL;//开始是空指向 + newNode->magic = OS_MEM_NODE_MAGIC;//魔法数字 用于标识这是一个 OsMemNodeHead 节点, 魔法数字不能被覆盖, + OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode);//添加一个空闲节点,由此有了首个可供分配的空闲节点 /* The last mem node */ - endNode = OS_MEM_END_NODE(pool, size); - endNode->magic = OS_MEM_NODE_MAGIC; -#if OS_MEM_EXPAND_ENABLE - endNode->ptr.next = NULL; - OsMemSentinelNodeSet(endNode, NULL, 0); + endNode = OS_MEM_END_NODE(pool, size);//确定尾节点位置,尾节点没有数据域 + endNode->magic = OS_MEM_NODE_MAGIC; //填入尾节点的魔法数字 +#if OS_MEM_EXPAND_ENABLE //支持扩展 + endNode->ptr.next = NULL;//尾节点没有后继节点 + OsMemSentinelNodeSet(endNode, NULL, 0);//将尾节点设置为哨兵节点 #else - endNode->sizeAndFlag = 0; - endNode->ptr.prev = newNode; + endNode->sizeAndFlag = 0;//0代表没有数据域 + endNode->ptr.prev = newNode;//前驱指针指向第一个节点 OS_MEM_NODE_SET_USED_FLAG(endNode->sizeAndFlag); #endif -#ifdef LOSCFG_MEM_WATERLINE - poolHead->info.curUsedSize = sizeof(struct OsMemPoolHead) + OS_MEM_NODE_HEAD_SIZE; - poolHead->info.waterLine = poolHead->info.curUsedSize; +#ifdef LOSCFG_MEM_WATERLINE //吃水线开关 + poolHead->info.curUsedSize = sizeof(struct OsMemPoolHead) + OS_MEM_NODE_HEAD_SIZE;//内存池已使用了这么多空间,这些都是存内存池自身数据的空间, + //但此处是否还要算是 endNode ? @note_thinking + poolHead->info.waterLine = poolHead->info.curUsedSize; //设置吃水线 #endif #ifdef LOSCFG_KERNEL_LMS if (resize != 0) { @@ -896,13 +909,13 @@ STATIC VOID OsMemPoolDeinit(const VOID *pool, UINT32 size) #endif (VOID)memset_s(pool, size, 0, sizeof(struct OsMemPoolHead)); } - +/// 新增内存池 STATIC UINT32 OsMemPoolAdd(VOID *pool, UINT32 size) { VOID *nextPool = g_poolHead; VOID *curPool = g_poolHead; UINTPTR poolEnd; - while (nextPool != NULL) { + while (nextPool != NULL) {//单链表遍历方式 poolEnd = (UINTPTR)nextPool + LOS_MemPoolSizeGet(nextPool); if (((pool <= nextPool) && (((UINTPTR)pool + size) > (UINTPTR)nextPool)) || (((UINTPTR)pool < poolEnd) && (((UINTPTR)pool + size) >= poolEnd))) { @@ -916,15 +929,15 @@ STATIC UINT32 OsMemPoolAdd(VOID *pool, UINT32 size) } if (g_poolHead == NULL) { - g_poolHead = pool; + g_poolHead = pool; //首个内存池 } else { - ((struct OsMemPoolHead *)curPool)->nextPool = pool; + ((struct OsMemPoolHead *)curPool)->nextPool = pool; //两池扯上关系 } - ((struct OsMemPoolHead *)pool)->nextPool = NULL; + ((struct OsMemPoolHead *)pool)->nextPool = NULL; //新池下一个无所指 return LOS_OK; } - +/// 删除内存池 STATIC UINT32 OsMemPoolDelete(const VOID *pool) { UINT32 ret = LOS_NOK; @@ -955,29 +968,39 @@ STATIC UINT32 OsMemPoolDelete(const VOID *pool) } #endif +/*! + * @brief LOS_MemInit 初始化一块指定的动态内存池,大小为size + * 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。 + * @param pool + * @param size + * @return + * @attention EndNode作为内存池末尾的节点,size为0。 + * @see + */ UINT32 LOS_MemInit(VOID *pool, UINT32 size) { if ((pool == NULL) || (size <= OS_MEM_MIN_POOL_SIZE)) { return OS_ERROR; } - size = OS_MEM_ALIGN(size, OS_MEM_ALIGN_SIZE); + size = OS_MEM_ALIGN(size, OS_MEM_ALIGN_SIZE);//4个字节对齐 if (OsMemPoolInit(pool, size)) { return OS_ERROR; } -#ifdef LOSCFG_MEM_MUL_POOL +#ifdef LOSCFG_MEM_MUL_POOL //多内存池开关 if (OsMemPoolAdd(pool, size)) { (VOID)OsMemPoolDeInit(pool, size); return OS_ERROR; } #endif - OsHookCall(LOS_HOOK_TYPE_MEM_INIT, pool, size); + OsHookCall(LOS_HOOK_TYPE_MEM_INIT, pool, size);//打印日志 return LOS_OK; } #ifdef LOSCFG_MEM_MUL_POOL +/// 删除指定内存池 UINT32 LOS_MemDeInit(VOID *pool) { struct OsMemPoolHead *tmpPool = (struct OsMemPoolHead *)pool; @@ -997,7 +1020,7 @@ UINT32 LOS_MemDeInit(VOID *pool) OsHookCall(LOS_HOOK_TYPE_MEM_DEINIT, tmpPool); return LOS_OK; } - +/// 打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。 UINT32 LOS_MemPoolList(VOID) { VOID *nextPool = g_poolHead; @@ -1011,7 +1034,7 @@ UINT32 LOS_MemPoolList(VOID) return index; } #endif - +/// 从指定动态内存池中申请size长度的内存 STATIC INLINE VOID *OsMemAlloc(struct OsMemPoolHead *pool, UINT32 size, UINT32 intSave) { struct OsMemNodeHead *allocNode = NULL; @@ -1024,15 +1047,15 @@ STATIC INLINE VOID *OsMemAlloc(struct OsMemPoolHead *pool, UINT32 size, UINT32 i UINT32 allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE); #if OS_MEM_EXPAND_ENABLE -retry: +retry: //这种写法也挺赞的 @note_good #endif - allocNode = OsMemFreeNodeGet(pool, allocSize); - if (allocNode == NULL) { + allocNode = OsMemFreeNodeGet(pool, allocSize);//获取空闲节点 + if (allocNode == NULL) {//没有内存了,怎搞? #if OS_MEM_EXPAND_ENABLE if (pool->info.attr & OS_MEM_POOL_EXPAND_ENABLE) { - INT32 ret = OsMemPoolExpand(pool, allocSize, intSave); + INT32 ret = OsMemPoolExpand(pool, allocSize, intSave);//扩展内存池 if (ret == 0) { - goto retry; + goto retry;//再来一遍 } } #endif @@ -1047,22 +1070,22 @@ retry: return NULL; } - if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_MIN_ALLOC_SIZE) <= allocNode->sizeAndFlag) { - OsMemSplitNode(pool, allocNode, allocSize); + if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_MIN_ALLOC_SIZE) <= allocNode->sizeAndFlag) {//所需小于内存池可供分配量 + OsMemSplitNode(pool, allocNode, allocSize);//劈开内存池 } - OS_MEM_NODE_SET_USED_FLAG(allocNode->sizeAndFlag); - OsMemWaterUsedRecord(pool, OS_MEM_NODE_GET_SIZE(allocNode->sizeAndFlag)); + OS_MEM_NODE_SET_USED_FLAG(allocNode->sizeAndFlag);//给节点贴上已使用的标签 + OsMemWaterUsedRecord(pool, OS_MEM_NODE_GET_SIZE(allocNode->sizeAndFlag));//更新吃水线 -#ifdef LOSCFG_MEM_LEAKCHECK +#ifdef LOSCFG_MEM_LEAKCHECK //检测内存泄漏开关 OsMemLinkRegisterRecord(allocNode); #endif - return OsMemCreateUsedNode((VOID *)allocNode); + return OsMemCreateUsedNode((VOID *)allocNode);//创建已使用节点 } - +/// 从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存 VOID *LOS_MemAlloc(VOID *pool, UINT32 size) { - if ((pool == NULL) || (size == 0)) { + if ((pool == NULL) || (size == 0)) {//没提供内存池时 return (size > 0) ? OsVmBootMemAlloc(size) : NULL; } @@ -1079,14 +1102,14 @@ VOID *LOS_MemAlloc(VOID *pool, UINT32 size) break; } MEM_LOCK(poolHead, intSave); - ptr = OsMemAlloc(poolHead, size, intSave); + ptr = OsMemAlloc(poolHead, size, intSave);//真正的分配内存函数,详细查看 鸿蒙内核源码分析(内存池篇) MEM_UNLOCK(poolHead, intSave); } while (0); - OsHookCall(LOS_HOOK_TYPE_MEM_ALLOC, pool, ptr, size); + OsHookCall(LOS_HOOK_TYPE_MEM_ALLOC, pool, ptr, size);//打印日志,到此一游 return ptr; } - +/// 从指定内存池中申请size长度的内存且地址按boundary字节对齐的内存 VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) { UINT32 gapSize; @@ -1143,10 +1166,10 @@ VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary) ptr = alignedPtr; } while (0); - OsHookCall(LOS_HOOK_TYPE_MEM_ALLOCALIGN, pool, ptr, size, boundary); + OsHookCall(LOS_HOOK_TYPE_MEM_ALLOCALIGN, pool, ptr, size, boundary);//打印对齐日志,表示程序曾临幸过此处 return ptr; } - +/// 内存池有效性检查 STATIC INLINE BOOL OsMemAddrValidCheck(const struct OsMemPoolHead *pool, const VOID *addr) { UINT32 size; @@ -1160,7 +1183,7 @@ STATIC INLINE BOOL OsMemAddrValidCheck(const struct OsMemPoolHead *pool, const V if (OS_MEM_MIDDLE_ADDR_OPEN_END(pool + 1, addr, (UINTPTR)pool + size)) { return TRUE; } -#if OS_MEM_EXPAND_ENABLE +#if OS_MEM_EXPAND_ENABLE //如果支持可扩展 struct OsMemNodeHead *node = NULL; struct OsMemNodeHead *sentinel = OS_MEM_END_NODE(pool, size); while (OsMemIsLastSentinelNode(sentinel) == FALSE) { @@ -1250,7 +1273,7 @@ STATIC UINT32 OsMemCheckUsedNode(const struct OsMemPoolHead *pool, const struct return LOS_OK; } - +/// 释放内存 STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead *node) { UINT32 ret = OsMemCheckUsedNode(pool, node); @@ -1260,10 +1283,10 @@ STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead } #ifdef LOSCFG_MEM_WATERLINE - pool->info.curUsedSize -= OS_MEM_NODE_GET_SIZE(node->sizeAndFlag); + pool->info.curUsedSize -= OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);//降低水位线 #endif - node->sizeAndFlag = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag); + node->sizeAndFlag = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);//获取大小和标记 #ifdef LOSCFG_MEM_LEAKCHECK OsMemLinkRegisterRecord(node); #endif @@ -1274,17 +1297,17 @@ STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead g_lms->check((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, TRUE); } #endif - struct OsMemNodeHead *preNode = node->ptr.prev; /* merage preNode */ + struct OsMemNodeHead *preNode = node->ptr.prev; /* merage preNode | 合并前一个节点*/ if ((preNode != NULL) && !OS_MEM_NODE_GET_USED_FLAG(preNode->sizeAndFlag)) { - OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)preNode); - OsMemMergeNode(node); + OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)preNode);//删除前节点的信息 + OsMemMergeNode(node);//向前合并 node = preNode; } - struct OsMemNodeHead *nextNode = OS_MEM_NEXT_NODE(node); /* merage nextNode */ + struct OsMemNodeHead *nextNode = OS_MEM_NEXT_NODE(node); /* merage nextNode | 计算后一个节点位置*/ if ((nextNode != NULL) && !OS_MEM_NODE_GET_USED_FLAG(nextNode->sizeAndFlag)) { - OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode); - OsMemMergeNode(nextNode); + OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode);//删除后节点信息 + OsMemMergeNode(nextNode);//合并节点 } #if OS_MEM_EXPAND_ENABLE @@ -1305,7 +1328,7 @@ STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead #endif return ret; } - +/// 释放从指定动态内存中申请的内存 UINT32 LOS_MemFree(VOID *pool, VOID *ptr) { UINT32 intSave; @@ -1321,13 +1344,13 @@ UINT32 LOS_MemFree(VOID *pool, VOID *ptr) struct OsMemNodeHead *node = NULL; do { - UINT32 gapSize = *(UINT32 *)((UINTPTR)ptr - sizeof(UINT32)); + UINT32 gapSize = *(UINT32 *)((UINTPTR)ptr - sizeof(UINT32));//获取节点大小和标签 即: sizeAndFlag if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize) && OS_MEM_NODE_GET_USED_FLAG(gapSize)) { PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FUNCTION__, __LINE__, gapSize); break; } - node = (struct OsMemNodeHead *)((UINTPTR)ptr - OS_MEM_NODE_HEAD_SIZE); + node = (struct OsMemNodeHead *)((UINTPTR)ptr - OS_MEM_NODE_HEAD_SIZE);//定位到节点开始位置 if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize)) { gapSize = OS_MEM_NODE_GET_ALIGNED_GAPSIZE(gapSize); @@ -1415,7 +1438,7 @@ STATIC INLINE VOID *OsGetRealPtr(const VOID *pool, VOID *ptr) } STATIC INLINE VOID *OsMemRealloc(struct OsMemPoolHead *pool, const VOID *ptr, - struct OsMemNodeHead *node, UINT32 size, UINT32 intSave) + struct OsMemNodeHead *node, UINT32 size, UINT32 intSave) { struct OsMemNodeHead *nextNode = NULL; UINT32 allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE); @@ -1446,7 +1469,7 @@ STATIC INLINE VOID *OsMemRealloc(struct OsMemPoolHead *pool, const VOID *ptr, } return tmpPtr; } - +/// 按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块 VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size) { if ((pool == NULL) || OS_MEM_NODE_GET_USED_FLAG(size) || OS_MEM_NODE_GET_ALIGNED_FLAG(size)) { @@ -1539,7 +1562,7 @@ UINT32 LOS_MemFreeByTaskID(VOID *pool, UINT32 taskID) return LOS_OK; } #endif - +/// 获取指定动态内存池的总大小 UINT32 LOS_MemPoolSizeGet(const VOID *pool) { UINT32 count = 0; @@ -1548,23 +1571,23 @@ UINT32 LOS_MemPoolSizeGet(const VOID *pool) return LOS_NOK; } - count += ((struct OsMemPoolHead *)pool)->info.totalSize; + count += ((struct OsMemPoolHead *)pool)->info.totalSize; // 这里的 += 好像没必要吧?, = 就可以了, @note_thinking -#if OS_MEM_EXPAND_ENABLE +#if OS_MEM_EXPAND_ENABLE //支持扩展 UINT32 size; struct OsMemNodeHead *node = NULL; - struct OsMemNodeHead *sentinel = OS_MEM_END_NODE(pool, count); + struct OsMemNodeHead *sentinel = OS_MEM_END_NODE(pool, count);//获取哨兵节点 - while (OsMemIsLastSentinelNode(sentinel) == FALSE) { - size = OS_MEM_NODE_GET_SIZE(sentinel->sizeAndFlag); - node = OsMemSentinelNodeGet(sentinel); - sentinel = OS_MEM_END_NODE(node, size); - count += size; + while (OsMemIsLastSentinelNode(sentinel) == FALSE) {//不是最后一个节点 + size = OS_MEM_NODE_GET_SIZE(sentinel->sizeAndFlag);//数据域大小 + node = OsMemSentinelNodeGet(sentinel);//再获取哨兵节点 + sentinel = OS_MEM_END_NODE(node, size);//获取尾节点 + count += size; //内存池大小变大 } #endif return count; } - +/// 获取指定动态内存池的总使用量大小 UINT32 LOS_MemTotalUsedGet(VOID *pool) { struct OsMemNodeHead *tmpNode = NULL; @@ -1637,7 +1660,7 @@ STATIC UINT32 OsMemAddrValidCheckPrint(const VOID *pool, struct OsMemFreeNodeHea } STATIC UINT32 OsMemIntegrityCheckSub(struct OsMemNodeHead **tmpNode, const VOID *pool, - const struct OsMemNodeHead *endNode) + const struct OsMemNodeHead *endNode) { if (!OS_MEM_MAGIC_VALID(*tmpNode)) { OsMemMagicCheckPrint(tmpNode); @@ -1653,7 +1676,7 @@ STATIC UINT32 OsMemIntegrityCheckSub(struct OsMemNodeHead **tmpNode, const VOID } STATIC UINT32 OsMemFreeListNodeCheck(const struct OsMemPoolHead *pool, - const struct OsMemFreeNodeHead *node) + const struct OsMemFreeNodeHead *node) { if (!OsMemAddrValidCheck(pool, node) || !OsMemAddrValidCheck(pool, node->prev) || @@ -1714,9 +1737,9 @@ OUT: #endif } } - +//对指定内存池做完整性检查, STATIC UINT32 OsMemIntegrityCheck(const struct OsMemPoolHead *pool, struct OsMemNodeHead **tmpNode, - struct OsMemNodeHead **preNode) + struct OsMemNodeHead **preNode) { struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize); @@ -1839,7 +1862,7 @@ STATIC INLINE UINT32 OsMemAllocCheck(struct OsMemPoolHead *pool, UINT32 intSave) return LOS_OK; } #endif - +/// 对指定内存池做完整性检查 UINT32 LOS_MemIntegrityCheck(const VOID *pool) { if (pool == NULL) { @@ -1864,7 +1887,7 @@ ERROR_OUT: } STATIC INLINE VOID OsMemInfoGet(struct OsMemPoolHead *poolInfo, struct OsMemNodeHead *node, - LOS_MEM_POOL_STATUS *poolStatus) + LOS_MEM_POOL_STATUS *poolStatus) { UINT32 totalUsedSize = 0; UINT32 totalFreeSize = 0; @@ -1893,8 +1916,17 @@ STATIC INLINE VOID OsMemInfoGet(struct OsMemPoolHead *poolInfo, struct OsMemNode poolStatus->freeNodeNum += freeNodeNum; } +/*! + * @brief LOS_MemInfoGet + * 获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小 + * @param pool + * @param poolStatus + * @return + * + * @see + */ UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus) -{ +{//内存碎片率计算:同样调用LOS_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。 struct OsMemPoolHead *poolInfo = pool; if (poolStatus == NULL) { @@ -1975,7 +2007,7 @@ STATIC VOID OsMemInfoPrint(VOID *pool) status.freeNodeNum); #endif } - +/// 打印指定内存池的空闲内存块的大小及数量 UINT32 LOS_MemFreeNodeShow(VOID *pool) { struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool; @@ -2022,7 +2054,7 @@ UINT32 LOS_MemFreeNodeShow(VOID *pool) return LOS_OK; } - +///内核空间动态内存(堆内存)初始化 , 争取系统动态内存池 STATUS_T OsKHeapInit(size_t size) { STATUS_T ret; @@ -2041,38 +2073,38 @@ STATUS_T OsKHeapInit(size_t size) return -1; } - m_aucSysMem0 = m_aucSysMem1 = ptr; - ret = LOS_MemInit(m_aucSysMem0, size); + m_aucSysMem0 = m_aucSysMem1 = ptr;// 指定内核内存池的位置 + ret = LOS_MemInit(m_aucSysMem0, size); //初始化内存池,供内核分配动态内存 if (ret != LOS_OK) { PRINT_ERR("vmm_kheap_init LOS_MemInit failed!\n"); g_vmBootMemBase -= size; return ret; } #if OS_MEM_EXPAND_ENABLE - LOS_MemExpandEnable(OS_SYS_MEM_ADDR); + LOS_MemExpandEnable(OS_SYS_MEM_ADDR);//支持扩展系统动态内存 #endif return LOS_OK; } - +///< 判断地址是否在堆区 BOOL OsMemIsHeapNode(const VOID *ptr) { - struct OsMemPoolHead *pool = (struct OsMemPoolHead *)m_aucSysMem1; - struct OsMemNodeHead *firstNode = OS_MEM_FIRST_NODE(pool); - struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize); + struct OsMemPoolHead *pool = (struct OsMemPoolHead *)m_aucSysMem1;//内核堆区开始地址 + struct OsMemNodeHead *firstNode = OS_MEM_FIRST_NODE(pool);//获取内存池首个节点 + struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize);//获取内存池的尾节点 - if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) { + if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {//如果在首尾范围内 return TRUE; } -#if OS_MEM_EXPAND_ENABLE - UINT32 intSave; - UINT32 size; - MEM_LOCK(pool, intSave); - while (OsMemIsLastSentinelNode(endNode) == FALSE) { - size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag); - firstNode = OsMemSentinelNodeGet(endNode); - endNode = OS_MEM_END_NODE(firstNode, size); - if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) { +#if OS_MEM_EXPAND_ENABLE//内存池经过扩展后,新旧块的虚拟地址是不连续的,所以需要跳块判断 + UINT32 intSave; + UINT32 size;//详细查看百篇博客系列篇之 鸿蒙内核源码分析(内存池篇) + MEM_LOCK(pool, intSave); //获取自旋锁 + while (OsMemIsLastSentinelNode(endNode) == FALSE) { //哨兵节点是内存池结束的标记 + size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);//获取节点大小 + firstNode = OsMemSentinelNodeGet(endNode);//获取下一块的开始地址 + endNode = OS_MEM_END_NODE(firstNode, size);//获取下一块的尾节点 + if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {//判断地址是否在该块中 MEM_UNLOCK(pool, intSave); return TRUE; } @@ -2081,3 +2113,5 @@ BOOL OsMemIsHeapNode(const VOID *ptr) #endif return FALSE; } + +