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 21OS_SEC_BSS struct TagMemFuncLib g_memArithAPI; /* 算法对应API */ 22OS_SEC_BSS struct TagFscMemCtrl g_fscMemNodeList[OS_FSC_MEM_LAST_IDX]; 23OS_SEC_BSS U32 g_fscMemBitMap = 1; 24 25OS_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 69OS_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 133OS_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 192OS_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 198OS_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 */ 211OS_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 = OsMemAlloc; 273 g_memArithAPI.allocAlign = OsMemAllocAlign; 274 g_memArithAPI.free = OsFscMemFree; 275 276 g_osMemAlloc = OsMemAlloc; 277 278 return OS_OK; 279} 280