|
|
|
@ -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,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,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
|
|
|
|
|
#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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|