• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2023 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2009-12-22
13  * Description: Fsc 内存实现
14  */
15 #include "prt_task_external.h"
16 #include "prt_fscmem_internal.h"
17 
18 /* 判断初始化内存地址和大小是否为4字节对齐 */
19 #define OS_MEM_GETBIT(addr) (addr & (U32)(sizeof(U32) - 1))
20 
21 OS_SEC_BSS struct TagMemFuncLib g_memArithAPI; /* 算法对应API */
22 OS_SEC_BSS struct TagFscMemCtrl g_fscMemNodeList[OS_FSC_MEM_LAST_IDX];
23 OS_SEC_BSS U32 g_fscMemBitMap = 1;
24 
OsFscMemSearch(U32 size,U32 * idx)25 OS_SEC_TEXT struct TagFscMemCtrl *OsFscMemSearch(U32 size, U32 *idx)
26 {
27     U32 staIdx;
28     struct TagFscMemCtrl *currBlk = NULL;
29     struct TagFscMemCtrl *headBlk = NULL;
30 
31     staIdx = OS_FSC_MEM_SZ2IDX(size);
32     *idx = staIdx + 1;
33 
34     while (TRUE) {
35         *idx = OsGetLmb1((g_fscMemBitMap << *idx) >> *idx);
36         if (OS_FSC_MEM_LAST_IDX <= *idx) {
37             *idx = staIdx;
38 
39             headBlk = &g_fscMemNodeList[*idx];
40             currBlk = headBlk->next;
41 
42             /* 空闲链表非空 */
43             while (currBlk != headBlk) {
44                 /* 找到可用的内存块 */
45                 if (OS_FSC_MEM_SZGET(currBlk) >= size) {
46                     return currBlk;
47                 }
48 
49                 currBlk = currBlk->next;
50             }
51 
52             OS_REPORT_ERROR(OS_ERRNO_FSCMEM_ALLOC_NO_MEMORY);
53             return NULL;
54         }
55 
56         headBlk = &g_fscMemNodeList[*idx];
57         /* 空闲链表为空,清除BitMap标志位 */
58         if (headBlk->next == headBlk) {
59             g_fscMemBitMap &= ~(OS_FSC_MEM_IDX2BIT(*idx));
60         } else {
61             break;
62         }
63     }
64     currBlk = headBlk->next;
65 
66     return currBlk;
67 }
68 
OsFscMemAllocInner(U32 mid,U32 size,uintptr_t align)69 OS_SEC_TEXT void *OsFscMemAllocInner(U32 mid, U32 size, uintptr_t align)
70 {
71     U32 idx;
72     U32 allocSize;
73     U32 *blkTailMagic = NULL;
74     uintptr_t usrAddr;
75     struct TagFscMemCtrl *plotBlk = NULL;
76     struct TagFscMemCtrl *currBlk = NULL;
77     struct TagFscMemCtrl *nextBlk = NULL;
78 
79     (void)mid;
80     if (size == 0) {
81         OS_REPORT_ERROR(OS_ERRNO_MEM_ALLOC_SIZE_ZERO);
82         return NULL;
83     }
84 
85     /* 由于已经按OS_FSC_MEM_SIZE_ALIGN字节对齐,最大可能补齐的大小是align - OS_FSC_MEM_SIZE_ALIGN */
86     allocSize = ALIGN(size, OS_FSC_MEM_SIZE_ALIGN) + (align - OS_FSC_MEM_SIZE_ALIGN) +
87         OS_FSC_MEM_USED_HEAD_SIZE + OS_FSC_MEM_TAIL_SIZE;
88     if ((allocSize < size) || allocSize >= ((OS_FSC_MEM_MAXVAL - OS_FSC_MEM_USED_HEAD_SIZE) - OS_FSC_MEM_TAIL_SIZE)) {
89         OS_REPORT_ERROR(OS_ERRNO_MEM_ALLOC_SIZETOOLARGE);
90         return NULL;
91     }
92 
93     currBlk = OsFscMemSearch(allocSize, &idx);
94     if (currBlk == NULL) {
95         return NULL;
96     }
97 
98     /* 找到足够空间的空闲链表,并对其进行分割 */
99     if (OS_FSC_MEM_SZGET(currBlk) >= (allocSize + OS_FSC_MEM_MIN_SIZE)) {
100         currBlk->size -= allocSize;
101 
102         /* 调整链表 */
103         if (idx != OS_FSC_MEM_SZ2IDX(currBlk->size)) {
104             OsFscMemDelete(currBlk);
105             OsFscMemInsert(currBlk, g_fscMemNodeList, &g_fscMemBitMap);
106         }
107 
108         plotBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
109         plotBlk->prevSize = currBlk->size;
110         plotBlk->size = allocSize;
111 
112         currBlk = plotBlk;
113     } else {
114         OsFscMemDelete(currBlk);
115     }
116 
117     nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
118     nextBlk->prevSize = 0;
119     currBlk->next = OS_FSC_MEM_MAGIC_USED;
120 
121     /* 设置内存越界检查魔术字 */
122     blkTailMagic = (U32 *)((uintptr_t)currBlk + (uintptr_t)currBlk->size - (uintptr_t)OS_FSC_MEM_TAIL_SIZE);
123     *blkTailMagic = OS_FSC_MEM_TAIL_MAGIC;
124 
125     // currBlk->prev 复用为内存对齐的偏移地址
126     currBlk->prev = 0;
127     usrAddr = (((uintptr_t)currBlk + OS_FSC_MEM_SLICE_HEAD_SIZE + align - 1) & ~(align - 1));
128     OsMemSetHeadAddr(usrAddr, ((uintptr_t)currBlk + OS_FSC_MEM_SLICE_HEAD_SIZE));
129 
130     return (void *)usrAddr;
131 }
132 
OsFscMemFree(void * addr)133 OS_SEC_TEXT U32 OsFscMemFree(void *addr)
134 {
135     struct TagFscMemCtrl *prevBlk = NULL; /* 前一内存块指针 */
136     struct TagFscMemCtrl *currBlk = NULL; /* 当前内存块指针 */
137     struct TagFscMemCtrl *nextBlk = NULL; /* 后一内存块指针 */
138     U32 *blkTailMagic = NULL;
139     uintptr_t blkSize;
140 
141     if (addr == NULL) {
142         return OS_ERRNO_MEM_FREE_ADDR_INVALID;
143     }
144 
145     currBlk = (struct TagFscMemCtrl *)OsMemGetHeadAddr((uintptr_t)addr);
146     blkSize = currBlk->size;
147 
148     if ((currBlk->next != OS_FSC_MEM_MAGIC_USED) || (currBlk->size == 0)) {
149         return OS_ERRNO_MEM_FREE_SH_DAMAGED;
150     }
151 
152     blkTailMagic = (U32 *)((uintptr_t)currBlk + blkSize - (uintptr_t)OS_FSC_MEM_TAIL_SIZE);
153     if (*blkTailMagic != OS_FSC_MEM_TAIL_MAGIC) {
154         return OS_ERRNO_MEM_OVERWRITE;
155     }
156 
157     nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + blkSize);
158 
159     /* 后一内存块未使用,当前模块释放后与其合并 */
160     if (nextBlk->next != OS_FSC_MEM_MAGIC_USED) {
161         OsFscMemDelete(nextBlk);
162 
163         currBlk->size += nextBlk->size;
164 
165         if (memset_s(nextBlk, sizeof(struct TagFscMemCtrl), 0, sizeof(struct TagFscMemCtrl)) != EOK) {
166             OS_GOTO_SYS_ERROR1();
167         }
168     }
169 
170     /* 前一内存块未使用,当前内存模块与其合并 */
171     if (currBlk->prevSize != 0) {
172         prevBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk - (uintptr_t)currBlk->prevSize);
173         prevBlk->size += currBlk->size;
174 
175         OsFscMemDelete(prevBlk);
176 
177         if (memset_s(currBlk, sizeof(struct TagFscMemCtrl), 0, sizeof(struct TagFscMemCtrl)) != EOK) {
178             OS_GOTO_SYS_ERROR1();
179         }
180         currBlk = prevBlk;
181     }
182 
183     /* 合并后的总内存块插入链表 */
184     OsFscMemInsert(currBlk, g_fscMemNodeList, &g_fscMemBitMap);
185 
186     nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
187     nextBlk->prevSize = currBlk->size;
188 
189     return OS_OK;
190 }
191 
OsMemAlloc(enum MoudleId mid,U8 ptNo,U32 size)192 OS_SEC_TEXT void *OsMemAlloc(enum MoudleId mid, U8 ptNo, U32 size)
193 {
194     (void)ptNo;
195     return OsFscMemAllocInner(mid, size, OS_FSC_MEM_SIZE_ALIGN);
196 }
197 
OsMemAllocAlign(U32 mid,U8 ptNo,U32 size,enum MemAlign alignPow)198 OS_SEC_TEXT void *OsMemAllocAlign(U32 mid, U8 ptNo, U32 size, enum MemAlign alignPow)
199 {
200     (void)ptNo;
201     if (alignPow >= MEM_ADDR_BUTT || alignPow < MEM_ADDR_ALIGN_004) {
202         OS_REPORT_ERROR(OS_ERRNO_MEM_ALLOC_ALIGNPOW_INVALID);
203         return NULL;
204     }
205     return OsFscMemAllocInner(mid, size, (1U << (U32)alignPow));
206 }
207 
208 /*
209  * 描述:初始化内存
210  */
OsFscMemInit(U32 addr,U32 size)211 OS_SEC_TEXT U32 OsFscMemInit(U32 addr, U32 size)
212 {
213     U32 idx;
214     struct TagFscMemCtrl *headBlk = NULL;
215     struct TagFscMemCtrl *currBlk = NULL;
216     struct TagFscMemCtrl *nextBlk = NULL;
217 
218     /* 异常判断 */
219     if ((void *)(uintptr_t)addr == NULL) {
220         return OS_ERRNO_MEM_INITADDR_ISINVALID;
221     }
222 
223     if (OS_MEM_GETBIT(addr) != 0U) {
224         return OS_ERRNO_MEM_INITADDR_INVALID;
225     }
226 
227     if (OS_MEM_GETBIT(size) != 0U) {
228         return OS_ERRNO_MEM_INITSIZE_INVALID;
229     }
230 
231     if (size < OS_FSC_MEM_USED_HEAD_SIZE) {
232         return OS_ERRNO_MEM_PTCREATE_SIZE_ISTOOSMALL;
233     }
234 
235     if (size > OS_FSC_MEM_MAXVAL) {
236         return OS_ERRNO_MEM_PTCREATE_SIZE_ISTOOBIG;
237     }
238 
239     if (memset_s((void *)(uintptr_t)addr, size, 0, size) != EOK) {
240         OS_GOTO_SYS_ERROR1();
241     }
242 
243     /* 链表初始化,指向自己 */
244     headBlk = &g_fscMemNodeList[0];
245     for (idx = 0; idx < OS_FSC_MEM_LAST_IDX; idx++, headBlk++) {
246         headBlk->prev = headBlk;
247         headBlk->next = headBlk;
248     }
249 
250     size -= OS_FSC_MEM_USED_HEAD_SIZE;
251 
252     g_fscMemBitMap |= 1U << (31 - OS_FSC_MEM_LAST_IDX);
253 
254     /* 获取索引号 */
255     idx = OS_FSC_MEM_SZ2IDX(size);
256     g_fscMemBitMap |= OS_FSC_MEM_IDX2BIT(idx);
257 
258     /* 挂载链表初始化 */
259     headBlk = &g_fscMemNodeList[idx];
260     currBlk = (struct TagFscMemCtrl *)(uintptr_t)addr;
261     currBlk->next = headBlk;
262     currBlk->prevSize = 0;
263     currBlk->size = size;
264     currBlk->prev = headBlk;
265     headBlk->next = currBlk;
266     headBlk->prev = currBlk;
267 
268     nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
269     nextBlk->next = OS_FSC_MEM_MAGIC_USED;
270     nextBlk->size = 0;
271 
272     g_memArithAPI.alloc = OsMemAlloc;
273     g_memArithAPI.allocAlign = OsMemAllocAlign;
274     g_memArithAPI.free = OsFscMemFree;
275 
276     g_osMemAlloc = OsMemAlloc;
277 
278     return OS_OK;
279 }
280