1 /* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2022 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 /** 33 * @defgroup los_memory Dynamic memory 34 * @ingroup kernel 35 */ 36 37 #ifndef _LOS_MEMORY_H 38 #define _LOS_MEMORY_H 39 40 #include "los_config.h" 41 #include "los_list.h" 42 #include "los_debug.h" 43 44 #ifdef __cplusplus 45 #if __cplusplus 46 extern "C" { 47 #endif /* __cplusplus */ 48 #endif /* __cplusplus */ 49 50 #if (LOSCFG_PLATFORM_EXC == 1) 51 UINT32 OsMemExcInfoGet(UINT32 memNumMax, MemInfoCB *memExcInfo); 52 #endif 53 54 /** 55 * @ingroup los_memory 56 * Starting address of the memory. 57 */ 58 #define OS_SYS_MEM_ADDR LOSCFG_SYS_HEAP_ADDR 59 60 #if (LOSCFG_MEM_LEAKCHECK == 1) 61 /** 62 * @ingroup los_memory 63 * @brief Print function call stack information of all used nodes. 64 * 65 * @par Description: 66 * <ul> 67 * <li>This API is used to print function call stack information of all used nodes.</li> 68 * </ul> 69 * 70 * @param pool [IN] Starting address of memory. 71 * 72 * @retval none. 73 * @par Dependency: 74 * <ul> 75 * <li>los_memory.h: the header file that contains the API declaration.</li> 76 * </ul> 77 * @see None. 78 */ 79 extern VOID LOS_MemUsedNodeShow(VOID *pool); 80 #endif 81 82 #if (LOSCFG_MEM_MUL_POOL == 1) 83 /** 84 * @ingroup los_memory 85 * @brief Deinitialize dynamic memory. 86 * 87 * @par Description: 88 * <ul> 89 * <li>This API is used to deinitialize the dynamic memory of a doubly linked list.</li> 90 * </ul> 91 * 92 * @param pool [IN] Starting address of memory. 93 * 94 * @retval #OS_ERROR The dynamic memory fails to be deinitialized. 95 * @retval #LOS_OK The dynamic memory is successfully deinitialized. 96 * @par Dependency: 97 * <ul> 98 * <li>los_memory.h: the header file that contains the API declaration.</li> 99 * </ul> 100 * @see None. 101 */ 102 extern UINT32 LOS_MemDeInit(VOID *pool); 103 104 /** 105 * @ingroup los_memory 106 * @brief Print information about all pools. 107 * 108 * @par Description: 109 * <ul> 110 * <li>This API is used to print information about all pools.</li> 111 * </ul> 112 * 113 * @retval #UINT32 The pool number. 114 * @par Dependency: 115 * <ul> 116 * <li>los_memory.h: the header file that contains the API declaration.</li> 117 * </ul> 118 * @see None. 119 */ 120 extern UINT32 LOS_MemPoolList(VOID); 121 #endif 122 123 #if (LOSCFG_MEM_FREE_BY_TASKID == 1) 124 /** 125 * @ingroup los_memory 126 * @brief Free memory nodes allocated by the specified task. 127 * 128 * @par Description: 129 * <ul> 130 * <li>This API is used to free all memory nodes allocated by the specified task.</li> 131 * </ul> 132 * 133 * @param pool [IN] The memory pool address. 134 * @param taskID [IN] The task ID and all memory nodes allocated by this task will be freed. 135 * 136 * @retval #OS_ERROR The memory pool is NULL or the task ID is invalid. 137 * @retval #LOS_OK All memory nodes allocated by this task are freed successfully. 138 * @par Dependency: 139 * <ul> 140 * <li>los_memory.h: the header file that contains the API declaration.</li> 141 * </ul> 142 * @see None. 143 */ 144 extern UINT32 LOS_MemFreeByTaskID(VOID *pool, UINT32 taskID); 145 #endif 146 147 #if (LOSCFG_MEM_MUL_REGIONS == 1) 148 typedef struct { 149 VOID *startAddress; 150 UINT32 length; 151 } LosMemRegion; 152 153 /** 154 * @ingroup los_memory 155 * @brief Initialize multiple non-continuous memory regions. 156 * 157 * @par Description: 158 * <ul> 159 * <li>This API is used to initialize multiple non-continuous memory regions. If the starting address of a pool is 160 * specified, the memory regions will be linked to the pool as free nodes. Otherwise, the first memory region will 161 * be initialized as a * new pool, and the rest regions will be linked as free nodes to the new pool.</li> 162 * </ul> 163 * 164 * @attention 165 * <ul> 166 * <li>If the starting address of a memory pool is specified, the start address of the non-continuous memory regions should be 167 * greater than the end address of the memory pool.</li> 168 * <li>The multiple non-continuous memory regions shouldn't conflict with each other.</li> 169 * </ul> 170 * 171 * @param pool [IN] The memory pool address. If NULL is specified, the start address of first memory region will be 172 * initialized as the memory pool address. If not NULL, it should be a valid address of a memory pool. 173 * @param memRegions [IN] The LosMemRegion array that contains multiple non-continuous memory regions. The start address 174 * of the memory regions are placed in ascending order. 175 * @param memRegionCount [IN] The count of non-continuous memory regions, and it should be the length of the LosMemRegion array. 176 * 177 * @retval #LOS_NOK The multiple non-continuous memory regions fails to be initialized. 178 * @retval #LOS_OK The multiple non-continuous memory regions is initialized successfully. 179 * @par Dependency: 180 * <ul> 181 * <li>los_memory.h: the header file that contains the API declaration.</li> 182 * </ul> 183 * @see None. 184 */ 185 extern UINT32 LOS_MemRegionsAdd(VOID *pool, const LosMemRegion * const memRegions, UINT32 memRegionCount); 186 #endif 187 188 /** 189 * @ingroup los_memory 190 * Memory pool extern information structure 191 */ 192 typedef struct { 193 UINT32 totalUsedSize; 194 UINT32 totalFreeSize; 195 UINT32 maxFreeNodeSize; 196 UINT32 usedNodeNum; 197 UINT32 freeNodeNum; 198 #if (LOSCFG_MEM_WATERLINE == 1) 199 UINT32 usageWaterLine; 200 #endif 201 } LOS_MEM_POOL_STATUS; 202 203 /** 204 * @ingroup los_memory 205 * @brief Initialize dynamic memory. 206 * 207 * @par Description: 208 * <ul> 209 * <li>This API is used to initialize the dynamic memory of a doubly linked list.</li> 210 * </ul> 211 * @attention 212 * <ul> 213 * <li>The size parameter value should match the following two conditions : 214 * 1) Be less than or equal to the Memory pool size; 215 * 2) Be greater than the size of OS_MEM_MIN_POOL_SIZE.</li> 216 * <li>Call this API when dynamic memory needs to be initialized during the startup of Huawei LiteOS.</li> 217 * <li>The parameter input must be four byte-aligned.</li> 218 * <li>The init area [pool, pool + size] should not conflict with other pools.</li> 219 * </ul> 220 * 221 * @param pool [IN] Starting address of memory. 222 * @param size [IN] Memory size. 223 * 224 * @retval #OS_ERROR The dynamic memory fails to be initialized. 225 * @retval #LOS_OK The dynamic memory is successfully initialized. 226 * @par Dependency: 227 * <ul> 228 * <li>los_memory.h: the header file that contains the API declaration.</li> 229 * </ul> 230 * @see None. 231 */ 232 extern UINT32 LOS_MemInit(VOID *pool, UINT32 size); 233 234 /** 235 * @ingroup los_memory 236 * @brief Allocate dynamic memory. 237 * 238 * @par Description: 239 * <ul> 240 * <li>This API is used to allocate a memory block of which the size is specified.</li> 241 * </ul> 242 * @attention 243 * <ul> 244 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 245 * <li>The size of the input parameter size can not be greater than the memory pool size that specified at the second 246 * input parameter of LOS_MemInit.</li> 247 * <li>The size of the input parameter size must be four byte-aligned.</li> 248 * </ul> 249 * 250 * @param pool [IN] Pointer to the memory pool that contains the memory block to be allocated. 251 * @param size [IN] Size of the memory block to be allocated (unit: byte). 252 * 253 * @retval #NULL The memory fails to be allocated. 254 * @retval #VOID* The memory is successfully allocated with the starting address of the allocated memory block 255 * returned. 256 * @par Dependency: 257 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 258 * @see LOS_MemRealloc | LOS_MemAllocAlign | LOS_MemFree 259 */ 260 extern VOID *LOS_MemAlloc(VOID *pool, UINT32 size); 261 262 /** 263 * @ingroup los_memory 264 * @brief Free dynamic memory. 265 * 266 * @par Description: 267 * <li>This API is used to free specified dynamic memory that has been allocated.</li> 268 * @attention 269 * <ul> 270 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 271 * <li>The input ptr parameter must be allocated by LOS_MemAlloc or LOS_MemAllocAlign or LOS_MemRealloc.</li> 272 * </ul> 273 * 274 * @param pool [IN] Pointer to the memory pool that contains the dynamic memory block to be freed. 275 * @param ptr [IN] Starting address of the memory block to be freed. 276 * 277 * @retval #LOS_NOK The memory block fails to be freed because the starting address of the memory block is 278 * invalid, or the memory overwriting occurs. 279 * @retval #LOS_OK The memory block is successfully freed. 280 * @par Dependency: 281 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 282 * @see LOS_MemAlloc | LOS_MemRealloc | LOS_MemAllocAlign 283 */ 284 extern UINT32 LOS_MemFree(VOID *pool, VOID *ptr); 285 286 /** 287 * @ingroup los_memory 288 * @brief Re-allocate a memory block. 289 * 290 * @par Description: 291 * <ul> 292 * <li>This API is used to allocate a new memory block of which the size is specified by size if the original memory 293 * block size is insufficient. The new memory block will copy the data in the original memory block of which the 294 * address is specified by ptr. The size of the new memory block determines the maximum size of data to be copied. 295 * After the new memory block is created, the original one is freed.</li> 296 * </ul> 297 * @attention 298 * <ul> 299 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 300 * <li>The input ptr parameter must be allocated by LOS_MemAlloc or LOS_MemAllocAlign.</li> 301 * <li>The size of the input parameter size can not be greater than the memory pool size that specified at the second 302 * input parameter of LOS_MemInit.</li> 303 * <li>The size of the input parameter size must be aligned as follows: 1) if the ptr is allocated by LOS_MemAlloc, 304 * it must be four byte-aligned; 2) if the ptr is allocated by LOS_MemAllocAlign, it must be aligned with the size of 305 * the input parameter boundary of LOS_MemAllocAlign.</li> 306 * </ul> 307 * 308 * @param pool [IN] Pointer to the memory pool that contains the original and new memory blocks. 309 * @param ptr [IN] Address of the original memory block. 310 * @param size [IN] Size of the new memory block. 311 * 312 * @retval #NULL The memory fails to be re-allocated. 313 * @retval #VOID* The memory is successfully re-allocated with the starting address of the new memory block returned. 314 * @par Dependency: 315 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 316 * @see LOS_MemAlloc | LOS_MemAllocAlign | LOS_MemFree 317 */ 318 extern VOID *LOS_MemRealloc(VOID *pool, VOID *ptr, UINT32 size); 319 320 /** 321 * @ingroup los_memory 322 * @brief Allocate aligned memory. 323 * 324 * @par Description: 325 * <ul> 326 * <li>This API is used to allocate memory blocks of specified size and of which the starting addresses are aligned on 327 * a specified boundary.</li> 328 * </ul> 329 * @attention 330 * <ul> 331 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 332 * <li>The size of the input parameter size can not be greater than the memory pool size that specified at the second 333 * input parameter of LOS_MemInit.</li> 334 * <li>The alignment parameter value must be a power of 2 with the minimum value being 4.</li> 335 * </ul> 336 * 337 * @param pool [IN] Pointer to the memory pool that contains the memory blocks to be allocated. 338 * @param size [IN] Size of the memory to be allocated. 339 * @param boundary [IN] Boundary on which the memory is aligned. 340 * 341 * @retval #NULL The memory fails to be allocated. 342 * @retval #VOID* The memory is successfully allocated with the starting address of the allocated memory returned. 343 * @par Dependency: 344 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 345 * @see LOS_MemAlloc | LOS_MemRealloc | LOS_MemFree 346 */ 347 extern VOID *LOS_MemAllocAlign(VOID *pool, UINT32 size, UINT32 boundary); 348 349 /** 350 * @ingroup los_memory 351 * @brief Get the size of memory pool's size. 352 * 353 * @par Description: 354 * <ul> 355 * <li>This API is used to get the size of memory pool' total size.</li> 356 * </ul> 357 * @attention 358 * <ul> 359 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 360 * </ul> 361 * 362 * @param pool [IN] A pointer pointed to the memory pool. 363 * 364 * @retval #LOS_NOK The incoming parameter pool is NULL. 365 * @retval #UINT32 The size of the memory pool. 366 * @par Dependency: 367 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 368 * @see None. 369 */ 370 extern UINT32 LOS_MemPoolSizeGet(const VOID *pool); 371 372 /** 373 * @ingroup los_memory 374 * @brief Get the size of memory totally used. 375 * 376 * @par Description: 377 * <ul> 378 * <li>This API is used to get the size of memory totally used in memory pool.</li> 379 * </ul> 380 * @attention 381 * <ul> 382 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 383 * </ul> 384 * 385 * @param pool [IN] A pointer pointed to the memory pool. 386 * 387 * @retval #LOS_NOK The incoming parameter pool is NULL. 388 * @retval #UINT32 The size of the memory pool used. 389 * @par Dependency: 390 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 391 * @see None. 392 */ 393 extern UINT32 LOS_MemTotalUsedGet(VOID *pool); 394 395 /** 396 * @ingroup los_memory 397 * @brief Get the information of memory pool. 398 * 399 * @par Description: 400 * <ul> 401 * <li>This API is used to get the information of memory pool.</li> 402 * </ul> 403 * @attention 404 * <ul> 405 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 406 * </ul> 407 * 408 * @param pool [IN] A pointer pointed to the memory pool. 409 * @param poolStatus [IN] A pointer for storage the pool status 410 * 411 * @retval #LOS_NOK The incoming parameter pool is NULL or invalid. 412 * @retval #LOS_OK Success to get memory information. 413 * @par Dependency: 414 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 415 * @see None. 416 */ 417 extern UINT32 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus); 418 419 /** 420 * @ingroup los_memory 421 * @brief Get the number of free node in every size. 422 * 423 * @par Description: 424 * <ul> 425 * <li>This API is used to get the number of free node in every size.</li> 426 * </ul> 427 * @attention 428 * <ul> 429 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 430 * </ul> 431 * 432 * @param pool [IN] A pointer pointed to the memory pool. 433 * 434 * @retval #LOS_NOK The incoming parameter pool is NULL. 435 * @retval #UINT32 The address of the last used node that casts to UINT32. 436 * @par Dependency: 437 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 438 * @see None. 439 */ 440 extern UINT32 LOS_MemFreeNodeShow(VOID *pool); 441 442 /** 443 * @ingroup los_memory 444 * @brief Check the memory pool integrity. 445 * 446 * @par Description: 447 * <ul> 448 * <li>This API is used to check the memory pool integrity.</li> 449 * </ul> 450 * @attention 451 * <ul> 452 * <li>The input pool parameter must be initialized via func LOS_MemInit.</li> 453 * <li>LOS_MemIntegrityCheck will be called by malloc function when the macro of LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK 454 * is defined in LiteOS.</li> 455 * <li>LOS_MemIntegrityCheck function can be called by user anytime.</li> 456 * </ul> 457 * 458 * @param pool [IN] A pointer pointed to the memory pool. 459 * 460 * @retval #LOS_NOK The memory pool (pool) is impaired. 461 * @retval #LOS_OK The memory pool (pool) is integrated. 462 * @par Dependency: 463 * <ul><li>los_memory.h: the header file that contains the API declaration.</li></ul> 464 * @see None. 465 */ 466 extern UINT32 LOS_MemIntegrityCheck(const VOID *pool); 467 468 /** 469 * @ingroup los_memory 470 * @brief Enable memory pool to support no internal lock during using interfaces. 471 * 472 * @par Description: 473 * <ul> 474 * <li>This API is used to enable memory pool to support no internal lock during using interfaces,</li> 475 * <li>such as LOS_MemAlloc/LOS_MemAllocAlign/LOS_MemRealloc/LOS_MemFree and so on. 476 * </ul> 477 * @attention 478 * <ul> 479 * <li>The memory pool does not support multi-threaded concurrent application scenarios. 480 * <li>If you want to use this function, you need to call this interface before the memory 481 * pool is used, it cannot be called during the trial period.</li> 482 * </ul> 483 * 484 * @param pool [IN] Starting address of memory. 485 * 486 * @retval node. 487 * @par Dependency: 488 * <ul> 489 * <li>los_memory.h: the header file that contains the API declaration.</li> 490 * </ul> 491 * @see None. 492 */ 493 494 /* Supposing a Second Level Index: SLI = 3. */ 495 #define OS_MEM_SLI 3 496 /* Giving 1 free list for each small bucket: 4, 8, 12, up to 124. */ 497 #define OS_MEM_SMALL_BUCKET_COUNT 31 498 #define OS_MEM_SMALL_BUCKET_MAX_SIZE 128 499 /* Giving 2^OS_MEM_SLI free lists for each large bucket. */ 500 #define OS_MEM_LARGE_BUCKET_COUNT 24 501 /* OS_MEM_SMALL_BUCKET_MAX_SIZE to the power of 2 is 7. */ 502 #define OS_MEM_LARGE_START_BUCKET 7 503 504 /* The count of free list. */ 505 #define OS_MEM_FREE_LIST_COUNT (OS_MEM_SMALL_BUCKET_COUNT + (OS_MEM_LARGE_BUCKET_COUNT << OS_MEM_SLI)) 506 /* The bitmap is used to indicate whether the free list is empty, 1: not empty, 0: empty. */ 507 #define OS_MEM_BITMAP_WORDS ((OS_MEM_FREE_LIST_COUNT >> 5) + 1) 508 509 struct OsMemNodeHead { 510 #if (LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK == 1) 511 UINT32 magic; 512 #endif 513 #if (LOSCFG_MEM_LEAKCHECK == 1) 514 UINTPTR linkReg[LOSCFG_MEM_RECORD_LR_CNT]; 515 #endif 516 union { 517 struct OsMemNodeHead *prev; /* The prev is used for current node points to the previous node */ 518 struct OsMemNodeHead *next; /* The next is used for sentinel node points to the expand node */ 519 } ptr; 520 #if (LOSCFG_TASK_MEM_USED == 1) 521 UINT32 taskID; 522 UINT32 sizeAndFlag; 523 #elif (LOSCFG_MEM_FREE_BY_TASKID == 1) 524 UINT32 taskID : 6; 525 UINT32 sizeAndFlag : 26; 526 #else 527 UINT32 sizeAndFlag; 528 #endif 529 }; 530 531 struct OsMemFreeNodeHead { 532 struct OsMemNodeHead header; 533 struct OsMemFreeNodeHead *prev; 534 struct OsMemFreeNodeHead *next; 535 }; 536 537 struct OsMemPoolInfo { 538 VOID *pool; 539 UINT32 totalSize; 540 UINT32 attr; 541 #if (LOSCFG_MEM_WATERLINE == 1) 542 UINT32 waterLine; /* Maximum usage size in a memory pool */ 543 UINT32 curUsedSize; /* Current usage size in a memory pool */ 544 #endif 545 #if (LOSCFG_MEM_MUL_REGIONS == 1) 546 UINT32 totalGapSize; 547 #endif 548 }; 549 550 struct OsMemPoolHead { 551 struct OsMemPoolInfo info; 552 UINT32 freeListBitmap[OS_MEM_BITMAP_WORDS]; 553 struct OsMemFreeNodeHead *freeList[OS_MEM_FREE_LIST_COUNT]; 554 #if (LOSCFG_MEM_MUL_POOL == 1) 555 VOID *nextPool; 556 #endif 557 }; 558 559 extern VOID LOS_MemUnlockEnable(VOID *pool); 560 561 extern UINT32 OsMemSystemInit(VOID); 562 extern VOID OsTaskMemUsed(VOID *pool, UINT32 *tskMemInfoBuf, UINT32 tskMemInfoCnt); 563 564 #ifdef __cplusplus 565 #if __cplusplus 566 } 567 #endif /* __cplusplus */ 568 #endif /* __cplusplus */ 569 570 #endif /* _LOS_MEMORY_H */ 571