1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_membox.h"
33 #include "securec.h"
34 #include "los_interrupt.h"
35 #include "los_context.h"
36 #include "los_debug.h"
37 #include "los_task.h"
38
39
40 /* The magic length is 32 bits, the lower 8 bits are used to save the owner task ID,
41 and the other 24 bits are used to set the magic number for verification. */
42 #define OS_MEMBOX_MAGIC 0xa55a5a00
43 #define OS_MEMBOX_TASKID_BITS 8
44 #define OS_MEMBOX_MAX_TASKID ((1 << OS_MEMBOX_TASKID_BITS) - 1)
45 #define OS_MEMBOX_TASKID_GET(addr) (((UINTPTR)(addr)) & OS_MEMBOX_MAX_TASKID)
46
OsMemBoxSetMagic(LOS_MEMBOX_NODE * node)47 STATIC INLINE VOID OsMemBoxSetMagic(LOS_MEMBOX_NODE *node)
48 {
49 UINT8 taskID = (UINT8)LOS_CurTaskIDGet();
50 node->pstNext = (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID);
51 }
52
OsMemBoxCheckMagic(LOS_MEMBOX_NODE * node)53 STATIC INLINE UINT32 OsMemBoxCheckMagic(LOS_MEMBOX_NODE *node)
54 {
55 UINT32 taskID = OS_MEMBOX_TASKID_GET(node->pstNext);
56 if (taskID > (LOSCFG_BASE_CORE_TSK_LIMIT + 1)) {
57 return LOS_NOK;
58 } else {
59 return (node->pstNext == (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID)) ? LOS_OK : LOS_NOK;
60 }
61 }
62
63 #define OS_MEMBOX_USER_ADDR(addr) \
64 ((VOID *)((UINT8 *)(addr) + OS_MEMBOX_NODE_HEAD_SIZE))
65 #define OS_MEMBOX_NODE_ADDR(addr) \
66 ((LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) - OS_MEMBOX_NODE_HEAD_SIZE))
67 #define MEMBOX_LOCK(state) ((state) = ArchIntLock())
68 #define MEMBOX_UNLOCK(state) ArchIntRestore(state)
69
OsCheckBoxMem(const LOS_MEMBOX_INFO * boxInfo,const VOID * node)70 STATIC INLINE UINT32 OsCheckBoxMem(const LOS_MEMBOX_INFO *boxInfo, const VOID *node)
71 {
72 UINT32 offset;
73
74 if (boxInfo->uwBlkSize == 0) {
75 return LOS_NOK;
76 }
77
78 offset = (UINT32)((UINTPTR)node - (UINTPTR)(boxInfo + 1));
79 if ((offset % boxInfo->uwBlkSize) != 0) {
80 return LOS_NOK;
81 }
82
83 if ((offset / boxInfo->uwBlkSize) >= boxInfo->uwBlkNum) {
84 return LOS_NOK;
85 }
86
87 return OsMemBoxCheckMagic((LOS_MEMBOX_NODE *)node);
88 }
89
90 #if (LOSCFG_PLATFORM_EXC == 1)
91 STATIC LOS_MEMBOX_INFO *g_memBoxHead = NULL;
OsMemBoxAdd(VOID * pool)92 STATIC VOID OsMemBoxAdd(VOID *pool)
93 {
94 LOS_MEMBOX_INFO *nextPool = g_memBoxHead;
95 LOS_MEMBOX_INFO *curPool = NULL;
96
97 while (nextPool != NULL) {
98 curPool = nextPool;
99 nextPool = nextPool->nextMemBox;
100 }
101
102 if (curPool == NULL) {
103 g_memBoxHead = pool;
104 } else {
105 curPool->nextMemBox = pool;
106 }
107
108 ((LOS_MEMBOX_INFO *)pool)->nextMemBox = NULL;
109 }
110 #endif
111
LOS_MemboxInit(VOID * pool,UINT32 poolSize,UINT32 blkSize)112 UINT32 LOS_MemboxInit(VOID *pool, UINT32 poolSize, UINT32 blkSize)
113 {
114 LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
115 LOS_MEMBOX_NODE *node = NULL;
116 UINT32 index;
117 UINT32 intSave;
118
119 if (pool == NULL) {
120 return LOS_NOK;
121 }
122
123 if (blkSize == 0) {
124 return LOS_NOK;
125 }
126
127 if (poolSize < sizeof(LOS_MEMBOX_INFO)) {
128 return LOS_NOK;
129 }
130
131 MEMBOX_LOCK(intSave);
132 boxInfo->uwBlkSize = LOS_MEMBOX_ALIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE);
133 boxInfo->uwBlkNum = (poolSize - sizeof(LOS_MEMBOX_INFO)) / boxInfo->uwBlkSize;
134 boxInfo->uwBlkCnt = 0;
135 if (boxInfo->uwBlkNum == 0) {
136 MEMBOX_UNLOCK(intSave);
137 return LOS_NOK;
138 }
139
140 node = (LOS_MEMBOX_NODE *)(boxInfo + 1);
141
142 boxInfo->stFreeList.pstNext = node;
143
144 for (index = 0; index < boxInfo->uwBlkNum - 1; ++index) {
145 node->pstNext = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize);
146 node = node->pstNext;
147 }
148
149 node->pstNext = NULL;
150
151 #if (LOSCFG_PLATFORM_EXC == 1)
152 OsMemBoxAdd(pool);
153 #endif
154
155 MEMBOX_UNLOCK(intSave);
156
157 return LOS_OK;
158 }
159
LOS_MemboxAlloc(VOID * pool)160 VOID *LOS_MemboxAlloc(VOID *pool)
161 {
162 LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
163 LOS_MEMBOX_NODE *node = NULL;
164 LOS_MEMBOX_NODE *nodeTmp = NULL;
165 UINT32 intSave;
166
167 if (pool == NULL) {
168 return NULL;
169 }
170
171 MEMBOX_LOCK(intSave);
172 node = &(boxInfo->stFreeList);
173 if (node->pstNext != NULL) {
174 nodeTmp = node->pstNext;
175 node->pstNext = nodeTmp->pstNext;
176 OsMemBoxSetMagic(nodeTmp);
177 boxInfo->uwBlkCnt++;
178 }
179 MEMBOX_UNLOCK(intSave);
180
181 return (nodeTmp == NULL) ? NULL : OS_MEMBOX_USER_ADDR(nodeTmp);
182 }
183
LOS_MemboxFree(VOID * pool,VOID * box)184 UINT32 LOS_MemboxFree(VOID *pool, VOID *box)
185 {
186 LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
187 UINT32 ret = LOS_NOK;
188 UINT32 intSave;
189
190 if ((pool == NULL) || (box == NULL)) {
191 return LOS_NOK;
192 }
193
194 MEMBOX_LOCK(intSave);
195 do {
196 LOS_MEMBOX_NODE *node = OS_MEMBOX_NODE_ADDR(box);
197 if (OsCheckBoxMem(boxInfo, node) != LOS_OK) {
198 break;
199 }
200
201 node->pstNext = boxInfo->stFreeList.pstNext;
202 boxInfo->stFreeList.pstNext = node;
203 boxInfo->uwBlkCnt--;
204 ret = LOS_OK;
205 } while (0);
206 MEMBOX_UNLOCK(intSave);
207
208 return ret;
209 }
210
LOS_MemboxClr(VOID * pool,VOID * box)211 VOID LOS_MemboxClr(VOID *pool, VOID *box)
212 {
213 LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
214
215 if ((pool == NULL) || (box == NULL)) {
216 return;
217 }
218
219 (VOID)memset_s(box, (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE), 0,
220 (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE));
221 }
222
LOS_ShowBox(VOID * pool)223 VOID LOS_ShowBox(VOID *pool)
224 {
225 UINT32 index;
226 UINT32 intSave;
227 LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool;
228 LOS_MEMBOX_NODE *node = NULL;
229
230 if (pool == NULL) {
231 return;
232 }
233 MEMBOX_LOCK(intSave);
234 PRINT_INFO("membox(%p, 0x%x, 0x%x):\r\n", pool, boxInfo->uwBlkSize, boxInfo->uwBlkNum);
235 PRINT_INFO("free node list:\r\n");
236
237 for (node = boxInfo->stFreeList.pstNext, index = 0; node != NULL;
238 node = node->pstNext, ++index) {
239 PRINT_INFO("(%u, %p)\r\n", index, node);
240 }
241
242 PRINT_INFO("all node list:\r\n");
243 node = (LOS_MEMBOX_NODE *)(boxInfo + 1);
244 for (index = 0; index < boxInfo->uwBlkNum; ++index, node = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize)) {
245 PRINT_INFO("(%u, %p, %p)\r\n", index, node, node->pstNext);
246 }
247 MEMBOX_UNLOCK(intSave);
248 }
249
LOS_MemboxStatisticsGet(const VOID * boxMem,UINT32 * maxBlk,UINT32 * blkCnt,UINT32 * blkSize)250 UINT32 LOS_MemboxStatisticsGet(const VOID *boxMem, UINT32 *maxBlk,
251 UINT32 *blkCnt, UINT32 *blkSize)
252 {
253 if ((boxMem == NULL) || (maxBlk == NULL) || (blkCnt == NULL) || (blkSize == NULL)) {
254 return LOS_NOK;
255 }
256
257 *maxBlk = ((OS_MEMBOX_S *)boxMem)->uwBlkNum;
258 *blkCnt = ((OS_MEMBOX_S *)boxMem)->uwBlkCnt;
259 *blkSize = ((OS_MEMBOX_S *)boxMem)->uwBlkSize;
260
261 return LOS_OK;
262 }
263
264 #if (LOSCFG_PLATFORM_EXC == 1)
OsMemboxExcInfoGetSub(const LOS_MEMBOX_INFO * pool,MemInfoCB * memExcInfo)265 STATIC VOID OsMemboxExcInfoGetSub(const LOS_MEMBOX_INFO *pool, MemInfoCB *memExcInfo)
266 {
267 LOS_MEMBOX_NODE *node = NULL;
268 UINTPTR poolStart, poolEnd;
269 UINT32 index;
270 UINT32 intSave;
271
272 (VOID)memset_s(memExcInfo, sizeof(MemInfoCB), 0, sizeof(MemInfoCB));
273
274 MEMBOX_LOCK(intSave);
275 memExcInfo->type = MEM_MANG_MEMBOX;
276 memExcInfo->startAddr = (UINTPTR)pool;
277 memExcInfo->blockSize = pool->uwBlkSize;
278 memExcInfo->size = pool->uwBlkNum; /* Block num */
279 memExcInfo->free = pool->uwBlkNum - pool->uwBlkCnt;
280
281 poolStart = (UINTPTR)pool;
282 poolEnd = poolStart + pool->uwBlkSize * pool->uwBlkNum + sizeof(LOS_MEMBOX_INFO);
283 node = (LOS_MEMBOX_NODE *)(pool + 1);
284 for (index = 0; index < pool->uwBlkNum; ++index, node = OS_MEMBOX_NEXT(node, pool->uwBlkSize)) {
285 if (((UINTPTR)node < poolStart) || ((UINTPTR)node >= poolEnd)) {
286 if (OsMemBoxCheckMagic(node)) {
287 memExcInfo->errorAddr = (UINT32)(UINTPTR)((CHAR *)node + OS_MEMBOX_NODE_HEAD_SIZE);
288 memExcInfo->errorLen = pool->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE;
289 memExcInfo->errorOwner = OS_MEMBOX_TASKID_GET(node->pstNext);
290 break;
291 }
292 }
293 }
294 MEMBOX_UNLOCK(intSave);
295 }
296
OsMemboxExcInfoGet(UINT32 memNumMax,MemInfoCB * memExcInfo)297 UINT32 OsMemboxExcInfoGet(UINT32 memNumMax, MemInfoCB *memExcInfo)
298 {
299 LOS_MEMBOX_INFO *memBox = g_memBoxHead;
300 UINT32 count = 0;
301 UINT8 *buffer = (UINT8 *)memExcInfo;
302
303 while (memBox != NULL) {
304 OsMemboxExcInfoGetSub(memBox, (MemInfoCB *)buffer);
305 count++;
306 buffer += sizeof(MemInfoCB);
307 if (count >= memNumMax) {
308 break;
309 }
310 memBox = memBox->nextMemBox;
311 }
312
313 return count;
314 }
315 #endif
316
317