更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_memory.c
浏览该文件的文档.
1/*!
2 * @file los_memory.c
3 * @brief
4 * @link tlsf算法论文 http://www.gii.upv.es/tlsf/files/ecrts04_tlsf.pdf @endlink
5 @verbatim
6 https://www.codenong.com/cs106845116/ TLSF算法(一)分配中的位图计算
7 基本概念
8 内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放。
9 OpenHarmony LiteOS-A的堆内存管理提供内存初始化、分配、释放等功能。在系统运行过程中,堆内存管理
10 模块通过对内存的申请/释放来管理用户和OS对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统的内存碎片问题。
11
12 运行机制
13 堆内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存
14 (内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。
15 与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。
16 OpenHarmony LiteOS-A堆内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。
17 动态内存核心算法框图如下:
18 @endverbatim
19 * @image html https://gitee.com/weharmonyos/resources/raw/master/11/1.png
20 @verbatim
21 根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[27, 231],如上图size class所示:
22
23 1. 对[4,127]区间的内存进行等分,如上图下半部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。
24 每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。
25 [4,127]区间的31个小区间内存对应31个比特位进行标记链表是否为空。
26 2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,
27 见上图上半部分的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。
28 总共24*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。
29 例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间[40,43],第10个空闲链表,位图标记的第10比特位。
30 把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,
31 根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,
32 进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间[29,29+2^6],
33 第31+2*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。
34 当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。
35 如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,
36 则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。
37
38 内存信息包括内存池大小、内存使用量、剩余内存大小、最大空闲内存、内存水线、内存节点数统计、碎片率等。
39 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小;
40 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-最大空闲内存块大小/剩余内存大小)来度量;
41
42 内存管理结构如下图所示:
43 @endverbatim
44 * @image html https://gitee.com/weharmonyos/resources/raw/master/11/2.png
45 * @version
46 * @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
47 * @date 2021-11-19
48 */
49/*
50 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
51 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
52 *
53 * Redistribution and use in source and binary forms, with or without modification,
54 * are permitted provided that the following conditions are met:
55 *
56 * 1. Redistributions of source code must retain the above copyright notice, this list of
57 * conditions and the following disclaimer.
58 *
59 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
60 * of conditions and the following disclaimer in the documentation and/or other materials
61 * provided with the distribution.
62 *
63 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
64 * to endorse or promote products derived from this software without specific prior written
65 * permission.
66 *
67 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
68 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
69 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
70 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
71 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
72 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
73 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
74 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
75 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
76 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
77 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
78 */
79
80#include "los_memory.h"
81#include "los_memory_pri.h"
82#include "sys/param.h"
83#include "los_spinlock.h"
84#include "los_vm_phys.h"
85#include "los_vm_boot.h"
86#include "los_vm_filemap.h"
87#include "los_task_pri.h"
88#include "los_hook.h"
89
90#ifdef LOSCFG_KERNEL_LMS
91#include "los_lms_pri.h"
92#endif
93
94/* Used to cut non-essential functions. | 用于削减非必要功能 */
95#define OS_MEM_FREE_BY_TASKID 0
96#ifdef LOSCFG_KERNEL_VM
97#define OS_MEM_EXPAND_ENABLE 1
98#else
99#define OS_MEM_EXPAND_ENABLE 0
100#endif
101
102/* the dump size of current broken node when memcheck error */
103#define OS_MEM_NODE_DUMP_SIZE 64
104/* column num of the output info of mem node */
105#define OS_MEM_COLUMN_NUM 8
106
107UINT8 *m_aucSysMem0 = NULL; ///< 异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
108UINT8 *m_aucSysMem1 = NULL; ///< 系统动态内存池地址的起始地址 @note_thinking 能否不要用 0,1来命名核心变量 ???
109
110#ifdef LOSCFG_MEM_MUL_POOL
111VOID *g_poolHead = NULL; ///内存池头,由它牵引多个内存池
112#endif
113
114/* The following is the macro definition and interface implementation related to the TLSF. */
115
116/* Supposing a Second Level Index: SLI = 3. */
117#define OS_MEM_SLI 3 ///< 二级小区间级数,
118/* Giving 1 free list for each small bucket: 4, 8, 12, up to 124. */
119#define OS_MEM_SMALL_BUCKET_COUNT 31 ///< 小桶的偏移单位 从 4 ~ 124 ,共32级
120#define OS_MEM_SMALL_BUCKET_MAX_SIZE 128 ///< 小桶的最大数量
121/* Giving OS_MEM_FREE_LIST_NUM free lists for each large bucket. */
122#define OS_MEM_LARGE_BUCKET_COUNT 24 /// 为每个大存储桶空闲列表数量 大桶范围: [2^7, 2^31] ,每个小区间有分为 2^3个小区间
123#define OS_MEM_FREE_LIST_NUM (1 << OS_MEM_SLI) ///< 2^3 = 8 个,即大桶的每个区间又分为8个小区间
124/* OS_MEM_SMALL_BUCKET_MAX_SIZE to the power of 2 is 7. */
125#define OS_MEM_LARGE_START_BUCKET 7 /// 大桶的开始下标
126
127/* The count of free list. */
128#define OS_MEM_FREE_LIST_COUNT (OS_MEM_SMALL_BUCKET_COUNT + (OS_MEM_LARGE_BUCKET_COUNT << OS_MEM_SLI)) ///< 总链表的数量 32 + 24 * 8 = 224
129/* The bitmap is used to indicate whether the free list is empty, 1: not empty, 0: empty. */
130#define OS_MEM_BITMAP_WORDS ((OS_MEM_FREE_LIST_COUNT >> 5) + 1) ///< 224 >> 5 + 1 = 7 ,为什么要右移 5 因为 2^5 = 32 是一个32位整型的大小
131 ///< 而 32 * 7 = 224 ,也就是说用 int[7]当位图就能表示完 224个链表 ,此处,一定要理解好,因为这是理解 TLSF 算法的关键.
132#define OS_MEM_BITMAP_MASK 0x1FU ///< 因为一个int型为 32位, 2^5 = 32,所以此处 0x1FU = 5个1 足以.
133
134/* Used to find the first bit of 1 in bitmap. */
135STATIC INLINE UINT16 OsMemFFS(UINT32 bitmap)
136{
137 bitmap &= ~bitmap + 1;
138 return (OS_MEM_BITMAP_MASK - CLZ(bitmap));
139}
140
141/* Used to find the last bit of 1 in bitmap. */
142STATIC INLINE UINT16 OsMemFLS(UINT32 bitmap)
143{
144 return (OS_MEM_BITMAP_MASK - CLZ(bitmap));
145}
146
147STATIC INLINE UINT32 OsMemLog2(UINT32 size)
148{
149 return OsMemFLS(size);
150}
151
152/* Get the first level: f = log2(size). | 获取第一级*/
153STATIC INLINE UINT32 OsMemFlGet(UINT32 size)
154{
155 if (size < OS_MEM_SMALL_BUCKET_MAX_SIZE) {
156 return ((size >> 2) - 1); /* 2: The small bucket setup is 4. */
157 }
158 return OsMemLog2(size);
159}
160
161/* Get the second level: s = (size - 2^f) * 2^SLI / 2^f. | 获取第二级 */
162STATIC INLINE UINT32 OsMemSlGet(UINT32 size, UINT32 fl)
163{
164 return (((size << OS_MEM_SLI) >> fl) - OS_MEM_FREE_LIST_NUM);
165}
166
167/* The following is the memory algorithm related macro definition and interface implementation. */
168/// 内存池节点
170 UINT32 magic; ///< 魔法数字 0xABCDDCBA
171 union {//注意这里的前后指向的是连续的地址节点,用于分割和合并
172 struct OsMemNodeHead *prev; /* The prev is used for current node points to the previous node | prev 用于当前节点指向前一个节点*/
173 struct OsMemNodeHead *next; /* The next is used for last node points to the expand node | next 用于最后一个节点指向展开节点*/
175#ifdef LOSCFG_MEM_LEAKCHECK //内存泄漏检测
176 UINTPTR linkReg[LOS_RECORD_LR_CNT];///< 存放左右节点地址,用于检测
177#endif
178 UINT32 sizeAndFlag; ///< 节点总大小+标签
179};
180/// 已使用内存池节点
182 struct OsMemNodeHead header;///< 已被使用节点
183#if OS_MEM_FREE_BY_TASKID
184 UINT32 taskID; ///< 使用节点的任务ID
185#endif
186};
187/// 内存池空闲节点
189 struct OsMemNodeHead header; ///< 内存池节点
190 struct OsMemFreeNodeHead *prev; ///< 前一个空闲前驱节点
191 struct OsMemFreeNodeHead *next; ///< 后一个空闲后继节点
192};
193/// 内存池信息
195 VOID *pool; ///< 指向内存块基地址,仅做记录而已,真正的分配内存跟它没啥关系
196 UINT32 totalSize; ///< 总大小,确定了内存池的边界
197 UINT32 attr; ///< 属性 default attr: lock, not expand.
198#ifdef LOSCFG_MEM_WATERLINE
199 UINT32 waterLine; /* Maximum usage size in a memory pool | 内存吃水线*/
200 UINT32 curUsedSize; /* Current usage size in a memory pool | 当前已使用大小*/
201#endif
202};
203/// 内存池头信息
205 struct OsMemPoolInfo info; ///< 记录内存池的信息
206 UINT32 freeListBitmap[OS_MEM_BITMAP_WORDS]; ///< 空闲位图 int[7] = 32 * 7 = 224 > 223
207 struct OsMemFreeNodeHead *freeList[OS_MEM_FREE_LIST_COUNT];///< 空闲节点链表 32 + 24 * 8 = 224
208 SPIN_LOCK_S spinlock; ///< 操作本池的自旋锁,涉及CPU多核竞争,所以必须得是自旋锁
209#ifdef LOSCFG_MEM_MUL_POOL
210 VOID *nextPool; ///< 指向下一个内存池 OsMemPoolHead 类型
211#endif
212};
213
214/* Spinlock for mem module, only available on SMP mode */
215#define MEM_LOCK(pool, state) LOS_SpinLockSave(&(pool)->spinlock, &(state))
216#define MEM_UNLOCK(pool, state) LOS_SpinUnlockRestore(&(pool)->spinlock, (state))
217
218/* The memory pool support expand. */
219#define OS_MEM_POOL_EXPAND_ENABLE 0x01 ///< 支持扩展
220/* The memory pool support no lock. */
221#define OS_MEM_POOL_LOCK_ENABLE 0x02 ///< 加锁
222
223#define OS_MEM_NODE_MAGIC 0xABCDDCBA ///< 内存节点的魔法数字
224#define OS_MEM_MIN_ALLOC_SIZE (sizeof(struct OsMemFreeNodeHead) - sizeof(struct OsMemUsedNodeHead)) //最小分配空间
225// 必须给指向空闲块的指针留位置
226#define OS_MEM_NODE_USED_FLAG 0x80000000U ///< 已使用标签
227#define OS_MEM_NODE_ALIGNED_FLAG 0x40000000U ///< 对齐标签
228#define OS_MEM_NODE_LAST_FLAG 0x20000000U /* Sentinel Node | 哨兵节点标签*/
229#define OS_MEM_NODE_ALIGNED_AND_USED_FLAG (OS_MEM_NODE_USED_FLAG | OS_MEM_NODE_ALIGNED_FLAG | OS_MEM_NODE_LAST_FLAG)
230
231#define OS_MEM_NODE_GET_ALIGNED_FLAG(sizeAndFlag) \
232 ((sizeAndFlag) & OS_MEM_NODE_ALIGNED_FLAG)
233#define OS_MEM_NODE_SET_ALIGNED_FLAG(sizeAndFlag) \
234 ((sizeAndFlag) = ((sizeAndFlag) | OS_MEM_NODE_ALIGNED_FLAG))
235#define OS_MEM_NODE_GET_ALIGNED_GAPSIZE(sizeAndFlag) \
236 ((sizeAndFlag) & ~OS_MEM_NODE_ALIGNED_FLAG)
237#define OS_MEM_NODE_GET_USED_FLAG(sizeAndFlag) \
238 ((sizeAndFlag) & OS_MEM_NODE_USED_FLAG)
239#define OS_MEM_NODE_SET_USED_FLAG(sizeAndFlag) \
240 ((sizeAndFlag) = ((sizeAndFlag) | OS_MEM_NODE_USED_FLAG))
241#define OS_MEM_NODE_GET_SIZE(sizeAndFlag) \
242 ((sizeAndFlag) & ~OS_MEM_NODE_ALIGNED_AND_USED_FLAG)
243#define OS_MEM_NODE_SET_LAST_FLAG(sizeAndFlag) \
244 ((sizeAndFlag) = ((sizeAndFlag) | OS_MEM_NODE_LAST_FLAG))
245#define OS_MEM_NODE_GET_LAST_FLAG(sizeAndFlag) \
246 ((sizeAndFlag) & OS_MEM_NODE_LAST_FLAG)
247
248#define OS_MEM_ALIGN_SIZE sizeof(UINTPTR)
249#define OS_MEM_IS_POW_TWO(value) ((((UINTPTR)(value)) & ((UINTPTR)(value) - 1)) == 0)
250#define OS_MEM_ALIGN(p, alignSize) (((UINTPTR)(p) + (alignSize) - 1) & ~((UINTPTR)((alignSize) - 1)))
251#define OS_MEM_IS_ALIGNED(a, b) (!(((UINTPTR)(a)) & (((UINTPTR)(b)) - 1)))
252#define OS_MEM_NODE_HEAD_SIZE sizeof(struct OsMemUsedNodeHead)
253#define OS_MEM_MIN_POOL_SIZE (OS_MEM_NODE_HEAD_SIZE + sizeof(struct OsMemPoolHead))
254#define OS_MEM_NEXT_NODE(node) \
255 ((struct OsMemNodeHead *)(VOID *)((UINT8 *)(node) + OS_MEM_NODE_GET_SIZE((node)->sizeAndFlag)))
256#define OS_MEM_FIRST_NODE(pool) \
257 (struct OsMemNodeHead *)((UINT8 *)(pool) + sizeof(struct OsMemPoolHead))
258#define OS_MEM_END_NODE(pool, size) \
259 (struct OsMemNodeHead *)((UINT8 *)(pool) + (size) - OS_MEM_NODE_HEAD_SIZE)
260#define OS_MEM_MIDDLE_ADDR_OPEN_END(startAddr, middleAddr, endAddr) \
261 (((UINT8 *)(startAddr) <= (UINT8 *)(middleAddr)) && ((UINT8 *)(middleAddr) < (UINT8 *)(endAddr)))
262#define OS_MEM_MIDDLE_ADDR(startAddr, middleAddr, endAddr) \
263 (((UINT8 *)(startAddr) <= (UINT8 *)(middleAddr)) && ((UINT8 *)(middleAddr) <= (UINT8 *)(endAddr)))
264#define OS_MEM_SET_MAGIC(node) ((node)->magic = OS_MEM_NODE_MAGIC)
265#define OS_MEM_MAGIC_VALID(node) ((node)->magic == OS_MEM_NODE_MAGIC)
266
267STATIC INLINE VOID OsMemFreeNodeAdd(VOID *pool, struct OsMemFreeNodeHead *node);
268STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead *node);
269STATIC VOID OsMemInfoPrint(VOID *pool);
270#ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK
271STATIC INLINE UINT32 OsMemAllocCheck(struct OsMemPoolHead *pool, UINT32 intSave);
272#endif
273
274#if OS_MEM_FREE_BY_TASKID
275STATIC INLINE VOID OsMemNodeSetTaskID(struct OsMemUsedNodeHead *node)
276{
277 node->taskID = LOS_CurTaskIDGet();//将当前任务ID绑定到内存池节点上
278}
279#endif
280
281#ifdef LOSCFG_MEM_WATERLINE
282STATIC INLINE VOID OsMemWaterUsedRecord(struct OsMemPoolHead *pool, UINT32 size)
283{
284 pool->info.curUsedSize += size; //延长可使用空间
285 if (pool->info.curUsedSize > pool->info.waterLine) {
286 pool->info.waterLine = pool->info.curUsedSize; //警戒线加高
287 }
288}
289#else
290STATIC INLINE VOID OsMemWaterUsedRecord(struct OsMemPoolHead *pool, UINT32 size)
291{
292 (VOID)pool; // @note_thinking 为何要这么写 ,因为格式规范吗 ? 直接啥也不写不行吗 ?
293 (VOID)size; // 编译器会优化掉这种代码
294}
295#endif
296
297#if OS_MEM_EXPAND_ENABLE
298/// 更新哨兵节点内容
299STATIC INLINE struct OsMemNodeHead *OsMemLastSentinelNodeGet(const struct OsMemNodeHead *sentinelNode)
300{
301 struct OsMemNodeHead *node = NULL;
302 VOID *ptr = sentinelNode->ptr.next;//返回不连续的内存块
303 UINT32 size = OS_MEM_NODE_GET_SIZE(sentinelNode->sizeAndFlag); // 获取大小
304
305 while ((ptr != NULL) && (size != 0)) {
306 node = OS_MEM_END_NODE(ptr, size);
307 ptr = node->ptr.next;
308 size = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);
309 }
310
311 return node;
312}
313/// 检查哨兵节点
314STATIC INLINE BOOL OsMemSentinelNodeCheck(struct OsMemNodeHead *sentinelNode)
315{
316 if (!OS_MEM_NODE_GET_USED_FLAG(sentinelNode->sizeAndFlag)) {
317 return FALSE;
318 }
319
320 if (!OS_MEM_MAGIC_VALID(sentinelNode)) {
321 return FALSE;
322 }
323
324 return TRUE;
325}
326/// 是否为最后一个哨兵节点
327STATIC INLINE BOOL OsMemIsLastSentinelNode(struct OsMemNodeHead *sentinelNode)
328{
329 if (OsMemSentinelNodeCheck(sentinelNode) == FALSE) {
330 PRINT_ERR("%s %d, The current sentinel node is invalid\n", __FUNCTION__, __LINE__);
331 return TRUE;
332 }
333
334 if ((OS_MEM_NODE_GET_SIZE(sentinelNode->sizeAndFlag) == 0) ||
335 (sentinelNode->ptr.next == NULL)) {
336 return TRUE;
337 }
338
339 return FALSE;
340}
341/// 设置哨兵节点内容
342STATIC INLINE VOID OsMemSentinelNodeSet(struct OsMemNodeHead *sentinelNode, VOID *newNode, UINT32 size)
343{
344 if (sentinelNode->ptr.next != NULL) { //哨兵节点有 逻辑地址不连续的衔接内存块
345 sentinelNode = OsMemLastSentinelNodeGet(sentinelNode);//更新哨兵节点内容
346 }
347
348 sentinelNode->sizeAndFlag = size;
349 sentinelNode->ptr.next = newNode;
350 OS_MEM_NODE_SET_USED_FLAG(sentinelNode->sizeAndFlag);
351 OS_MEM_NODE_SET_LAST_FLAG(sentinelNode->sizeAndFlag);
352}
353
354STATIC INLINE VOID *OsMemSentinelNodeGet(struct OsMemNodeHead *node)
355{
356 return node->ptr.next;
357}
358
359STATIC INLINE struct OsMemNodeHead *PreSentinelNodeGet(const VOID *pool, const struct OsMemNodeHead *node)
360{
361 UINT32 nextSize;
362 struct OsMemNodeHead *nextNode = NULL;
363 struct OsMemNodeHead *sentinelNode = NULL;
364
365 sentinelNode = OS_MEM_END_NODE(pool, ((struct OsMemPoolHead *)pool)->info.totalSize);
366 while (sentinelNode != NULL) {
367 if (OsMemIsLastSentinelNode(sentinelNode)) {
368 PRINT_ERR("PreSentinelNodeGet can not find node %#x\n", node);
369 return NULL;
370 }
371 nextNode = OsMemSentinelNodeGet(sentinelNode);
372 if (nextNode == node) {
373 return sentinelNode;
374 }
375 nextSize = OS_MEM_NODE_GET_SIZE(sentinelNode->sizeAndFlag);
376 sentinelNode = OS_MEM_END_NODE(nextNode, nextSize);
377 }
378
379 return NULL;
380}
381/// 大内存释放
383{
384 LosVmPage *page = OsVmVaddrToPage((VOID *)ptr);//获取物理页
385 if ((page == NULL) || (page->nPages == 0)) {
386 return LOS_NOK;
387 }
388 LOS_PhysPagesFreeContiguous((VOID *)ptr, page->nPages);//释放连续的几个物理页
389
390 return LOS_OK;
391}
392
393STATIC INLINE BOOL TryShrinkPool(const VOID *pool, const struct OsMemNodeHead *node)
394{
395 struct OsMemNodeHead *mySentinel = NULL;
396 struct OsMemNodeHead *preSentinel = NULL;
397 size_t totalSize = (UINTPTR)node->ptr.prev - (UINTPTR)node;
398 size_t nodeSize = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);
399
400 if (nodeSize != totalSize) {
401 return FALSE;
402 }
403
404 preSentinel = PreSentinelNodeGet(pool, node);
405 if (preSentinel == NULL) {
406 return FALSE;
407 }
408
409 mySentinel = node->ptr.prev;
410 if (OsMemIsLastSentinelNode(mySentinel)) { /* prev node becomes sentinel node */
411 preSentinel->ptr.next = NULL;
412 OsMemSentinelNodeSet(preSentinel, NULL, 0);
413 } else {
414 preSentinel->sizeAndFlag = mySentinel->sizeAndFlag;
415 preSentinel->ptr.next = mySentinel->ptr.next;
416 }
417
418 if (OsMemLargeNodeFree(node) != LOS_OK) {
419 PRINT_ERR("TryShrinkPool free %#x failed!\n", node);
420 return FALSE;
421 }
422#ifdef LOSCFG_KERNEL_LMS
424#endif
425 return TRUE;
426}
427/// 内存池扩展实现
428STATIC INLINE INT32 OsMemPoolExpandSub(VOID *pool, UINT32 size, UINT32 intSave)
429{
430 UINT32 tryCount = MAX_SHRINK_PAGECACHE_TRY;
431 struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool;
432 struct OsMemNodeHead *newNode = NULL;
433 struct OsMemNodeHead *endNode = NULL;
434
435 size = ROUNDUP(size + OS_MEM_NODE_HEAD_SIZE, PAGE_SIZE);//圆整
436 endNode = OS_MEM_END_NODE(pool, poolInfo->info.totalSize);//获取哨兵节点
437
438RETRY:
439 newNode = (struct OsMemNodeHead *)LOS_PhysPagesAllocContiguous(size >> PAGE_SHIFT);//申请新的内存池 | 物理内存
440 if (newNode == NULL) {
441 if (tryCount > 0) {
442 tryCount--;
443 MEM_UNLOCK(poolInfo, intSave);
444 OsTryShrinkMemory(size >> PAGE_SHIFT);
445 MEM_LOCK(poolInfo, intSave);
446 goto RETRY;
447 }
448
449 PRINT_ERR("OsMemPoolExpand alloc failed size = %u\n", size);
450 return -1;
451 }
452#ifdef LOSCFG_KERNEL_LMS
453 UINT32 resize = 0;
454 if (g_lms != NULL) {
455 /*
456 * resize == 0, shadow memory init failed, no shadow memory for this pool, set poolSize as original size.
457 * resize != 0, shadow memory init successful, set poolSize as resize.
458 */
459 resize = g_lms->init(newNode, size);
460 size = (resize == 0) ? size : resize;
461 }
462#endif
463 newNode->sizeAndFlag = (size - OS_MEM_NODE_HEAD_SIZE);//设置新节点大小
464 newNode->ptr.prev = OS_MEM_END_NODE(newNode, size);//新节点的前节点指向新节点的哨兵节点
465 OsMemSentinelNodeSet(endNode, newNode, size);//设置老内存池的哨兵节点信息,其实就是指向新内存块
466 OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode);//将新节点加入空闲链表
467
468 endNode = OS_MEM_END_NODE(newNode, size);//获取新节点的哨兵节点
469 (VOID)memset(endNode, 0, sizeof(*endNode));//清空内存
470 endNode->ptr.next = NULL;//新哨兵节点没有后续指向,因为它已成为最后
471 endNode->magic = OS_MEM_NODE_MAGIC;//设置新哨兵节的魔法数字
472 OsMemSentinelNodeSet(endNode, NULL, 0); //设置新哨兵节点内容
473 OsMemWaterUsedRecord(poolInfo, OS_MEM_NODE_HEAD_SIZE);//更新内存池警戒线
474
475 return 0;
476}
477/// 扩展内存池
478STATIC INLINE INT32 OsMemPoolExpand(VOID *pool, UINT32 allocSize, UINT32 intSave)
479{
480 UINT32 expandDefault = MEM_EXPAND_SIZE(LOS_MemPoolSizeGet(pool));//至少要扩展现有内存池的 1/8 大小
481 UINT32 expandSize = MAX(expandDefault, allocSize);
482 UINT32 tryCount = 1;//尝试次数
483 UINT32 ret;
484
485 do {
486 ret = OsMemPoolExpandSub(pool, expandSize, intSave);
487 if (ret == 0) {
488 return 0;
489 }
490
491 if (allocSize > expandDefault) {
492 break;
493 }
494 expandSize = allocSize;
495 } while (tryCount--);
496
497 return -1;
498}
499///< 允许指定内存池扩展
500VOID LOS_MemExpandEnable(VOID *pool)
501{
502 if (pool == NULL) {
503 return;
504 }
505
506 ((struct OsMemPoolHead *)pool)->info.attr |= OS_MEM_POOL_EXPAND_ENABLE;
507}
508#endif
509
510#ifdef LOSCFG_KERNEL_LMS
511STATIC INLINE VOID OsLmsFirstNodeMark(VOID *pool, struct OsMemNodeHead *node)
512{
513 if (g_lms == NULL) {
514 return;
515 }
516
517 g_lms->simpleMark((UINTPTR)pool, (UINTPTR)node, LMS_SHADOW_PAINT_U8);
518 g_lms->simpleMark((UINTPTR)node, (UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, LMS_SHADOW_REDZONE_U8);
519 g_lms->simpleMark((UINTPTR)OS_MEM_NEXT_NODE(node), (UINTPTR)OS_MEM_NEXT_NODE(node) + OS_MEM_NODE_HEAD_SIZE,
520 LMS_SHADOW_REDZONE_U8);
521 g_lms->simpleMark((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, (UINTPTR)OS_MEM_NEXT_NODE(node),
522 LMS_SHADOW_AFTERFREE_U8);
523}
524
525STATIC INLINE VOID OsLmsAllocAlignMark(VOID *ptr, VOID *alignedPtr, UINT32 size)
526{
527 struct OsMemNodeHead *allocNode = NULL;
528
529 if ((g_lms == NULL) || (ptr == NULL)) {
530 return;
531 }
532 allocNode = (struct OsMemNodeHead *)((struct OsMemUsedNodeHead *)ptr - 1);
533 if (ptr != alignedPtr) {
534 g_lms->simpleMark((UINTPTR)ptr, (UINTPTR)ptr + sizeof(UINT32), LMS_SHADOW_PAINT_U8);
535 g_lms->simpleMark((UINTPTR)ptr + sizeof(UINT32), (UINTPTR)alignedPtr, LMS_SHADOW_REDZONE_U8);
536 }
537
538 /* mark remining as redzone */
539 g_lms->simpleMark(LMS_ADDR_ALIGN((UINTPTR)alignedPtr + size), (UINTPTR)OS_MEM_NEXT_NODE(allocNode),
540 LMS_SHADOW_REDZONE_U8);
541}
542
543STATIC INLINE VOID OsLmsReallocMergeNodeMark(struct OsMemNodeHead *node)
544{
545 if (g_lms == NULL) {
546 return;
547 }
548
549 g_lms->simpleMark((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, (UINTPTR)OS_MEM_NEXT_NODE(node),
550 LMS_SHADOW_ACCESSABLE_U8);
551}
552
553STATIC INLINE VOID OsLmsReallocSplitNodeMark(struct OsMemNodeHead *node)
554{
555 if (g_lms == NULL) {
556 return;
557 }
558 /* mark next node */
559 g_lms->simpleMark((UINTPTR)OS_MEM_NEXT_NODE(node),
560 (UINTPTR)OS_MEM_NEXT_NODE(node) + OS_MEM_NODE_HEAD_SIZE, LMS_SHADOW_REDZONE_U8);
561 g_lms->simpleMark((UINTPTR)OS_MEM_NEXT_NODE(node) + OS_MEM_NODE_HEAD_SIZE,
562 (UINTPTR)OS_MEM_NEXT_NODE(OS_MEM_NEXT_NODE(node)), LMS_SHADOW_AFTERFREE_U8);
563}
564
565STATIC INLINE VOID OsLmsReallocResizeMark(struct OsMemNodeHead *node, UINT32 resize)
566{
567 if (g_lms == NULL) {
568 return;
569 }
570 /* mark remaining as redzone */
571 g_lms->simpleMark((UINTPTR)node + resize, (UINTPTR)OS_MEM_NEXT_NODE(node), LMS_SHADOW_REDZONE_U8);
572}
573#endif
574#ifdef LOSCFG_MEM_LEAKCHECK //内存泄漏检查
575STATIC INLINE VOID OsMemLinkRegisterRecord(struct OsMemNodeHead *node)
576{
577 LOS_RecordLR(node->linkReg, LOS_RECORD_LR_CNT, LOS_RECORD_LR_CNT, LOS_OMIT_LR_CNT);
578}
579
580STATIC INLINE VOID OsMemUsedNodePrint(struct OsMemNodeHead *node)
581{
582 UINT32 count;
583
584 if (OS_MEM_NODE_GET_USED_FLAG(node->sizeAndFlag)) {
585#ifdef __LP64__
586 PRINTK("0x%018x: ", node);
587#else
588 PRINTK("0x%010x: ", node);
589#endif
590 for (count = 0; count < LOS_RECORD_LR_CNT; count++) {
591#ifdef __LP64__
592 PRINTK(" 0x%018x ", node->linkReg[count]);
593#else
594 PRINTK(" 0x%010x ", node->linkReg[count]);
595#endif
596 }
597 PRINTK("\n");
598 }
599}
600/// 打印已使用的节点
601VOID OsMemUsedNodeShow(VOID *pool)
602{
603 if (pool == NULL) {
604 PRINTK("input param is NULL\n");
605 return;
606 }
607 if (LOS_MemIntegrityCheck(pool)) {
608 PRINTK("LOS_MemIntegrityCheck error\n");
609 return;
610 }
611 struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool;
612 struct OsMemNodeHead *tmpNode = NULL;
613 struct OsMemNodeHead *endNode = NULL;
614 UINT32 size;
615 UINT32 intSave;
616 UINT32 count;
617
618#ifdef __LP64__
619 PRINTK("\n\rnode ");
620#else
621 PRINTK("\n\rnode ");
622#endif
623 for (count = 0; count < LOS_RECORD_LR_CNT; count++) {
624#ifdef __LP64__
625 PRINTK(" LR[%u] ", count);
626#else
627 PRINTK(" LR[%u] ", count);
628#endif
629 }
630 PRINTK("\n");
631
632 MEM_LOCK(poolInfo, intSave);
633 endNode = OS_MEM_END_NODE(pool, poolInfo->info.totalSize);
634#if OS_MEM_EXPAND_ENABLE
635 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= endNode;
636 tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
637 if (tmpNode == endNode) {
638 if (OsMemIsLastSentinelNode(endNode) == FALSE) {
639 size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);
640 tmpNode = OsMemSentinelNodeGet(endNode);
641 endNode = OS_MEM_END_NODE(tmpNode, size);
642 continue;
643 } else {
644 break;
645 }
646 } else {
647 OsMemUsedNodePrint(tmpNode);
648 }
649 }
650#else
651 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode < endNode;
652 tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
653 OsMemUsedNodePrint(tmpNode);
654 }
655#endif
656 MEM_UNLOCK(poolInfo, intSave);
657}
658
659STATIC VOID OsMemNodeBacktraceInfo(const struct OsMemNodeHead *tmpNode,
660 const struct OsMemNodeHead *preNode)
661{
662 int i;
663 PRINTK("\n broken node head LR info: \n");
664 for (i = 0; i < LOS_RECORD_LR_CNT; i++) {
665 PRINTK(" LR[%d]:%#x\n", i, tmpNode->linkReg[i]);
666 }
667
668 PRINTK("\n pre node head LR info: \n");
669 for (i = 0; i < LOS_RECORD_LR_CNT; i++) {
670 PRINTK(" LR[%d]:%#x\n", i, preNode->linkReg[i]);
671 }
672}
673#endif
674
676{
677 UINT32 fl = OsMemFlGet(size);//获取一级位图
678 if (size < OS_MEM_SMALL_BUCKET_MAX_SIZE) {
679 return fl;
680 }
681
682 UINT32 sl = OsMemSlGet(size, fl);//获取二级位图
683 return (OS_MEM_SMALL_BUCKET_COUNT + ((fl - OS_MEM_LARGE_START_BUCKET) << OS_MEM_SLI) + sl);
684}
685
686STATIC INLINE struct OsMemFreeNodeHead *OsMemFindCurSuitableBlock(struct OsMemPoolHead *poolHead,
687 UINT32 index, UINT32 size)
688{
689 struct OsMemFreeNodeHead *node = NULL;
690
691 for (node = poolHead->freeList[index]; node != NULL; node = node->next) {
692 if (node->header.sizeAndFlag >= size) {
693 return node;
694 }
695 }
696
697 return NULL;
698}
699
700#define BITMAP_INDEX(index) ((index) >> 5)
701STATIC INLINE UINT32 OsMemNotEmptyIndexGet(struct OsMemPoolHead *poolHead, UINT32 index)
702{
703 UINT32 mask;
704
705 mask = poolHead->freeListBitmap[BITMAP_INDEX(index)];
706 mask &= ~((1 << (index & OS_MEM_BITMAP_MASK)) - 1);
707 if (mask != 0) {
708 index = OsMemFFS(mask) + (index & ~OS_MEM_BITMAP_MASK);
709 return index;
710 }
711
712 return OS_MEM_FREE_LIST_COUNT;
713}
714/// 找到下一个合适的块
715STATIC INLINE struct OsMemFreeNodeHead *OsMemFindNextSuitableBlock(VOID *pool, UINT32 size, UINT32 *outIndex)
716{
717 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
718 UINT32 fl = OsMemFlGet(size);
719 UINT32 sl;
720 UINT32 index, tmp;
721 UINT32 curIndex = OS_MEM_FREE_LIST_COUNT;
722 UINT32 mask;
723
724 do {
725 if (size < OS_MEM_SMALL_BUCKET_MAX_SIZE) {
726 index = fl;
727 } else {
728 sl = OsMemSlGet(size, fl);
729 curIndex = ((fl - OS_MEM_LARGE_START_BUCKET) << OS_MEM_SLI) + sl + OS_MEM_SMALL_BUCKET_COUNT;
730 index = curIndex + 1;
731 }
732
733 tmp = OsMemNotEmptyIndexGet(poolHead, index);
734 if (tmp != OS_MEM_FREE_LIST_COUNT) {
735 index = tmp;
736 goto DONE;
737 }
738
739 for (index = LOS_Align(index + 1, 32); index < OS_MEM_FREE_LIST_COUNT; index += 32) { /* 32: align size */
740 mask = poolHead->freeListBitmap[BITMAP_INDEX(index)];
741 if (mask != 0) {
742 index = OsMemFFS(mask) + index;
743 goto DONE;
744 }
745 }
746 } while (0);
747
748 if (curIndex == OS_MEM_FREE_LIST_COUNT) {
749 return NULL;
750 }
751
752 *outIndex = curIndex;
753 return OsMemFindCurSuitableBlock(poolHead, curIndex, size);
754DONE:
755 *outIndex = index;
756 return poolHead->freeList[index];
757}
758
759STATIC INLINE VOID OsMemSetFreeListBit(struct OsMemPoolHead *head, UINT32 index)
760{
761 head->freeListBitmap[BITMAP_INDEX(index)] |= 1U << (index & 0x1f);
762}
763
764STATIC INLINE VOID OsMemClearFreeListBit(struct OsMemPoolHead *head, UINT32 index)
765{
766 head->freeListBitmap[BITMAP_INDEX(index)] &= ~(1U << (index & 0x1f));
767}
768
769STATIC INLINE VOID OsMemListAdd(struct OsMemPoolHead *pool, UINT32 listIndex, struct OsMemFreeNodeHead *node)
770{
771 struct OsMemFreeNodeHead *firstNode = pool->freeList[listIndex];
772 if (firstNode != NULL) {
773 firstNode->prev = node;
774 }
775 node->prev = NULL;
776 node->next = firstNode;
777 pool->freeList[listIndex] = node;
778 OsMemSetFreeListBit(pool, listIndex);
779 node->header.magic = OS_MEM_NODE_MAGIC;
780}
781/// 从空闲链表中删除
782STATIC INLINE VOID OsMemListDelete(struct OsMemPoolHead *pool, UINT32 listIndex, struct OsMemFreeNodeHead *node)
783{
784 if (node == pool->freeList[listIndex]) {
785 pool->freeList[listIndex] = node->next;
786 if (node->next == NULL) {//如果链表空了
787 OsMemClearFreeListBit(pool, listIndex);//将位图位 置为 0
788 } else {
789 node->next->prev = NULL;
790 }
791 } else {
792 node->prev->next = node->next;
793 if (node->next != NULL) {
794 node->next->prev = node->prev;
795 }
796 }
797 node->header.magic = OS_MEM_NODE_MAGIC;
798}
799/// 添加一个空闲节点
800STATIC INLINE VOID OsMemFreeNodeAdd(VOID *pool, struct OsMemFreeNodeHead *node)
801{
802 UINT32 index = OsMemFreeListIndexGet(node->header.sizeAndFlag);//根据大小定位索引位
803 if (index >= OS_MEM_FREE_LIST_COUNT) {
804 LOS_Panic("The index of free lists is error, index = %u\n", index);
805 return;
806 }
807 OsMemListAdd(pool, index, node);//挂入链表
808}
809/// 从空闲链表上摘除节点
810STATIC INLINE VOID OsMemFreeNodeDelete(VOID *pool, struct OsMemFreeNodeHead *node)
811{
812 UINT32 index = OsMemFreeListIndexGet(node->header.sizeAndFlag);//根据大小定位索引位
813 if (index >= OS_MEM_FREE_LIST_COUNT) {
814 LOS_Panic("The index of free lists is error, index = %u\n", index);
815 return;
816 }
817 OsMemListDelete(pool, index, node);
818}
819//获取一个空闲的节点
820STATIC INLINE struct OsMemNodeHead *OsMemFreeNodeGet(VOID *pool, UINT32 size)
821{
822 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
823 UINT32 index;
824 struct OsMemFreeNodeHead *firstNode = OsMemFindNextSuitableBlock(pool, size, &index);
825 if (firstNode == NULL) {
826 return NULL;
827 }
828
829 OsMemListDelete(poolHead, index, firstNode);
830
831 return &firstNode->header;
832}
833/// 合并节点,和前面的节点合并 node 消失
834STATIC INLINE VOID OsMemMergeNode(struct OsMemNodeHead *node)
835{
836 struct OsMemNodeHead *nextNode = NULL;
837
838 node->ptr.prev->sizeAndFlag += node->sizeAndFlag; //前节点长度变长
839 nextNode = (struct OsMemNodeHead *)((UINTPTR)node + node->sizeAndFlag); // 下一个节点位置
840 if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) {//不是哨兵节点
841 nextNode->ptr.prev = node->ptr.prev;//后一个节点的前节点变成前前节点
842 }
843}
844/// 切割节点
845STATIC INLINE VOID OsMemSplitNode(VOID *pool, struct OsMemNodeHead *allocNode, UINT32 allocSize)
846{
847 struct OsMemFreeNodeHead *newFreeNode = NULL;
848 struct OsMemNodeHead *nextNode = NULL;
849
850 newFreeNode = (struct OsMemFreeNodeHead *)(VOID *)((UINT8 *)allocNode + allocSize);//切割后出现的新空闲节点,在分配节点的右侧
851 newFreeNode->header.ptr.prev = allocNode;//新节点指向前节点,说明是从左到右切割
852 newFreeNode->header.sizeAndFlag = allocNode->sizeAndFlag - allocSize;//新空闲节点大小
853 allocNode->sizeAndFlag = allocSize;//分配节点大小
854 nextNode = OS_MEM_NEXT_NODE(&newFreeNode->header);//获取新节点的下一个节点
855 if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) {//如果下一个节点不是哨兵节点(末尾节点)
856 nextNode->ptr.prev = &newFreeNode->header;//下一个节点的前节点为新空闲节点
857 if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->sizeAndFlag)) {//如果下一个节点也是空闲的
858 OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode);//删除下一个节点信息
859 OsMemMergeNode(nextNode);//下一个节点和新空闲节点 合并成一个新节点
860 }
861 }
862
863 OsMemFreeNodeAdd(pool, newFreeNode);//挂入空闲链表
864}
865//
866STATIC INLINE VOID *OsMemCreateUsedNode(VOID *addr)
867{
868 struct OsMemUsedNodeHead *node = (struct OsMemUsedNodeHead *)addr;//直接将地址转成使用节点,说明节点信息也存在内存池中
869 //这种用法是非常巧妙的
870#if OS_MEM_FREE_BY_TASKID
871 OsMemNodeSetTaskID(node);//设置使用内存节点的任务
872#endif
873
874#ifdef LOSCFG_KERNEL_LMS //检测内存泄漏
875 struct OsMemNodeHead *newNode = (struct OsMemNodeHead *)node;
876 if (g_lms != NULL) {
877 g_lms->mallocMark(newNode, OS_MEM_NEXT_NODE(newNode), OS_MEM_NODE_HEAD_SIZE);
878 }
879#endif
880 return node + 1; //@note_good 这个地方挺有意思的,只是将结构体扩展下,留一个 int 位 ,变成了已使用节点,返回的地址正是要分配给应用的地址
881}
882
883/*!
884 * @brief OsMemPoolInit 内存池初始化
885 * 内存池节点部分包含3种类型节点:未使用空闲内存节点(OsMemFreeNodeHead),已使用内存节点(OsMemUsedNodeHead) 和 尾节点(OsMemNodeHead)。
886 * \n 每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。
887 * \n 空闲内存节点和已使用内存节点后面的内存区域是数据域
888 * @param pool
889 * @param size
890 * @return
891 *
892 * @see
893 */
894STATIC UINT32 OsMemPoolInit(VOID *pool, UINT32 size)
895{
896 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
897 struct OsMemNodeHead *newNode = NULL;
898 struct OsMemNodeHead *endNode = NULL;
899#ifdef LOSCFG_KERNEL_LMS
900 UINT32 resize = 0;
901 if (g_lms != NULL) {
902 /*
903 * resize == 0, shadow memory init failed, no shadow memory for this pool, set poolSize as original size.
904 * resize != 0, shadow memory init successful, set poolSize as resize.
905 */
906 resize = g_lms->init(pool, size);
907 size = (resize == 0) ? size : resize;
908 }
909#endif
910 (VOID)memset(poolHead, 0, sizeof(struct OsMemPoolHead));
911
912 LOS_SpinInit(&poolHead->spinlock);
913 poolHead->info.pool = pool; //内存池的起始地址,但注意真正的内存并不是从此处分配,它只是用来记录这个内存块的开始位置而已.
914 poolHead->info.totalSize = size;//内存池总大小
915 poolHead->info.attr = OS_MEM_POOL_LOCK_ENABLE; /* default attr: lock, not expand. | 默认是上锁,不支持扩展,需扩展得另外设置*/
916
917 newNode = OS_MEM_FIRST_NODE(pool);//跳到第一个节点位置,即跳过结构体本身位置,真正的分配内存是从newNode开始的.
918 newNode->sizeAndFlag = (size - sizeof(struct OsMemPoolHead) - OS_MEM_NODE_HEAD_SIZE);//这才是可供分配给外界使用的总内存块大小,即数据域
919 //OS_MEM_NODE_HEAD_SIZE 叫当前使用节点,即指 newNode占用的空间
920 newNode->ptr.prev = NULL;//开始是空指向
921 newNode->magic = OS_MEM_NODE_MAGIC;//魔法数字 用于标识这是一个 OsMemNodeHead 节点, 魔法数字不能被覆盖,
922 OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)newNode);//添加一个空闲节点,由此有了首个可供分配的空闲节点
923
924 /* The last mem node */
925 endNode = OS_MEM_END_NODE(pool, size);//确定尾节点位置,尾节点没有数据域
926 endNode->magic = OS_MEM_NODE_MAGIC; //填入尾节点的魔法数字
927#if OS_MEM_EXPAND_ENABLE //支持扩展
928 endNode->ptr.next = NULL;//尾节点没有后继节点
929 OsMemSentinelNodeSet(endNode, NULL, 0);//将尾节点设置为哨兵节点
930#else
931 endNode->sizeAndFlag = 0;//0代表没有数据域
932 endNode->ptr.prev = newNode;//前驱指针指向第一个节点
933 OS_MEM_NODE_SET_USED_FLAG(endNode->sizeAndFlag);
934#endif
935#ifdef LOSCFG_MEM_WATERLINE //吃水线开关
936 poolHead->info.curUsedSize = sizeof(struct OsMemPoolHead) + OS_MEM_NODE_HEAD_SIZE;//内存池已使用了这么多空间,这些都是存内存池自身数据的空间,
937 //但此处是否还要算是 endNode ? @note_thinking
938 poolHead->info.waterLine = poolHead->info.curUsedSize; //设置吃水线
939#endif
940#ifdef LOSCFG_KERNEL_LMS
941 if (resize != 0) {
942 OsLmsFirstNodeMark(pool, newNode);
943 }
944#endif
945 return LOS_OK;
946}
947
948#ifdef LOSCFG_MEM_MUL_POOL
949STATIC VOID OsMemPoolDeinit(VOID *pool)
950{
951 (VOID)memset(pool, 0, sizeof(struct OsMemPoolHead));
952}
953/// 新增内存池
954STATIC UINT32 OsMemPoolAdd(VOID *pool, UINT32 size)
955{
956 VOID *nextPool = g_poolHead;
957 VOID *curPool = g_poolHead;
958 UINTPTR poolEnd;
959 while (nextPool != NULL) {//单链表遍历方式
961 if (((pool <= nextPool) && (((UINTPTR)pool + size) > (UINTPTR)nextPool)) ||
962 (((UINTPTR)pool < poolEnd) && (((UINTPTR)pool + size) >= poolEnd))) {
963 PRINT_ERR("pool [%#x, %#x) conflict with pool [%#x, %#x)\n",
964 pool, (UINTPTR)pool + size,
966 return LOS_NOK;
967 }
968 curPool = nextPool;
969 nextPool = ((struct OsMemPoolHead *)nextPool)->nextPool;
970 }
971
972 if (g_poolHead == NULL) {
973 g_poolHead = pool; //首个内存池
974 } else {
975 ((struct OsMemPoolHead *)curPool)->nextPool = pool; //两池扯上关系
976 }
977
978 ((struct OsMemPoolHead *)pool)->nextPool = NULL; //新池下一个无所指
979 return LOS_OK;
980}
981/// 删除内存池
982STATIC UINT32 OsMemPoolDelete(VOID *pool)
983{
984 UINT32 ret = LOS_NOK;
985 VOID *nextPool = NULL;
986 VOID *curPool = NULL;
987
988 do {
989 if (pool == g_poolHead) {
990 g_poolHead = ((struct OsMemPoolHead *)g_poolHead)->nextPool;
991 ret = LOS_OK;
992 break;
993 }
994
995 curPool = g_poolHead;
997 while (nextPool != NULL) {
998 if (pool == nextPool) {
999 ((struct OsMemPoolHead *)curPool)->nextPool = ((struct OsMemPoolHead *)nextPool)->nextPool;
1000 ret = LOS_OK;
1001 break;
1002 }
1003 curPool = nextPool;
1004 nextPool = ((struct OsMemPoolHead *)nextPool)->nextPool;
1005 }
1006 } while (0);
1007
1008 return ret;
1009}
1010#endif
1011
1012/*!
1013 * @brief LOS_MemInit 初始化一块指定的动态内存池,大小为size
1014 * 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。
1015 * @param pool
1016 * @param size
1017 * @return
1018 * @attention EndNode作为内存池末尾的节点,size为0。
1019 * @see
1020 */
1021UINT32 LOS_MemInit(VOID *pool, UINT32 size)
1022{
1023 if ((pool == NULL) || (size <= OS_MEM_MIN_POOL_SIZE)) {
1024 return OS_ERROR;
1025 }
1026
1027 size = OS_MEM_ALIGN(size, OS_MEM_ALIGN_SIZE);//4个字节对齐
1028 if (OsMemPoolInit(pool, size)) {
1029 return OS_ERROR;
1030 }
1031
1032#ifdef LOSCFG_MEM_MUL_POOL //多内存池开关
1033 if (OsMemPoolAdd(pool, size)) {
1034 (VOID)OsMemPoolDeinit(pool);
1035 return OS_ERROR;
1036 }
1037#endif
1038
1039 OsHookCall(LOS_HOOK_TYPE_MEM_INIT, pool, size);//打印日志
1040 return LOS_OK;
1041}
1042
1043#ifdef LOSCFG_MEM_MUL_POOL
1044/// 删除指定内存池
1046{
1047 if (pool == NULL) {
1048 return OS_ERROR;
1049 }
1050
1051 if (OsMemPoolDelete(pool)) {
1052 return OS_ERROR;
1053 }
1054
1055 OsMemPoolDeinit(pool);
1056
1057 OsHookCall(LOS_HOOK_TYPE_MEM_DEINIT, pool);
1058 return LOS_OK;
1059}
1060/// 打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。
1062{
1063 VOID *nextPool = g_poolHead;
1064 UINT32 index = 0;
1065 while (nextPool != NULL) {
1066 PRINTK("pool%u :\n", index);
1067 index++;
1069 nextPool = ((struct OsMemPoolHead *)nextPool)->nextPool;
1070 }
1071 return index;
1072}
1073#endif
1074/// 从指定动态内存池中申请size长度的内存
1075STATIC INLINE VOID *OsMemAlloc(struct OsMemPoolHead *pool, UINT32 size, UINT32 intSave)
1076{
1077 struct OsMemNodeHead *allocNode = NULL;
1078
1079#ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK
1080 if (OsMemAllocCheck(pool, intSave) == LOS_NOK) {
1081 return NULL;
1082 }
1083#endif
1084
1085 UINT32 allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE);
1086#if OS_MEM_EXPAND_ENABLE
1087retry: //这种写法也挺赞的 @note_good
1088#endif
1089 allocNode = OsMemFreeNodeGet(pool, allocSize);//获取空闲节点
1090 if (allocNode == NULL) {//没有内存了,怎搞?
1091#if OS_MEM_EXPAND_ENABLE
1092 if (pool->info.attr & OS_MEM_POOL_EXPAND_ENABLE) {
1093 INT32 ret = OsMemPoolExpand(pool, allocSize, intSave);//扩展内存池
1094 if (ret == 0) {
1095 goto retry;//再来一遍
1096 }
1097 }
1098#endif
1099 MEM_UNLOCK(pool, intSave);
1100 PRINT_ERR("---------------------------------------------------"
1101 "--------------------------------------------------------\n");
1102 OsMemInfoPrint(pool);
1103 PRINT_ERR("[%s] No suitable free block, require free node size: 0x%x\n", __FUNCTION__, allocSize);
1104 PRINT_ERR("----------------------------------------------------"
1105 "-------------------------------------------------------\n");
1106 MEM_LOCK(pool, intSave);
1107 return NULL;
1108 }
1109
1110 if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_MIN_ALLOC_SIZE) <= allocNode->sizeAndFlag) {//所需小于内存池可供分配量
1111 OsMemSplitNode(pool, allocNode, allocSize);//劈开内存池
1112 }
1113
1114 OS_MEM_NODE_SET_USED_FLAG(allocNode->sizeAndFlag);//给节点贴上已使用的标签
1115 OsMemWaterUsedRecord(pool, OS_MEM_NODE_GET_SIZE(allocNode->sizeAndFlag));//更新吃水线
1116
1117#ifdef LOSCFG_MEM_LEAKCHECK //检测内存泄漏开关
1118 OsMemLinkRegisterRecord(allocNode);
1119#endif
1120 return OsMemCreateUsedNode((VOID *)allocNode);//创建已使用节点
1121}
1122/// 从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
1123VOID *LOS_MemAlloc(VOID *pool, UINT32 size)
1124{
1125 if ((pool == NULL) || (size == 0)) {//没提供内存池时
1126 return (size > 0) ? OsVmBootMemAlloc(size) : NULL;
1127 }
1128
1129 if (size < OS_MEM_MIN_ALLOC_SIZE) {
1130 size = OS_MEM_MIN_ALLOC_SIZE;
1131 }
1132
1133 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
1134 VOID *ptr = NULL;
1135 UINT32 intSave;
1136
1137 do {
1138 if (OS_MEM_NODE_GET_USED_FLAG(size) || OS_MEM_NODE_GET_ALIGNED_FLAG(size)) {
1139 break;
1140 }
1141 MEM_LOCK(poolHead, intSave);
1142 ptr = OsMemAlloc(poolHead, size, intSave);//真正的分配内存函数,详细查看 鸿蒙内核源码分析(内存池篇)
1143 MEM_UNLOCK(poolHead, intSave);
1144 } while (0);
1145
1146 OsHookCall(LOS_HOOK_TYPE_MEM_ALLOC, pool, ptr, size);//打印日志,到此一游
1147 return ptr;
1148}
1149/// 从指定内存池中申请size长度的内存且地址按boundary字节对齐的内存
1150VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary)
1151{
1152 UINT32 gapSize;
1153
1154 if ((pool == NULL) || (size == 0) || (boundary == 0) || !OS_MEM_IS_POW_TWO(boundary) ||
1155 !OS_MEM_IS_ALIGNED(boundary, sizeof(VOID *))) {
1156 return NULL;
1157 }
1158
1159 if (size < OS_MEM_MIN_ALLOC_SIZE) {
1160 size = OS_MEM_MIN_ALLOC_SIZE;
1161 }
1162
1163 /*
1164 * sizeof(gapSize) bytes stores offset between alignedPtr and ptr,
1165 * the ptr has been OS_MEM_ALIGN_SIZE(4 or 8) aligned, so maximum
1166 * offset between alignedPtr and ptr is boundary - OS_MEM_ALIGN_SIZE
1167 */
1168 if ((boundary - sizeof(gapSize)) > ((UINT32)(-1) - size)) {
1169 return NULL;
1170 }
1171
1172 UINT32 useSize = (size + boundary) - sizeof(gapSize);
1173 if (OS_MEM_NODE_GET_USED_FLAG(useSize) || OS_MEM_NODE_GET_ALIGNED_FLAG(useSize)) {
1174 return NULL;
1175 }
1176
1177 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
1178 UINT32 intSave;
1179 VOID *ptr = NULL;
1180 VOID *alignedPtr = NULL;
1181
1182 do {
1183 MEM_LOCK(poolHead, intSave);
1184 ptr = OsMemAlloc(pool, useSize, intSave);
1185 MEM_UNLOCK(poolHead, intSave);
1186 alignedPtr = (VOID *)OS_MEM_ALIGN(ptr, boundary);
1187 if (ptr == alignedPtr) {
1188#ifdef LOSCFG_KERNEL_LMS
1189 OsLmsAllocAlignMark(ptr, alignedPtr, size);
1190#endif
1191 break;
1192 }
1193
1194 /* store gapSize in address (ptr - 4), it will be checked while free */
1195 gapSize = (UINT32)((UINTPTR)alignedPtr - (UINTPTR)ptr);
1196 struct OsMemUsedNodeHead *allocNode = (struct OsMemUsedNodeHead *)ptr - 1;
1197 OS_MEM_NODE_SET_ALIGNED_FLAG(allocNode->header.sizeAndFlag);
1198 OS_MEM_NODE_SET_ALIGNED_FLAG(gapSize);
1199 *(UINT32 *)((UINTPTR)alignedPtr - sizeof(gapSize)) = gapSize;
1200#ifdef LOSCFG_KERNEL_LMS
1201 OsLmsAllocAlignMark(ptr, alignedPtr, size);
1202#endif
1203 ptr = alignedPtr;
1204 } while (0);
1205
1206 OsHookCall(LOS_HOOK_TYPE_MEM_ALLOCALIGN, pool, ptr, size, boundary);//打印对齐日志,表示程序曾临幸过此处
1207 return ptr;
1208}
1209/// 内存池有效性检查
1210STATIC INLINE BOOL OsMemAddrValidCheck(const struct OsMemPoolHead *pool, const VOID *addr)
1211{
1212 UINT32 size;
1213
1214 /* First node prev is NULL */
1215 if (addr == NULL) {
1216 return TRUE;
1217 }
1218
1219 size = pool->info.totalSize;
1220 if (OS_MEM_MIDDLE_ADDR_OPEN_END(pool + 1, addr, (UINTPTR)pool + size)) {
1221 return TRUE;
1222 }
1223#if OS_MEM_EXPAND_ENABLE //如果支持可扩展
1224 struct OsMemNodeHead *node = NULL;
1225 struct OsMemNodeHead *sentinel = OS_MEM_END_NODE(pool, size);
1226 while (OsMemIsLastSentinelNode(sentinel) == FALSE) {
1227 size = OS_MEM_NODE_GET_SIZE(sentinel->sizeAndFlag);
1228 node = OsMemSentinelNodeGet(sentinel);
1229 sentinel = OS_MEM_END_NODE(node, size);
1230 if (OS_MEM_MIDDLE_ADDR_OPEN_END(node, addr, (UINTPTR)node + size)) {
1231 return TRUE;
1232 }
1233 }
1234#endif
1235 return FALSE;
1236}
1237
1238STATIC INLINE BOOL OsMemIsNodeValid(const struct OsMemNodeHead *node, const struct OsMemNodeHead *startNode,
1239 const struct OsMemNodeHead *endNode,
1240 const struct OsMemPoolHead *poolInfo)
1241{
1242 if (!OS_MEM_MIDDLE_ADDR(startNode, node, endNode)) {
1243 return FALSE;
1244 }
1245
1246 if (OS_MEM_NODE_GET_USED_FLAG(node->sizeAndFlag)) {
1247 if (!OS_MEM_MAGIC_VALID(node)) {
1248 return FALSE;
1249 }
1250 return TRUE;
1251 }
1252
1253 if (!OsMemAddrValidCheck(poolInfo, node->ptr.prev)) {
1254 return FALSE;
1255 }
1256
1257 return TRUE;
1258}
1259
1260STATIC BOOL MemCheckUsedNode(const struct OsMemPoolHead *pool, const struct OsMemNodeHead *node,
1261 const struct OsMemNodeHead *startNode, const struct OsMemNodeHead *endNode)
1262{
1263 if (!OsMemIsNodeValid(node, startNode, endNode, pool)) {
1264 return FALSE;
1265 }
1266
1267 if (!OS_MEM_NODE_GET_USED_FLAG(node->sizeAndFlag)) {
1268 return FALSE;
1269 }
1270
1271 const struct OsMemNodeHead *nextNode = OS_MEM_NEXT_NODE(node);
1272 if (!OsMemIsNodeValid(nextNode, startNode, endNode, pool)) {
1273 return FALSE;
1274 }
1275
1276 if (!OS_MEM_NODE_GET_LAST_FLAG(nextNode->sizeAndFlag)) {
1277 if (nextNode->ptr.prev != node) {
1278 return FALSE;
1279 }
1280 }
1281
1282 if ((node != startNode) &&
1283 ((!OsMemIsNodeValid(node->ptr.prev, startNode, endNode, pool)) ||
1284 (OS_MEM_NEXT_NODE(node->ptr.prev) != node))) {
1285 return FALSE;
1286 }
1287
1288 return TRUE;
1289}
1290
1291STATIC UINT32 OsMemCheckUsedNode(const struct OsMemPoolHead *pool, const struct OsMemNodeHead *node)
1292{
1293 struct OsMemNodeHead *startNode = (struct OsMemNodeHead *)OS_MEM_FIRST_NODE(pool);
1294 struct OsMemNodeHead *endNode = (struct OsMemNodeHead *)OS_MEM_END_NODE(pool, pool->info.totalSize);
1295 BOOL doneFlag = FALSE;
1296
1297 do {
1298 doneFlag = MemCheckUsedNode(pool, node, startNode, endNode);
1299 if (!doneFlag) {
1300#if OS_MEM_EXPAND_ENABLE
1301 if (OsMemIsLastSentinelNode(endNode) == FALSE) {
1302 startNode = OsMemSentinelNodeGet(endNode);
1303 endNode = OS_MEM_END_NODE(startNode, OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag));
1304 continue;
1305 }
1306#endif
1307 return LOS_NOK;
1308 }
1309 } while (!doneFlag);
1310
1311 return LOS_OK;
1312}
1313/// 释放内存
1314STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead *node)
1315{
1316 UINT32 ret = OsMemCheckUsedNode(pool, node);
1317 if (ret != LOS_OK) {
1318 PRINT_ERR("OsMemFree check error!\n");
1319 return ret;
1320 }
1321
1322#ifdef LOSCFG_MEM_WATERLINE
1323 pool->info.curUsedSize -= OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);//降低水位线
1324#endif
1325
1326 node->sizeAndFlag = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);//获取大小和标记
1327#ifdef LOSCFG_MEM_LEAKCHECK
1329#endif
1330#ifdef LOSCFG_KERNEL_LMS
1331 struct OsMemNodeHead *nextNodeBackup = OS_MEM_NEXT_NODE(node);
1332 struct OsMemNodeHead *curNodeBackup = node;
1333 if (g_lms != NULL) {
1334 g_lms->check((UINTPTR)node + OS_MEM_NODE_HEAD_SIZE, TRUE);
1335 }
1336#endif
1337 struct OsMemNodeHead *preNode = node->ptr.prev; /* merage preNode | 合并前一个节点*/
1338 if ((preNode != NULL) && !OS_MEM_NODE_GET_USED_FLAG(preNode->sizeAndFlag)) {
1339 OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)preNode);//删除前节点的信息
1340 OsMemMergeNode(node);//向前合并
1341 node = preNode;
1342 }
1343
1344 struct OsMemNodeHead *nextNode = OS_MEM_NEXT_NODE(node); /* merage nextNode | 计算后一个节点位置*/
1345 if ((nextNode != NULL) && !OS_MEM_NODE_GET_USED_FLAG(nextNode->sizeAndFlag)) {
1346 OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode);//删除后节点信息
1347 OsMemMergeNode(nextNode);//合并节点
1348 }
1349
1350#if OS_MEM_EXPAND_ENABLE
1351 if (pool->info.attr & OS_MEM_POOL_EXPAND_ENABLE) {
1352 /* if this is a expand head node, and all unused, free it to pmm */
1353 if ((node->ptr.prev != NULL) && (node->ptr.prev > node)) {
1354 if (TryShrinkPool(pool, node)) {
1355 return LOS_OK;
1356 }
1357 }
1358 }
1359#endif
1360 OsMemFreeNodeAdd(pool, (struct OsMemFreeNodeHead *)node);
1361#ifdef LOSCFG_KERNEL_LMS
1362 if (g_lms != NULL) {
1363 g_lms->freeMark(curNodeBackup, nextNodeBackup, OS_MEM_NODE_HEAD_SIZE);
1364 }
1365#endif
1366 return ret;
1367}
1368/// 释放从指定动态内存中申请的内存
1369UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
1370{
1371 UINT32 intSave;
1372 UINT32 ret = LOS_NOK;
1373
1374 if ((pool == NULL) || (ptr == NULL) || !OS_MEM_IS_ALIGNED(pool, sizeof(VOID *)) ||
1375 !OS_MEM_IS_ALIGNED(ptr, sizeof(VOID *))) {
1376 return ret;
1377 }
1378 OsHookCall(LOS_HOOK_TYPE_MEM_FREE, pool, ptr);
1379
1380 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
1381 struct OsMemNodeHead *node = NULL;
1382
1383 do {
1384 UINT32 gapSize = *(UINT32 *)((UINTPTR)ptr - sizeof(UINT32));//获取节点大小和标签 即: sizeAndFlag
1385 if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize) && OS_MEM_NODE_GET_USED_FLAG(gapSize)) {
1386 PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FUNCTION__, __LINE__, gapSize);
1387 break;
1388 }
1389
1390 node = (struct OsMemNodeHead *)((UINTPTR)ptr - OS_MEM_NODE_HEAD_SIZE);//定位到节点开始位置
1391
1392 if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize)) {
1393 gapSize = OS_MEM_NODE_GET_ALIGNED_GAPSIZE(gapSize);
1394 if ((gapSize & (OS_MEM_ALIGN_SIZE - 1)) || (gapSize > ((UINTPTR)ptr - OS_MEM_NODE_HEAD_SIZE))) {
1395 PRINT_ERR("illegal gapSize: 0x%x\n", gapSize);
1396 break;
1397 }
1398 node = (struct OsMemNodeHead *)((UINTPTR)ptr - gapSize - OS_MEM_NODE_HEAD_SIZE);
1399 }
1400 MEM_LOCK(poolHead, intSave);
1401 ret = OsMemFree(poolHead, node);
1402 MEM_UNLOCK(poolHead, intSave);
1403 } while (0);
1404
1405 return ret;
1406}
1407
1408STATIC INLINE VOID OsMemReAllocSmaller(VOID *pool, UINT32 allocSize, struct OsMemNodeHead *node, UINT32 nodeSize)
1409{
1410#ifdef LOSCFG_MEM_WATERLINE
1411 struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool;
1412#endif
1413 node->sizeAndFlag = nodeSize;
1414 if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_MIN_ALLOC_SIZE) <= nodeSize) {
1415 OsMemSplitNode(pool, node, allocSize);
1416 OS_MEM_NODE_SET_USED_FLAG(node->sizeAndFlag);
1417#ifdef LOSCFG_MEM_WATERLINE
1418 poolInfo->info.curUsedSize -= nodeSize - allocSize;
1419#endif
1420#ifdef LOSCFG_KERNEL_LMS
1422 } else {
1423 OsLmsReallocResizeMark(node, allocSize);
1424#endif
1425 }
1426 OS_MEM_NODE_SET_USED_FLAG(node->sizeAndFlag);
1427#ifdef LOSCFG_MEM_LEAKCHECK
1429#endif
1430}
1431
1432STATIC INLINE VOID OsMemMergeNodeForReAllocBigger(VOID *pool, UINT32 allocSize, struct OsMemNodeHead *node,
1433 UINT32 nodeSize, struct OsMemNodeHead *nextNode)
1434{
1435 node->sizeAndFlag = nodeSize;
1436 OsMemFreeNodeDelete(pool, (struct OsMemFreeNodeHead *)nextNode);
1437 OsMemMergeNode(nextNode);
1438#ifdef LOSCFG_KERNEL_LMS
1440#endif
1441 if ((allocSize + OS_MEM_NODE_HEAD_SIZE + OS_MEM_MIN_ALLOC_SIZE) <= node->sizeAndFlag) {
1442 OsMemSplitNode(pool, node, allocSize);
1443#ifdef LOSCFG_KERNEL_LMS
1445 } else {
1446 OsLmsReallocResizeMark(node, allocSize);
1447#endif
1448 }
1449 OS_MEM_NODE_SET_USED_FLAG(node->sizeAndFlag);
1450 OsMemWaterUsedRecord((struct OsMemPoolHead *)pool, node->sizeAndFlag - nodeSize);
1451#ifdef LOSCFG_MEM_LEAKCHECK
1453#endif
1454}
1455
1456STATIC INLINE VOID *OsGetRealPtr(const VOID *pool, VOID *ptr)
1457{
1458 VOID *realPtr = ptr;
1459 UINT32 gapSize = *((UINT32 *)((UINTPTR)ptr - sizeof(UINT32)));
1460
1461 if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize) && OS_MEM_NODE_GET_USED_FLAG(gapSize)) {
1462 PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FUNCTION__, __LINE__, gapSize);
1463 return NULL;
1464 }
1465 if (OS_MEM_NODE_GET_ALIGNED_FLAG(gapSize)) {
1466 gapSize = OS_MEM_NODE_GET_ALIGNED_GAPSIZE(gapSize);
1467 if ((gapSize & (OS_MEM_ALIGN_SIZE - 1)) ||
1468 (gapSize > ((UINTPTR)ptr - OS_MEM_NODE_HEAD_SIZE - (UINTPTR)pool))) {
1469 PRINT_ERR("[%s:%d]gapSize:0x%x error\n", __FUNCTION__, __LINE__, gapSize);
1470 return NULL;
1471 }
1472 realPtr = (VOID *)((UINTPTR)ptr - (UINTPTR)gapSize);
1473 }
1474 return realPtr;
1475}
1476
1477STATIC INLINE VOID *OsMemRealloc(struct OsMemPoolHead *pool, const VOID *ptr,
1478 struct OsMemNodeHead *node, UINT32 size, UINT32 intSave)
1479{
1480 struct OsMemNodeHead *nextNode = NULL;
1481 UINT32 allocSize = OS_MEM_ALIGN(size + OS_MEM_NODE_HEAD_SIZE, OS_MEM_ALIGN_SIZE);
1482 UINT32 nodeSize = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);
1483 VOID *tmpPtr = NULL;
1484
1485 if (nodeSize >= allocSize) {
1486 OsMemReAllocSmaller(pool, allocSize, node, nodeSize);
1487 return (VOID *)ptr;
1488 }
1489
1490 nextNode = OS_MEM_NEXT_NODE(node);
1491 if (!OS_MEM_NODE_GET_USED_FLAG(nextNode->sizeAndFlag) &&
1492 ((nextNode->sizeAndFlag + nodeSize) >= allocSize)) {
1493 OsMemMergeNodeForReAllocBigger(pool, allocSize, node, nodeSize, nextNode);
1494 return (VOID *)ptr;
1495 }
1496
1497 tmpPtr = OsMemAlloc(pool, size, intSave);
1498 if (tmpPtr != NULL) {
1499 if (memcpy_s(tmpPtr, size, ptr, (nodeSize - OS_MEM_NODE_HEAD_SIZE)) != EOK) {
1500 MEM_UNLOCK(pool, intSave);
1501 (VOID)LOS_MemFree((VOID *)pool, (VOID *)tmpPtr);
1502 MEM_LOCK(pool, intSave);
1503 return NULL;
1504 }
1505 (VOID)OsMemFree(pool, node);
1506 }
1507 return tmpPtr;
1508}
1509/// 按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块
1510VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size)
1511{
1512 if ((pool == NULL) || OS_MEM_NODE_GET_USED_FLAG(size) || OS_MEM_NODE_GET_ALIGNED_FLAG(size)) {
1513 return NULL;
1514 }
1515 OsHookCall(LOS_HOOK_TYPE_MEM_REALLOC, pool, ptr, size);
1516 if (size < OS_MEM_MIN_ALLOC_SIZE) {
1517 size = OS_MEM_MIN_ALLOC_SIZE;
1518 }
1519
1520 if (ptr == NULL) {
1521 return LOS_MemAlloc(pool, size);
1522 }
1523
1524 if (size == 0) {
1525 (VOID)LOS_MemFree(pool, ptr);
1526 return NULL;
1527 }
1528
1529 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
1530 struct OsMemNodeHead *node = NULL;
1531 VOID *newPtr = NULL;
1532 UINT32 intSave;
1533
1534 MEM_LOCK(poolHead, intSave);
1535 do {
1536 ptr = OsGetRealPtr(pool, ptr);
1537 if (ptr == NULL) {
1538 break;
1539 }
1540
1541 node = (struct OsMemNodeHead *)((UINTPTR)ptr - OS_MEM_NODE_HEAD_SIZE);
1542 if (OsMemCheckUsedNode(pool, node) != LOS_OK) {
1543 break;
1544 }
1545
1546 newPtr = OsMemRealloc(pool, ptr, node, size, intSave);
1547 } while (0);
1548 MEM_UNLOCK(poolHead, intSave);
1549
1550 return newPtr;
1551}
1552
1553#if OS_MEM_FREE_BY_TASKID
1555{
1556 if (pool == NULL) {
1557 return OS_ERROR;
1558 }
1559
1560 if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
1561 return OS_ERROR;
1562 }
1563
1564 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
1565 struct OsMemNodeHead *tmpNode = NULL;
1566 struct OsMemUsedNodeHead *node = NULL;
1567 struct OsMemNodeHead *endNode = NULL;
1568 UINT32 size;
1569 UINT32 intSave;
1570
1571 MEM_LOCK(poolHead, intSave);
1572 endNode = OS_MEM_END_NODE(pool, poolHead->info.totalSize);
1573 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= endNode;) {
1574 if (tmpNode == endNode) {
1575 if (OsMemIsLastSentinelNode(endNode) == FALSE) {
1576 size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);
1577 tmpNode = OsMemSentinelNodeGet(endNode);
1578 endNode = OS_MEM_END_NODE(tmpNode, size);
1579 continue;
1580 } else {
1581 break;
1582 }
1583 } else {
1584 if (!OS_MEM_NODE_GET_USED_FLAG(tmpNode->sizeAndFlag)) {
1585 tmpNode = OS_MEM_NEXT_NODE(tmpNode);
1586 continue;
1587 }
1588
1589 node = (struct OsMemUsedNodeHead *)tmpNode;
1590 tmpNode = OS_MEM_NEXT_NODE(tmpNode);
1591
1592 if (node->taskID == taskID) {
1593 OsMemFree(poolHead, &node->header);
1594 }
1595 }
1596 }
1597 MEM_UNLOCK(poolHead, intSave);
1598
1599 return LOS_OK;
1600}
1601#endif
1602/// 获取指定动态内存池的总大小
1604{
1605 UINT32 count = 0;
1606
1607 if (pool == NULL) {
1608 return LOS_NOK;
1609 }
1610
1611 count += ((struct OsMemPoolHead *)pool)->info.totalSize; // 这里的 += 好像没必要吧?, = 就可以了, @note_thinking
1612
1613#if OS_MEM_EXPAND_ENABLE //支持扩展
1614 UINT32 size;
1615 struct OsMemNodeHead *node = NULL;
1616 struct OsMemNodeHead *sentinel = OS_MEM_END_NODE(pool, count);//获取哨兵节点
1617
1618 while (OsMemIsLastSentinelNode(sentinel) == FALSE) {//不是最后一个节点
1619 size = OS_MEM_NODE_GET_SIZE(sentinel->sizeAndFlag);//数据域大小
1620 node = OsMemSentinelNodeGet(sentinel);//再获取哨兵节点
1621 sentinel = OS_MEM_END_NODE(node, size);//获取尾节点
1622 count += size; //内存池大小变大
1623 }
1624#endif
1625 return count;
1626}
1627/// 获取指定动态内存池的总使用量大小
1629{
1630 struct OsMemNodeHead *tmpNode = NULL;
1631 struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool;
1632 struct OsMemNodeHead *endNode = NULL;
1633 UINT32 memUsed = 0;
1634 UINT32 intSave;
1635
1636 if (pool == NULL) {
1637 return LOS_NOK;
1638 }
1639
1640 MEM_LOCK(poolInfo, intSave);
1641 endNode = OS_MEM_END_NODE(pool, poolInfo->info.totalSize);
1642#if OS_MEM_EXPAND_ENABLE
1643 UINT32 size;
1644 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= endNode;) {
1645 if (tmpNode == endNode) {
1646 memUsed += OS_MEM_NODE_HEAD_SIZE;
1647 if (OsMemIsLastSentinelNode(endNode) == FALSE) {
1648 size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);
1649 tmpNode = OsMemSentinelNodeGet(endNode);
1650 endNode = OS_MEM_END_NODE(tmpNode, size);
1651 continue;
1652 } else {
1653 break;
1654 }
1655 } else {
1656 if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->sizeAndFlag)) {
1657 memUsed += OS_MEM_NODE_GET_SIZE(tmpNode->sizeAndFlag);
1658 }
1659 tmpNode = OS_MEM_NEXT_NODE(tmpNode);
1660 }
1661 }
1662#else
1663 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode < endNode;) {
1664 if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->sizeAndFlag)) {
1665 memUsed += OS_MEM_NODE_GET_SIZE(tmpNode->sizeAndFlag);
1666 }
1667 tmpNode = OS_MEM_NEXT_NODE(tmpNode);
1668 }
1669#endif
1670 MEM_UNLOCK(poolInfo, intSave);
1671
1672 return memUsed;
1673}
1674
1675STATIC INLINE VOID OsMemMagicCheckPrint(struct OsMemNodeHead **tmpNode)
1676{
1677 PRINT_ERR("[%s], %d, memory check error!\n"
1678 "memory used but magic num wrong, magic num = %#x\n",
1679 __FUNCTION__, __LINE__, (*tmpNode)->magic);
1680}
1681
1682STATIC UINT32 OsMemAddrValidCheckPrint(const VOID *pool, struct OsMemFreeNodeHead **tmpNode)
1683{
1684 if (((*tmpNode)->prev != NULL) && !OsMemAddrValidCheck(pool, (*tmpNode)->prev)) {
1685 PRINT_ERR("[%s], %d, memory check error!\n"
1686 " freeNode.prev:%#x is out of legal mem range\n",
1687 __FUNCTION__, __LINE__, (*tmpNode)->prev);
1688 return LOS_NOK;
1689 }
1690 if (((*tmpNode)->next != NULL) && !OsMemAddrValidCheck(pool, (*tmpNode)->next)) {
1691 PRINT_ERR("[%s], %d, memory check error!\n"
1692 " freeNode.next:%#x is out of legal mem range\n",
1693 __FUNCTION__, __LINE__, (*tmpNode)->next);
1694 return LOS_NOK;
1695 }
1696 return LOS_OK;
1697}
1698
1699STATIC UINT32 OsMemIntegrityCheckSub(struct OsMemNodeHead **tmpNode, const VOID *pool,
1700 const struct OsMemNodeHead *endNode)
1701{
1702 if (!OS_MEM_MAGIC_VALID(*tmpNode)) {
1703 OsMemMagicCheckPrint(tmpNode);
1704 return LOS_NOK;
1705 }
1706
1707 if (!OS_MEM_NODE_GET_USED_FLAG((*tmpNode)->sizeAndFlag)) { /* is free node, check free node range */
1708 if (OsMemAddrValidCheckPrint(pool, (struct OsMemFreeNodeHead **)tmpNode)) {
1709 return LOS_NOK;
1710 }
1711 }
1712 return LOS_OK;
1713}
1714
1716 const struct OsMemFreeNodeHead *node)
1717{
1718 if (!OsMemAddrValidCheck(pool, node) ||
1719 !OsMemAddrValidCheck(pool, node->prev) ||
1720 !OsMemAddrValidCheck(pool, node->next) ||
1721 !OsMemAddrValidCheck(pool, node->header.ptr.prev)) {
1722 return LOS_NOK;
1723 }
1724
1725 if (!OS_MEM_IS_ALIGNED(node, sizeof(VOID *)) ||
1726 !OS_MEM_IS_ALIGNED(node->prev, sizeof(VOID *)) ||
1727 !OS_MEM_IS_ALIGNED(node->next, sizeof(VOID *)) ||
1728 !OS_MEM_IS_ALIGNED(node->header.ptr.prev, sizeof(VOID *))) {
1729 return LOS_NOK;
1730 }
1731
1732 return LOS_OK;
1733}
1734
1735STATIC VOID OsMemPoolHeadCheck(const struct OsMemPoolHead *pool)
1736{
1737 struct OsMemFreeNodeHead *tmpNode = NULL;
1738 UINT32 index;
1739 UINT32 flag = 0;
1740
1741 if ((pool->info.pool != pool) || !OS_MEM_IS_ALIGNED(pool, sizeof(VOID *))) {
1742 PRINT_ERR("wrong mem pool addr: %#x, func:%s, line:%d\n", pool, __FUNCTION__, __LINE__);
1743 return;
1744 }
1745
1746 for (index = 0; index < OS_MEM_FREE_LIST_COUNT; index++) {
1747 for (tmpNode = pool->freeList[index]; tmpNode != NULL; tmpNode = tmpNode->next) {
1748 if (OsMemFreeListNodeCheck(pool, tmpNode)) {
1749 flag = 1;
1750 PRINT_ERR("FreeListIndex: %u, node: %#x, bNode: %#x, prev: %#x, next: %#x\n",
1751 index, tmpNode, tmpNode->header.ptr.prev, tmpNode->prev, tmpNode->next);
1752 goto OUT;
1753 }
1754 }
1755 }
1756
1757OUT:
1758 if (flag) {
1759 PRINTK("mem pool info: poolAddr: %#x, poolSize: 0x%x\n", pool, pool->info.totalSize);
1760#ifdef LOSCFG_MEM_WATERLINE
1761 PRINTK("mem pool info: poolWaterLine: 0x%x, poolCurUsedSize: 0x%x\n", pool->info.waterLine,
1762 pool->info.curUsedSize);
1763#endif
1764#if OS_MEM_EXPAND_ENABLE
1765 UINT32 size;
1766 struct OsMemNodeHead *node = NULL;
1767 struct OsMemNodeHead *sentinel = OS_MEM_END_NODE(pool, pool->info.totalSize);
1768 while (OsMemIsLastSentinelNode(sentinel) == FALSE) {
1769 size = OS_MEM_NODE_GET_SIZE(sentinel->sizeAndFlag);
1770 node = OsMemSentinelNodeGet(sentinel);
1771 sentinel = OS_MEM_END_NODE(node, size);
1772 PRINTK("expand node info: nodeAddr: %#x, nodeSize: 0x%x\n", node, size);
1773 }
1774#endif
1775 }
1776}
1777//对指定内存池做完整性检查,
1778STATIC UINT32 OsMemIntegrityCheck(const struct OsMemPoolHead *pool, struct OsMemNodeHead **tmpNode,
1779 struct OsMemNodeHead **preNode)
1780{
1781 struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize);
1782
1783 OsMemPoolHeadCheck(pool);
1784
1785 *preNode = OS_MEM_FIRST_NODE(pool);
1786 do {
1787 for (*tmpNode = *preNode; *tmpNode < endNode; *tmpNode = OS_MEM_NEXT_NODE(*tmpNode)) {
1788 if (OsMemIntegrityCheckSub(tmpNode, pool, endNode) == LOS_NOK) {
1789 return LOS_NOK;
1790 }
1791 *preNode = *tmpNode;
1792 }
1793#if OS_MEM_EXPAND_ENABLE
1794 if (OsMemIsLastSentinelNode(*tmpNode) == FALSE) {
1795 *preNode = OsMemSentinelNodeGet(*tmpNode);
1796 endNode = OS_MEM_END_NODE(*preNode, OS_MEM_NODE_GET_SIZE((*tmpNode)->sizeAndFlag));
1797 } else
1798#endif
1799 {
1800 break;
1801 }
1802 } while (1);
1803 return LOS_OK;
1804}
1805
1806STATIC VOID OsMemNodeInfo(const struct OsMemNodeHead *tmpNode,
1807 const struct OsMemNodeHead *preNode)
1808{
1809 struct OsMemUsedNodeHead *usedNode = NULL;
1810 struct OsMemFreeNodeHead *freeNode = NULL;
1811
1812 if (tmpNode == preNode) {
1813 PRINTK("\n the broken node is the first node\n");
1814 }
1815
1816 if (OS_MEM_NODE_GET_USED_FLAG(tmpNode->sizeAndFlag)) {
1817 usedNode = (struct OsMemUsedNodeHead *)tmpNode;
1818 PRINTK("\n broken node head: %#x %#x %#x, ",
1819 usedNode->header.ptr.prev, usedNode->header.magic, usedNode->header.sizeAndFlag);
1820 } else {
1821 freeNode = (struct OsMemFreeNodeHead *)tmpNode;
1822 PRINTK("\n broken node head: %#x %#x %#x %#x, %#x",
1823 freeNode->header.ptr.prev, freeNode->next, freeNode->prev, freeNode->header.magic,
1824 freeNode->header.sizeAndFlag);
1825 }
1826
1827 if (OS_MEM_NODE_GET_USED_FLAG(preNode->sizeAndFlag)) {
1828 usedNode = (struct OsMemUsedNodeHead *)preNode;
1829 PRINTK("prev node head: %#x %#x %#x\n",
1830 usedNode->header.ptr.prev, usedNode->header.magic, usedNode->header.sizeAndFlag);
1831 } else {
1832 freeNode = (struct OsMemFreeNodeHead *)preNode;
1833 PRINTK("prev node head: %#x %#x %#x %#x, %#x",
1834 freeNode->header.ptr.prev, freeNode->next, freeNode->prev, freeNode->header.magic,
1835 freeNode->header.sizeAndFlag);
1836 }
1837
1838#ifdef LOSCFG_MEM_LEAKCHECK
1839 OsMemNodeBacktraceInfo(tmpNode, preNode);
1840#endif
1841
1842 PRINTK("\n---------------------------------------------\n");
1843 PRINTK(" dump mem tmpNode:%#x ~ %#x\n", tmpNode, ((UINTPTR)tmpNode + OS_MEM_NODE_DUMP_SIZE));
1844 OsDumpMemByte(OS_MEM_NODE_DUMP_SIZE, (UINTPTR)tmpNode);
1845 PRINTK("\n---------------------------------------------\n");
1846 if (preNode != tmpNode) {
1847 PRINTK(" dump mem :%#x ~ tmpNode:%#x\n", ((UINTPTR)tmpNode - OS_MEM_NODE_DUMP_SIZE), tmpNode);
1848 OsDumpMemByte(OS_MEM_NODE_DUMP_SIZE, ((UINTPTR)tmpNode - OS_MEM_NODE_DUMP_SIZE));
1849 PRINTK("\n---------------------------------------------\n");
1850 }
1851}
1852
1854 const struct OsMemNodeHead *tmpNode,
1855 const struct OsMemNodeHead *preNode,
1856 UINT32 intSave)
1857{
1858 OsMemNodeInfo(tmpNode, preNode);
1859
1860#if OS_MEM_FREE_BY_TASKID
1861 LosTaskCB *taskCB = NULL;
1862 if (OS_MEM_NODE_GET_USED_FLAG(preNode->sizeAndFlag)) {
1863 struct OsMemUsedNodeHead *usedNode = (struct OsMemUsedNodeHead *)preNode;
1864 UINT32 taskID = usedNode->taskID;
1865 if (OS_TID_CHECK_INVALID(taskID)) {
1866 MEM_UNLOCK(pool, intSave);
1867 LOS_Panic("Task ID %u in pre node is invalid!\n", taskID);
1868 return;
1869 }
1870
1871 taskCB = OS_TCB_FROM_TID(taskID);
1872 if (OsTaskIsUnused(taskCB) || (taskCB->taskEntry == NULL)) {
1873 MEM_UNLOCK(pool, intSave);
1874 LOS_Panic("\r\nTask ID %u in pre node is not created!\n", taskID);
1875 return;
1876 }
1877 } else {
1878 PRINTK("The prev node is free\n");
1879 }
1880 MEM_UNLOCK(pool, intSave);
1881 LOS_Panic("cur node: %#x\npre node: %#x\npre node was allocated by task:%s\n",
1882 tmpNode, preNode, taskCB->taskName);
1883#else
1884 MEM_UNLOCK(pool, intSave);
1885 LOS_Panic("Memory integrity check error, cur node: %#x, pre node: %#x\n", tmpNode, preNode);
1886#endif
1887}
1888
1889#ifdef LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK
1890STATIC INLINE UINT32 OsMemAllocCheck(struct OsMemPoolHead *pool, UINT32 intSave)
1891{
1892 struct OsMemNodeHead *tmpNode = NULL;
1893 struct OsMemNodeHead *preNode = NULL;
1894
1895 if (OsMemIntegrityCheck(pool, &tmpNode, &preNode)) {
1896 OsMemIntegrityCheckError(pool, tmpNode, preNode, intSave);
1897 return LOS_NOK;
1898 }
1899 return LOS_OK;
1900}
1901#endif
1902/// 对指定内存池做完整性检查
1904{
1905 if (pool == NULL) {
1906 return LOS_NOK;
1907 }
1908
1909 struct OsMemPoolHead *poolHead = (struct OsMemPoolHead *)pool;
1910 struct OsMemNodeHead *tmpNode = NULL;
1911 struct OsMemNodeHead *preNode = NULL;
1912 UINT32 intSave = 0;
1913
1914 MEM_LOCK(poolHead, intSave);
1915 if (OsMemIntegrityCheck(poolHead, &tmpNode, &preNode)) {
1916 goto ERROR_OUT;
1917 }
1918 MEM_UNLOCK(poolHead, intSave);
1919 return LOS_OK;
1920
1921ERROR_OUT:
1922 OsMemIntegrityCheckError(poolHead, tmpNode, preNode, intSave);
1923 return LOS_NOK;
1924}
1925
1926STATIC INLINE VOID OsMemInfoGet(struct OsMemPoolHead *poolInfo, struct OsMemNodeHead *node,
1927 LOS_MEM_POOL_STATUS *poolStatus)
1928{
1929 UINT32 totalUsedSize = 0;
1930 UINT32 totalFreeSize = 0;
1931 UINT32 usedNodeNum = 0;
1932 UINT32 freeNodeNum = 0;
1933 UINT32 maxFreeSize = 0;
1934 UINT32 size;
1935
1936 if (!OS_MEM_NODE_GET_USED_FLAG(node->sizeAndFlag)) {
1937 size = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);
1938 ++freeNodeNum;
1939 totalFreeSize += size;
1940 if (maxFreeSize < size) {
1941 maxFreeSize = size;
1942 }
1943 } else {
1944 size = OS_MEM_NODE_GET_SIZE(node->sizeAndFlag);
1945 ++usedNodeNum;
1946 totalUsedSize += size;
1947 }
1948
1949 poolStatus->totalUsedSize += totalUsedSize;
1950 poolStatus->totalFreeSize += totalFreeSize;
1951 poolStatus->maxFreeNodeSize = MAX(poolStatus->maxFreeNodeSize, maxFreeSize);
1952 poolStatus->usedNodeNum += usedNodeNum;
1953 poolStatus->freeNodeNum += freeNodeNum;
1954}
1955
1956/*!
1957 * @brief LOS_MemInfoGet
1958 * 获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小
1959 * @param pool
1960 * @param poolStatus
1961 * @return
1962 *
1963 * @see
1964 */
1966{//内存碎片率计算:同样调用LOS_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。
1967 struct OsMemPoolHead *poolInfo = pool;
1968
1969 if (poolStatus == NULL) {
1970 PRINT_ERR("can't use NULL addr to save info\n");
1971 return LOS_NOK;
1972 }
1973
1974 if ((pool == NULL) || (poolInfo->info.pool != pool)) {
1975 PRINT_ERR("wrong mem pool addr: %#x, line:%d\n", poolInfo, __LINE__);
1976 return LOS_NOK;
1977 }
1978
1979 (VOID)memset(poolStatus, 0, sizeof(LOS_MEM_POOL_STATUS));
1980
1981 struct OsMemNodeHead *tmpNode = NULL;
1982 struct OsMemNodeHead *endNode = NULL;
1983 UINT32 intSave;
1984
1985 MEM_LOCK(poolInfo, intSave);
1986 endNode = OS_MEM_END_NODE(pool, poolInfo->info.totalSize);
1987#if OS_MEM_EXPAND_ENABLE
1988 UINT32 size;
1989 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode <= endNode; tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
1990 if (tmpNode == endNode) {
1991 poolStatus->totalUsedSize += OS_MEM_NODE_HEAD_SIZE;
1992 poolStatus->usedNodeNum++;
1993 if (OsMemIsLastSentinelNode(endNode) == FALSE) {
1994 size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);
1995 tmpNode = OsMemSentinelNodeGet(endNode);
1996 endNode = OS_MEM_END_NODE(tmpNode, size);
1997 continue;
1998 } else {
1999 break;
2000 }
2001 } else {
2002 OsMemInfoGet(poolInfo, tmpNode, poolStatus);
2003 }
2004 }
2005#else
2006 for (tmpNode = OS_MEM_FIRST_NODE(pool); tmpNode < endNode; tmpNode = OS_MEM_NEXT_NODE(tmpNode)) {
2007 OsMemInfoGet(poolInfo, tmpNode, poolStatus);
2008 }
2009#endif
2010#ifdef LOSCFG_MEM_WATERLINE
2011 poolStatus->usageWaterLine = poolInfo->info.waterLine;
2012#endif
2013 MEM_UNLOCK(poolInfo, intSave);
2014
2015 return LOS_OK;
2016}
2017
2018STATIC VOID OsMemInfoPrint(VOID *pool)
2019{
2020 struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool;
2021 LOS_MEM_POOL_STATUS status = {0};
2022
2023 if (LOS_MemInfoGet(pool, &status) == LOS_NOK) {
2024 return;
2025 }
2026
2027#ifdef LOSCFG_MEM_WATERLINE
2028 PRINTK("pool addr pool size used size free size "
2029 "max free node size used node num free node num UsageWaterLine\n");
2030 PRINTK("--------------- -------- ------- -------- "
2031 "-------------- ------------- ------------ ------------\n");
2032 PRINTK("%-16#x 0x%-8x 0x%-8x 0x%-8x 0x%-16x 0x%-13x 0x%-13x 0x%-13x\n",
2033 poolInfo->info.pool, LOS_MemPoolSizeGet(pool), status.totalUsedSize,
2034 status.totalFreeSize, status.maxFreeNodeSize, status.usedNodeNum,
2035 status.freeNodeNum, status.usageWaterLine);
2036#else
2037 PRINTK("pool addr pool size used size free size "
2038 "max free node size used node num free node num\n");
2039 PRINTK("--------------- -------- ------- -------- "
2040 "-------------- ------------- ------------\n");
2041 PRINTK("%-16#x 0x%-8x 0x%-8x 0x%-8x 0x%-16x 0x%-13x 0x%-13x\n",
2042 poolInfo->info.pool, LOS_MemPoolSizeGet(pool), status.totalUsedSize,
2043 status.totalFreeSize, status.maxFreeNodeSize, status.usedNodeNum,
2044 status.freeNodeNum);
2045#endif
2046}
2047/// 打印指定内存池的空闲内存块的大小及数量
2049{
2050 struct OsMemPoolHead *poolInfo = (struct OsMemPoolHead *)pool;
2051
2052 if ((poolInfo == NULL) || ((UINTPTR)pool != (UINTPTR)poolInfo->info.pool)) {
2053 PRINT_ERR("wrong mem pool addr: %#x, line:%d\n", poolInfo, __LINE__);
2054 return LOS_NOK;
2055 }
2056
2057 struct OsMemFreeNodeHead *node = NULL;
2058 UINT32 countNum[OS_MEM_FREE_LIST_COUNT] = {0};
2059 UINT32 index;
2060 UINT32 intSave;
2061
2062 MEM_LOCK(poolInfo, intSave);
2063 for (index = 0; index < OS_MEM_FREE_LIST_COUNT; index++) {
2064 node = poolInfo->freeList[index];
2065 while (node) {
2066 node = node->next;
2067 countNum[index]++;
2068 }
2069 }
2070 MEM_UNLOCK(poolInfo, intSave);
2071
2072 PRINTK("\n ************************ left free node number**********************\n");
2073 for (index = 0; index < OS_MEM_FREE_LIST_COUNT; index++) {
2074 if (countNum[index] == 0) {
2075 continue;
2076 }
2077
2078 PRINTK("free index: %03u, ", index);
2079 if (index < OS_MEM_SMALL_BUCKET_COUNT) {
2080 PRINTK("size: [%#x], num: %u\n", (index + 1) << 2, countNum[index]); /* 2: setup is 4. */
2081 } else {
2082 UINT32 val = 1 << (((index - OS_MEM_SMALL_BUCKET_COUNT) >> OS_MEM_SLI) + OS_MEM_LARGE_START_BUCKET);
2083 UINT32 offset = val >> OS_MEM_SLI;
2084 PRINTK("size: [%#x, %#x], num: %u\n",
2085 (offset * ((index - OS_MEM_SMALL_BUCKET_COUNT) % (1 << OS_MEM_SLI))) + val,
2086 ((offset * (((index - OS_MEM_SMALL_BUCKET_COUNT) % (1 << OS_MEM_SLI)) + 1)) + val - 1),
2087 countNum[index]);
2088 }
2089 }
2090 PRINTK("\n ********************************************************************\n\n");
2091
2092 return LOS_OK;
2093}
2094///内核空间动态内存(堆内存)初始化 , 争取系统动态内存池
2096{
2097 STATUS_T ret;
2098 VOID *ptr = NULL;
2099 /*
2100 * roundup to MB aligned in order to set kernel attributes. kernel text/code/data attributes
2101 * should page mapping, remaining region should section mapping. so the boundary should be
2102 * MB aligned.
2103 */
2104 UINTPTR end = ROUNDUP(g_vmBootMemBase + size, MB);
2105 size = end - g_vmBootMemBase;
2106
2107 ptr = OsVmBootMemAlloc(size);
2108 if (!ptr) {
2109 PRINT_ERR("vmm_kheap_init boot_alloc_mem failed! %d\n", size);
2110 return -1;
2111 }
2112
2113 m_aucSysMem0 = m_aucSysMem1 = ptr;// 指定内核内存池的位置
2114 ret = LOS_MemInit(m_aucSysMem0, size); //初始化内存池,供内核分配动态内存
2115 if (ret != LOS_OK) {
2116 PRINT_ERR("vmm_kheap_init LOS_MemInit failed!\n");
2117 g_vmBootMemBase -= size;
2118 return ret;
2119 }
2120#if OS_MEM_EXPAND_ENABLE
2121 LOS_MemExpandEnable(OS_SYS_MEM_ADDR);//支持扩展系统动态内存
2122#endif
2123 return LOS_OK;
2124}
2125///< 判断地址是否在堆区
2126BOOL OsMemIsHeapNode(const VOID *ptr)
2127{
2128 struct OsMemPoolHead *pool = (struct OsMemPoolHead *)m_aucSysMem1;//内核堆区开始地址
2129 struct OsMemNodeHead *firstNode = OS_MEM_FIRST_NODE(pool);//获取内存池首个节点
2130 struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize);//获取内存池的尾节点
2131
2132 if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {//如果在首尾范围内
2133 return TRUE;
2134 }
2135
2136#if OS_MEM_EXPAND_ENABLE//内存池经过扩展后,新旧块的虚拟地址是不连续的,所以需要跳块判断
2137 UINT32 intSave;
2138 UINT32 size;//详细查看百篇博客系列篇之 鸿蒙内核源码分析(内存池篇)
2139 MEM_LOCK(pool, intSave); //获取自旋锁
2140 while (OsMemIsLastSentinelNode(endNode) == FALSE) { //哨兵节点是内存池结束的标记
2141 size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);//获取节点大小
2142 firstNode = OsMemSentinelNodeGet(endNode);//获取下一块的开始地址
2143 endNode = OS_MEM_END_NODE(firstNode, size);//获取下一块的尾节点
2144 if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {//判断地址是否在该块中
2145 MEM_UNLOCK(pool, intSave);
2146 return TRUE;
2147 }
2148 }
2149 MEM_UNLOCK(pool, intSave);
2150#endif
2151 return FALSE;
2152}
2153
2154
LITE_OS_SEC_TEXT UINTPTR LOS_Align(UINTPTR addr, UINT32 boundary)
Align the value (addr) by some bytes (boundary) you specify.
Definition: los_misc.c:35
VOID LOS_RecordLR(UINTPTR *LR, UINT32 LRSize, UINT32 recordCount, UINT32 jumpCount)
record LR function.
Definition: los_exc.c:1353
NORETURN VOID LOS_Panic(const CHAR *fmt,...)
Kernel panic function.
UINT32 LOS_MemPoolList(VOID)
打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。
Definition: los_memory.c:1061
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT8 * m_aucSysMem1
系统动态内存池地址的起始地址 @note_thinking 能否不要用 0,1来命名核心变量 ???
Definition: los_memory.c:108
VOID * LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size)
按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块
Definition: los_memory.c:1510
UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus)
LOS_MemInfoGet 获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小
Definition: los_memory.c:1965
VOID * LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary)
从指定内存池中申请size长度的内存且地址按boundary字节对齐的内存
Definition: los_memory.c:1150
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
UINT32 LOS_MemFreeNodeShow(VOID *pool)
打印指定内存池的空闲内存块的大小及数量
Definition: los_memory.c:2048
UINT32 LOS_MemPoolSizeGet(const VOID *pool)
获取指定动态内存池的总大小
Definition: los_memory.c:1603
VOID LOS_MemExpandEnable(VOID *pool)
Enable memory pool to support dynamic expansion.
Definition: los_memory.c:500
UINT32 LOS_MemTotalUsedGet(VOID *pool)
获取指定动态内存池的总使用量大小
Definition: los_memory.c:1628
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
UINT32 LOS_MemDeInit(VOID *pool)
删除指定内存池
Definition: los_memory.c:1045
UINT32 LOS_MemInit(VOID *pool, UINT32 size)
LOS_MemInit 初始化一块指定的动态内存池,大小为size 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。
Definition: los_memory.c:1021
UINT32 LOS_MemIntegrityCheck(const VOID *pool)
对指定内存池做完整性检查
Definition: los_memory.c:1903
LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)
Obtain current running task ID.
Definition: los_task.c:331
void * memset(void *addr, int c, size_t len)
Definition: lms_libc.c:36
LmsHook * g_lms
Definition: los_lms.c:68
VOID LOS_LmsCheckPoolDel(const VOID *pool)
Definition: los_lms.c:189
UINT32 LOS_MemFreeByTaskID(VOID *pool, UINT32 taskID)
Definition: los_memory.c:1554
STATIC INLINE VOID OsMemLinkRegisterRecord(struct OsMemNodeHead *node)
Definition: los_memory.c:575
STATIC INLINE UINT32 OsMemFreeListIndexGet(UINT32 size)
Definition: los_memory.c:675
BOOL OsMemIsHeapNode(const VOID *ptr)
Definition: los_memory.c:2126
STATIC INLINE VOID OsLmsFirstNodeMark(VOID *pool, struct OsMemNodeHead *node)
Definition: los_memory.c:511
STATIC INLINE VOID OsLmsReallocSplitNodeMark(struct OsMemNodeHead *node)
Definition: los_memory.c:553
VOID * g_poolHead
Definition: los_memory.c:111
STATIC INLINE struct OsMemFreeNodeHead * OsMemFindCurSuitableBlock(struct OsMemPoolHead *poolHead, UINT32 index, UINT32 size)
Definition: los_memory.c:686
STATIC INLINE struct OsMemFreeNodeHead * OsMemFindNextSuitableBlock(VOID *pool, UINT32 size, UINT32 *outIndex)
找到下一个合适的块
Definition: los_memory.c:715
STATIC INLINE VOID OsMemWaterUsedRecord(struct OsMemPoolHead *pool, UINT32 size)
Definition: los_memory.c:282
STATIC UINT32 OsMemPoolDelete(VOID *pool)
删除内存池
Definition: los_memory.c:982
STATIC VOID OsMemPoolHeadCheck(const struct OsMemPoolHead *pool)
Definition: los_memory.c:1735
STATIC INLINE VOID OsMemSetFreeListBit(struct OsMemPoolHead *head, UINT32 index)
Definition: los_memory.c:759
VOID OsMemUsedNodeShow(VOID *pool)
打印已使用的节点
Definition: los_memory.c:601
STATIC INLINE VOID OsMemInfoGet(struct OsMemPoolHead *poolInfo, struct OsMemNodeHead *node, LOS_MEM_POOL_STATUS *poolStatus)
Definition: los_memory.c:1926
STATIC INLINE INT32 OsMemPoolExpandSub(VOID *pool, UINT32 size, UINT32 intSave)
内存池扩展实现
Definition: los_memory.c:428
STATIC INLINE UINT16 OsMemFLS(UINT32 bitmap)
Definition: los_memory.c:142
STATIC INLINE VOID OsMemMergeNode(struct OsMemNodeHead *node)
合并节点,和前面的节点合并 node 消失
Definition: los_memory.c:834
STATIC INLINE UINT32 OsMemFlGet(UINT32 size)
Definition: los_memory.c:153
STATIC UINT32 OsMemCheckUsedNode(const struct OsMemPoolHead *pool, const struct OsMemNodeHead *node)
Definition: los_memory.c:1291
STATIC INLINE BOOL OsMemAddrValidCheck(const struct OsMemPoolHead *pool, const VOID *addr)
内存池有效性检查
Definition: los_memory.c:1210
STATIC VOID OsMemNodeInfo(const struct OsMemNodeHead *tmpNode, const struct OsMemNodeHead *preNode)
Definition: los_memory.c:1806
STATIC INLINE VOID OsMemSentinelNodeSet(struct OsMemNodeHead *sentinelNode, VOID *newNode, UINT32 size)
设置哨兵节点内容
Definition: los_memory.c:342
STATIC INLINE VOID OsMemClearFreeListBit(struct OsMemPoolHead *head, UINT32 index)
Definition: los_memory.c:764
STATIC INLINE VOID OsMemSplitNode(VOID *pool, struct OsMemNodeHead *allocNode, UINT32 allocSize)
切割节点
Definition: los_memory.c:845
STATIC INLINE VOID * OsMemAlloc(struct OsMemPoolHead *pool, UINT32 size, UINT32 intSave)
从指定动态内存池中申请size长度的内存
Definition: los_memory.c:1075
STATIC INLINE struct OsMemNodeHead * OsMemFreeNodeGet(VOID *pool, UINT32 size)
Definition: los_memory.c:820
STATIC VOID OsMemNodeBacktraceInfo(const struct OsMemNodeHead *tmpNode, const struct OsMemNodeHead *preNode)
Definition: los_memory.c:659
STATIC UINT32 OsMemPoolInit(VOID *pool, UINT32 size)
OsMemPoolInit 内存池初始化 内存池节点部分包含3种类型节点:未使用空闲内存节点(OsMemFreeNodeHead),已使用内存节点(OsMemUsedNodeHead) 和 尾节点(Os...
Definition: los_memory.c:894
STATIC INLINE UINT32 OsMemFree(struct OsMemPoolHead *pool, struct OsMemNodeHead *node)
释放内存
Definition: los_memory.c:1314
STATIC INLINE VOID OsMemReAllocSmaller(VOID *pool, UINT32 allocSize, struct OsMemNodeHead *node, UINT32 nodeSize)
Definition: los_memory.c:1408
STATIC UINT32 OsMemAddrValidCheckPrint(const VOID *pool, struct OsMemFreeNodeHead **tmpNode)
Definition: los_memory.c:1682
STATIC INLINE VOID OsMemMagicCheckPrint(struct OsMemNodeHead **tmpNode)
Definition: los_memory.c:1675
STATIC INLINE UINT16 OsMemFFS(UINT32 bitmap)
Definition: los_memory.c:135
STATIC INLINE BOOL TryShrinkPool(const VOID *pool, const struct OsMemNodeHead *node)
Definition: los_memory.c:393
STATIC INLINE BOOL OsMemIsNodeValid(const struct OsMemNodeHead *node, const struct OsMemNodeHead *startNode, const struct OsMemNodeHead *endNode, const struct OsMemPoolHead *poolInfo)
Definition: los_memory.c:1238
STATIC UINT32 OsMemIntegrityCheck(const struct OsMemPoolHead *pool, struct OsMemNodeHead **tmpNode, struct OsMemNodeHead **preNode)
Definition: los_memory.c:1778
STATIC INLINE BOOL OsMemSentinelNodeCheck(struct OsMemNodeHead *sentinelNode)
检查哨兵节点
Definition: los_memory.c:314
STATIC INLINE VOID OsMemFreeNodeDelete(VOID *pool, struct OsMemFreeNodeHead *node)
从空闲链表上摘除节点
Definition: los_memory.c:810
STATIC INLINE VOID OsMemListDelete(struct OsMemPoolHead *pool, UINT32 listIndex, struct OsMemFreeNodeHead *node)
从空闲链表中删除
Definition: los_memory.c:782
STATIC UINT32 OsMemIntegrityCheckSub(struct OsMemNodeHead **tmpNode, const VOID *pool, const struct OsMemNodeHead *endNode)
Definition: los_memory.c:1699
STATUS_T OsKHeapInit(size_t size)
内核空间动态内存(堆内存)初始化 , 争取系统动态内存池
Definition: los_memory.c:2095
STATIC INLINE VOID OsMemFreeNodeAdd(VOID *pool, struct OsMemFreeNodeHead *node)
添加一个空闲节点
Definition: los_memory.c:800
STATIC INLINE VOID * OsMemCreateUsedNode(VOID *addr)
Definition: los_memory.c:866
STATIC INLINE VOID OsMemUsedNodePrint(struct OsMemNodeHead *node)
Definition: los_memory.c:580
STATIC INLINE UINT32 OsMemNotEmptyIndexGet(struct OsMemPoolHead *poolHead, UINT32 index)
Definition: los_memory.c:701
STATIC INLINE INT32 OsMemPoolExpand(VOID *pool, UINT32 allocSize, UINT32 intSave)
扩展内存池
Definition: los_memory.c:478
STATIC INLINE UINT32 OsMemLog2(UINT32 size)
Definition: los_memory.c:147
STATIC INLINE struct OsMemNodeHead * PreSentinelNodeGet(const VOID *pool, const struct OsMemNodeHead *node)
Definition: los_memory.c:359
STATIC VOID OsMemIntegrityCheckError(struct OsMemPoolHead *pool, const struct OsMemNodeHead *tmpNode, const struct OsMemNodeHead *preNode, UINT32 intSave)
Definition: los_memory.c:1853
STATIC INLINE VOID * OsGetRealPtr(const VOID *pool, VOID *ptr)
Definition: los_memory.c:1456
STATIC INLINE struct OsMemNodeHead * OsMemLastSentinelNodeGet(const struct OsMemNodeHead *sentinelNode)
更新哨兵节点内容
Definition: los_memory.c:299
STATIC INLINE VOID OsMemMergeNodeForReAllocBigger(VOID *pool, UINT32 allocSize, struct OsMemNodeHead *node, UINT32 nodeSize, struct OsMemNodeHead *nextNode)
Definition: los_memory.c:1432
STATIC INLINE BOOL OsMemIsLastSentinelNode(struct OsMemNodeHead *sentinelNode)
是否为最后一个哨兵节点
Definition: los_memory.c:327
STATIC UINT32 OsMemFreeListNodeCheck(const struct OsMemPoolHead *pool, const struct OsMemFreeNodeHead *node)
Definition: los_memory.c:1715
UINT32 OsMemLargeNodeFree(const VOID *ptr)
大内存释放
Definition: los_memory.c:382
STATIC BOOL MemCheckUsedNode(const struct OsMemPoolHead *pool, const struct OsMemNodeHead *node, const struct OsMemNodeHead *startNode, const struct OsMemNodeHead *endNode)
Definition: los_memory.c:1260
STATIC INLINE VOID OsLmsReallocResizeMark(struct OsMemNodeHead *node, UINT32 resize)
Definition: los_memory.c:565
STATIC VOID OsMemPoolDeinit(VOID *pool)
Definition: los_memory.c:949
STATIC INLINE UINT32 OsMemSlGet(UINT32 size, UINT32 fl)
Definition: los_memory.c:162
STATIC INLINE VOID * OsMemRealloc(struct OsMemPoolHead *pool, const VOID *ptr, struct OsMemNodeHead *node, UINT32 size, UINT32 intSave)
Definition: los_memory.c:1477
STATIC INLINE UINT32 OsMemAllocCheck(struct OsMemPoolHead *pool, UINT32 intSave)
Definition: los_memory.c:1890
STATIC INLINE VOID OsMemNodeSetTaskID(struct OsMemUsedNodeHead *node)
Definition: los_memory.c:275
STATIC INLINE VOID OsLmsAllocAlignMark(VOID *ptr, VOID *alignedPtr, UINT32 size)
Definition: los_memory.c:525
STATIC INLINE VOID * OsMemSentinelNodeGet(struct OsMemNodeHead *node)
Definition: los_memory.c:354
STATIC INLINE VOID OsMemListAdd(struct OsMemPoolHead *pool, UINT32 listIndex, struct OsMemFreeNodeHead *node)
Definition: los_memory.c:769
STATIC VOID OsMemInfoPrint(VOID *pool)
Definition: los_memory.c:2018
STATIC UINT32 OsMemPoolAdd(VOID *pool, UINT32 size)
新增内存池
Definition: los_memory.c:954
STATIC INLINE VOID OsLmsReallocMergeNodeMark(struct OsMemNodeHead *node)
Definition: los_memory.c:543
VOID OsDumpMemByte(size_t length, UINTPTR addr)
VOID LOS_SpinInit(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:37
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
任务是否在使用
Definition: los_task_pri.h:255
unsigned short UINT16
Definition: los_typedef.h:56
signed int INT32
Definition: los_typedef.h:60
unsigned char UINT8
Definition: los_typedef.h:55
int STATUS_T
Definition: los_typedef.h:215
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57
size_t BOOL
Definition: los_typedef.h:88
VOID * OsVmBootMemAlloc(size_t len)
Definition: los_vm_boot.c:50
UINTPTR g_vmBootMemBase
虚拟内存区间检查, 需理解 los_vm_zone.h 中画出的鸿蒙虚拟内存全景图
Definition: los_vm_boot.c:45
int OsTryShrinkMemory(size_t nPage)
Definition: los_vm_scan.c:340
VOID * LOS_PhysPagesAllocContiguous(size_t nPages)
分配连续的物理页
Definition: los_vm_phys.c:478
VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages)
释放指定页数地址连续的物理内存
Definition: los_vm_phys.c:494
LosVmPage * OsVmVaddrToPage(VOID *ptr)
通过虚拟地址找映射的物理页框
Definition: los_vm_phys.c:295
VOID(* simpleMark)(UINTPTR startAddr, UINTPTR endAddr, UINT32 value)
Definition: los_lms_pri.h:100
UINT32(* init)(const VOID *pool, UINT32 size)
Definition: los_lms_pri.h:97
VOID(* mallocMark)(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
Definition: los_lms_pri.h:98
VOID(* check)(UINTPTR checkAddr, BOOL isFreeCheck)
Definition: los_lms_pri.h:101
VOID(* freeMark)(const VOID *curNodeStart, const VOID *nextNodeStart, UINT32 nodeHeadSize)
Definition: los_lms_pri.h:99
内存池空闲节点
Definition: los_memory.c:188
struct OsMemFreeNodeHead * next
后一个空闲后继节点
Definition: los_memory.c:191
struct OsMemFreeNodeHead * prev
前一个空闲前驱节点
Definition: los_memory.c:190
struct OsMemNodeHead header
内存池节点
Definition: los_memory.c:189
内存池节点
Definition: los_memory.c:169
struct OsMemNodeHead * prev
Definition: los_memory.c:172
union OsMemNodeHead::@5 ptr
UINT32 sizeAndFlag
节点总大小+标签
Definition: los_memory.c:178
struct OsMemNodeHead * next
Definition: los_memory.c:173
UINTPTR linkReg[LOS_RECORD_LR_CNT]
存放左右节点地址,用于检测
Definition: los_memory.c:176
UINT32 magic
魔法数字 0xABCDDCBA
Definition: los_memory.c:170
内存池头信息
Definition: los_memory.c:204
struct OsMemFreeNodeHead * freeList[OS_MEM_FREE_LIST_COUNT]
空闲节点链表 32 + 24 * 8 = 224
Definition: los_memory.c:207
struct OsMemPoolInfo info
记录内存池的信息
Definition: los_memory.c:205
VOID * nextPool
指向下一个内存池 OsMemPoolHead 类型
Definition: los_memory.c:210
SPIN_LOCK_S spinlock
操作本池的自旋锁,涉及CPU多核竞争,所以必须得是自旋锁
Definition: los_memory.c:208
UINT32 freeListBitmap[OS_MEM_BITMAP_WORDS]
空闲位图 int[7] = 32 * 7 = 224 > 223
Definition: los_memory.c:206
内存池信息
Definition: los_memory.c:194
UINT32 curUsedSize
Definition: los_memory.c:200
UINT32 totalSize
总大小,确定了内存池的边界
Definition: los_memory.c:196
VOID * pool
指向内存块基地址,仅做记录而已,真正的分配内存跟它没啥关系
Definition: los_memory.c:195
UINT32 attr
属性 default attr: lock, not expand.
Definition: los_memory.c:197
UINT32 waterLine
Definition: los_memory.c:199
已使用内存池节点
Definition: los_memory.c:181
struct OsMemNodeHead header
已被使用节点
Definition: los_memory.c:182
UINT32 taskID
使用节点的任务ID
Definition: los_memory.c:184
TSK_ENTRY_FUNC taskEntry
CHAR taskName[OS_TCB_NAME_LEN]
物理页框描述符 虚拟内存体现的是程序对内存资源的需求,而物理内存是对该请求的供应。 伙伴算法的思想是:把内存中连续的空闲页框空间看成是空闲页框块,并按照它们的大小(连续页框的数目)分组
Definition: los_vm_page.h:53
UINT16 nPages
Definition: los_vm_page.h:61