xref: /kernel/uniproton/src/mem/fsc/prt_fscmem.c (revision 54568cb3)
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