Merge pull request 'mem拯救计划' (#20) from gonghao_branch into main

pull/22/head
piyl8cs5f 1 year ago
commit 90aa7c7c8e

@ -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)

@ -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

@ -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
#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
#define OS_MEM_FREE_LIST_NUM (1 << OS_MEM_SLI)
#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,16 +226,16 @@ 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
@ -247,11 +247,12 @@ STATIC INLINE VOID OsMemWaterUsedRecord(struct OsMemPoolHead *pool, UINT32 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,12 +626,12 @@ 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);
}
@ -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
* EndNodeFreeNode
* @param pool
* @param size
* @return
* @attention EndNodesize0
* @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);
@ -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;
@ -1714,7 +1737,7 @@ OUT:
#endif
}
}
//对指定内存池做完整性检查,
STATIC UINT32 OsMemIntegrityCheck(const struct OsMemPoolHead *pool, struct OsMemNodeHead **tmpNode,
struct OsMemNodeHead **preNode)
{
@ -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) {
@ -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
#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)) {
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;
}

Loading…
Cancel
Save