• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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