1 /*
2 * Copyright (c) 2009-2022 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 #define OWNER_HWI 0xffff
19 #define OWNER_SYS 0xeeee
20 /* 判断初始化内存地址和大小是否为4字节对齐 */
21 #define OS_MEM_GETBIT(addr) (addr & (U32)(sizeof(U32) - 1))
22
23 OS_SEC_BSS struct TagMemFuncLib g_memArithAPI; /* 算法对应API */
24 OS_SEC_BSS struct TagFscMemCtrl g_fscMemNodeList[OS_FSC_MEM_LAST_IDX];
25 OS_SEC_BSS U32 g_fscMemBitMap = 1;
26
OsFscMemSearch(U32 size,U32 * idx)27 OS_SEC_TEXT struct TagFscMemCtrl *OsFscMemSearch(U32 size, U32 *idx)
28 {
29 U32 staIdx;
30 struct TagFscMemCtrl *currBlk = NULL;
31 struct TagFscMemCtrl *headBlk = NULL;
32
33 staIdx = OS_FSC_MEM_SZ2IDX(size);
34 *idx = staIdx + 1;
35
36 while (TRUE) {
37 *idx = OsGetLmb1((g_fscMemBitMap << *idx) >> *idx);
38 if (OS_FSC_MEM_LAST_IDX <= *idx) {
39 *idx = staIdx;
40
41 headBlk = &g_fscMemNodeList[*idx];
42 currBlk = headBlk->next;
43
44 /* 空闲链表非空 */
45 while (currBlk != headBlk) {
46 /* 找到可用的内存块 */
47 if (OS_FSC_MEM_SZGET(currBlk) >= size) {
48 return currBlk;
49 }
50
51 currBlk = currBlk->next;
52 }
53
54 OS_REPORT_ERROR(OS_ERRNO_FSCMEM_ALLOC_NO_MEMORY);
55 return NULL;
56 }
57
58 headBlk = &g_fscMemNodeList[*idx];
59 /* 空闲链表为空,清除BitMap标志位 */
60 if (headBlk->next == headBlk) {
61 g_fscMemBitMap &= ~(OS_FSC_MEM_IDX2BIT(*idx));
62 } else {
63 break;
64 }
65 }
66 currBlk = headBlk->next;
67
68 return currBlk;
69 }
70
OsFscMemAlloc(U32 mid,U32 size)71 OS_SEC_TEXT void *OsFscMemAlloc(U32 mid, U32 size)
72 {
73 U32 idx;
74 U32 *blkTailMagic = NULL;
75 struct TagFscMemCtrl *plotBlk = NULL;
76 struct TagFscMemCtrl *currBlk = NULL;
77 struct TagFscMemCtrl *nextBlk = NULL;
78
79 if (size == 0) {
80 OS_REPORT_ERROR(OS_ERRNO_MEM_ALLOC_SIZE_ZERO);
81 return NULL;
82 } else if (size >= ((OS_FSC_MEM_MAXVAL - OS_FSC_MEM_USED_HEAD_SIZE) - OS_FSC_MEM_TAIL_SIZE)) {
83 OS_REPORT_ERROR(OS_ERRNO_MEM_ALLOC_SIZETOOLARGE);
84 return NULL;
85 }
86
87 size = ALIGN(size, OS_FSC_MEM_SIZE_ALIGN) + OS_FSC_MEM_USED_HEAD_SIZE + OS_FSC_MEM_TAIL_SIZE;
88
89 currBlk = OsFscMemSearch(size, &idx);
90 if (currBlk == NULL) {
91 return NULL;
92 }
93
94 /* 找到足够空间的空闲链表,并对其进行分割 */
95 if (OS_FSC_MEM_SZGET(currBlk) >= (size + OS_FSC_MEM_MIN_SIZE)) {
96 currBlk->size -= (U16)size;
97
98 /* 调整链表 */
99 if (idx != OS_FSC_MEM_SZ2IDX(currBlk->size)) {
100 OsFscMemDelete(currBlk);
101 OsFscMemInsert(currBlk, g_fscMemNodeList, &g_fscMemBitMap);
102 }
103
104 plotBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
105 plotBlk->prevSize = currBlk->size;
106 plotBlk->size = (U16)size;
107
108 currBlk = plotBlk;
109 } else {
110 OsFscMemDelete(currBlk);
111 }
112
113 nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
114 nextBlk->prevSize = 0;
115 currBlk->next = OS_FSC_MEM_MAGIC_USED;
116
117 /* 设置内存越界检查魔术字 */
118 blkTailMagic = (U32 *)((uintptr_t)currBlk + (uintptr_t)currBlk->size - (uintptr_t)OS_FSC_MEM_TAIL_SIZE);
119 *blkTailMagic = OS_FSC_MEM_TAIL_MAGIC;
120
121 if (mid == 0) {
122 if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) == 0) {
123 currBlk->prev = (struct TagFscMemCtrl *)OWNER_SYS;
124 } else if ((UNI_FLAG & OS_FLG_HWI_ACTIVE) != 0) {
125 currBlk->prev = (struct TagFscMemCtrl *)OWNER_HWI;
126 } else {
127 currBlk->prev = (struct TagFscMemCtrl *)(uintptr_t)(RUNNING_TASK->taskPid);
128 }
129 } else {
130 currBlk->prev = (struct TagFscMemCtrl *)OWNER_SYS;
131 }
132
133 return (void *)((uintptr_t)currBlk + (uintptr_t)OS_FSC_MEM_USED_HEAD_SIZE);
134 }
135
OsFscMemFree(void * addr)136 OS_SEC_TEXT U32 OsFscMemFree(void *addr)
137 {
138 struct TagFscMemCtrl *prevBlk = NULL; /* 前一内存块指针 */
139 struct TagFscMemCtrl *currBlk = NULL; /* 当前内存块指针 */
140 struct TagFscMemCtrl *nextBlk = NULL; /* 后一内存块指针 */
141 U32 *blkTailMagic = NULL;
142 uintptr_t blkSize;
143
144 if (addr == NULL) {
145 return OS_ERRNO_MEM_FREE_ADDR_INVALID;
146 }
147
148 currBlk = (struct TagFscMemCtrl *)((uintptr_t)addr - (uintptr_t)OS_FSC_MEM_USED_HEAD_SIZE);
149 blkSize = currBlk->size;
150
151 if ((currBlk->next != OS_FSC_MEM_MAGIC_USED) || (currBlk->size == 0)) {
152 return OS_ERRNO_MEM_FREE_SH_DAMAGED;
153 }
154
155 blkTailMagic = (U32 *)((uintptr_t)currBlk + blkSize - (uintptr_t)OS_FSC_MEM_TAIL_SIZE);
156 if (*blkTailMagic != OS_FSC_MEM_TAIL_MAGIC) {
157 return OS_ERRNO_MEM_OVERWRITE;
158 }
159
160 nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + blkSize);
161
162 /* 后一内存块未使用,当前模块释放后与其合并 */
163 if (nextBlk->next != OS_FSC_MEM_MAGIC_USED) {
164 OsFscMemDelete(nextBlk);
165
166 currBlk->size += nextBlk->size;
167
168 if (memset_s(nextBlk, sizeof(struct TagFscMemCtrl), 0, sizeof(struct TagFscMemCtrl)) != EOK) {
169 OS_GOTO_SYS_ERROR1();
170 }
171 }
172
173 /* 前一内存块未使用,当前内存模块与其合并 */
174 if (currBlk->prevSize != 0) {
175 prevBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk - (uintptr_t)currBlk->prevSize);
176 prevBlk->size += currBlk->size;
177
178 OsFscMemDelete(prevBlk);
179
180 if (memset_s(currBlk, sizeof(struct TagFscMemCtrl), 0, sizeof(struct TagFscMemCtrl)) != EOK) {
181 OS_GOTO_SYS_ERROR1();
182 }
183 currBlk = prevBlk;
184 }
185
186 /* 合并后的总内存块插入链表 */
187 OsFscMemInsert(currBlk, g_fscMemNodeList, &g_fscMemBitMap);
188
189 nextBlk = (struct TagFscMemCtrl *)((uintptr_t)currBlk + (uintptr_t)currBlk->size);
190 nextBlk->prevSize = currBlk->size;
191
192 return OS_OK;
193 }
194
OsMemAlloc(enum MoudleId mid,U8 ptNo,U32 size)195 OS_SEC_TEXT void *OsMemAlloc(enum MoudleId mid, U8 ptNo, U32 size)
196 {
197 (void)ptNo;
198 return OsFscMemAlloc((U32)mid, size);
199 }
200
OsMemAllocAlign(U32 mid,U8 ptNo,U32 size,enum MemAlign alignPow)201 OS_SEC_TEXT void *OsMemAllocAlign(U32 mid, U8 ptNo, U32 size, enum MemAlign alignPow)
202 {
203 (void)ptNo;
204 (void)alignPow;
205 return OsFscMemAlloc(mid, size);
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 = (U16)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 = OsFscMemAlloc;
273 g_memArithAPI.free = OsFscMemFree;
274
275 g_osMemAlloc = OsMemAlloc;
276
277 return OS_OK;
278 }
279