1 /* 2 * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD 7 */ 8 /* 9 * Licensed to the Apache Software Foundation (ASF) under one 10 * or more contributor license agreements. See the NOTICE file 11 * distributed with this work for additional information 12 * regarding copyright ownership. The ASF licenses this file 13 * to you under the Apache License, Version 2.0 (the 14 * "License"); you may not use this file except in compliance 15 * with the License. You may obtain a copy of the License at 16 * 17 * http://www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, 20 * software distributed under the License is distributed on an 21 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22 * KIND, either express or implied. See the License for the 23 * specific language governing permissions and limitations 24 * under the License. 25 */ 26 27 /** 28 * @addtogroup OSKernel 29 * @{ 30 * @defgroup OSMempool Memory Pools 31 * @{ 32 */ 33 34 35 #ifndef _OS_MEMPOOL_H_ 36 #define _OS_MEMPOOL_H_ 37 38 #include <stdbool.h> 39 #include "os/os.h" 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 /** 46 * A memory block structure. This simply contains a pointer to the free list 47 * chain and is only used when the block is on the free list. When the block 48 * has been removed from the free list the entire memory block is usable by the 49 * caller. 50 */ 51 struct os_memblock { 52 SLIST_ENTRY(os_memblock) mb_next; 53 }; 54 55 /* XXX: Change this structure so that we keep the first address in the pool? */ 56 /* XXX: add memory debug structure and associated code */ 57 /* XXX: Change how I coded the SLIST_HEAD here. It should be named: 58 SLIST_HEAD(,os_memblock) mp_head; */ 59 60 /** 61 * Memory pool 62 */ 63 struct os_mempool { 64 /** Size of the memory blocks, in bytes. */ 65 uint32_t mp_block_size; 66 /** The number of memory blocks. */ 67 uint16_t mp_num_blocks; 68 /** The number of free blocks left */ 69 uint16_t mp_num_free; 70 /** The lowest number of free blocks seen */ 71 uint16_t mp_min_free; 72 /** Bitmap of OS_MEMPOOL_F_[...] values. */ 73 uint8_t mp_flags; 74 /** Address of memory buffer used by pool */ 75 uint32_t mp_membuf_addr; 76 STAILQ_ENTRY(os_mempool) mp_list; 77 SLIST_HEAD(,os_memblock); 78 /** Name for memory block */ 79 const char *name; 80 }; 81 82 /** 83 * Indicates an extended mempool. Address can be safely cast to 84 * (struct os_mempool_ext *). 85 */ 86 #define OS_MEMPOOL_F_EXT 0x01 87 88 struct os_mempool_ext; 89 90 /** 91 * Block put callback function. If configured, this callback gets executed 92 * whenever a block is freed to the corresponding extended mempool. Note: The 93 * os_memblock_put() function calls this callback instead of freeing the block 94 * itself. Therefore, it is the callback's responsibility to free the block 95 * via a call to os_memblock_put_from_cb(). 96 * 97 * @param ome The extended mempool that a block is being 98 * freed back to. 99 * @param data The block being freed. 100 * @param arg Optional argument configured along with the 101 * callback. 102 * 103 * @return Indicates whether the block was successfully 104 * freed. A non-zero value should only be 105 * returned if the block was not successfully 106 * released back to its pool. 107 */ 108 typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data, 109 void *arg); 110 111 struct os_mempool_ext { 112 struct os_mempool mpe_mp; 113 114 /* Callback that is executed immediately when a block is freed. */ 115 os_mempool_put_fn *mpe_put_cb; 116 void *mpe_put_arg; 117 }; 118 119 #define OS_MEMPOOL_INFO_NAME_LEN (32) 120 121 /** 122 * Information describing a memory pool, used to return OS information 123 * to the management layer. 124 */ 125 struct os_mempool_info { 126 /** Size of the memory blocks in the pool */ 127 int omi_block_size; 128 /** Number of memory blocks in the pool */ 129 int omi_num_blocks; 130 /** Number of free memory blocks */ 131 int omi_num_free; 132 /** Minimum number of free memory blocks ever */ 133 int omi_min_free; 134 /** Name of the memory pool */ 135 char omi_name[OS_MEMPOOL_INFO_NAME_LEN]; 136 }; 137 138 /** 139 * Get information about the next system memory pool. 140 * 141 * @param mempool The current memory pool, or NULL if starting iteration. 142 * @param info A pointer to the structure to return memory pool information 143 * into. 144 * 145 * @return The next memory pool in the list to get information about, or NULL 146 * when at the last memory pool. 147 */ 148 struct os_mempool *os_mempool_info_get_next(struct os_mempool *, 149 struct os_mempool_info *); 150 151 #if (OS_ALIGNMENT == 4) 152 typedef uint32_t os_membuf_t; 153 #elif (OS_ALIGNMENT == 8) 154 typedef uint64_t os_membuf_t; 155 #elif (OS_ALIGNMENT == 16) 156 typedef __uint128_t os_membuf_t; 157 #else 158 #error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`" 159 #endif /* OS_ALIGNMENT == * */ 160 #define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n)) 161 162 /** Calculates the number of bytes required to initialize a memory pool. */ 163 #define OS_MEMPOOL_BYTES(n,blksize) \ 164 (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize))) 165 166 #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED 167 /** 168 * Initialize a memory pool. 169 * 170 * @param mp Pointer to a pointer to a mempool 171 * @param blocks The number of blocks in the pool 172 * @param blocks_size The size of the block, in bytes. 173 * @param membuf Pointer to memory to contain blocks. 174 * @param name Name of the pool. 175 * 176 * @return os_error_t 177 */ 178 os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks, 179 uint32_t block_size, void *membuf, const char *name); 180 #define os_mempool_init r_os_mempool_init 181 /** 182 * Initializes an extended memory pool. Extended attributes (e.g., callbacks) 183 * are not specified when this function is called; they are assigned manually 184 * after initialization. 185 * 186 * @param mpe The extended memory pool to initialize. 187 * @param blocks The number of blocks in the pool. 188 * @param block_size The size of each block, in bytes. 189 * @param membuf Pointer to memory to contain blocks. 190 * @param name Name of the pool. 191 * 192 * @return os_error_t 193 */ 194 os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, 195 uint32_t block_size, void *membuf, const char *name); 196 #define os_mempool_ext_init r_os_mempool_ext_init 197 /** 198 * Removes the specified mempool from the list of initialized mempools. 199 * 200 * @param mp The mempool to unregister. 201 * 202 * @return 0 on success; 203 * OS_INVALID_PARM if the mempool is not 204 * registered. 205 */ 206 os_error_t r_os_mempool_unregister(struct os_mempool *mp); 207 #define os_mempool_unregister r_os_mempool_unregister 208 209 210 /** 211 * Clears a memory pool. 212 * 213 * @param mp The mempool to clear. 214 * 215 * @return os_error_t 216 */ 217 os_error_t r_os_mempool_clear(struct os_mempool *mp); 218 #define os_mempool_clear r_os_mempool_clear 219 220 221 /** 222 * Performs an integrity check of the specified mempool. This function 223 * attempts to detect memory corruption in the specified memory pool. 224 * 225 * @param mp The mempool to check. 226 * 227 * @return true if the memory pool passes the integrity 228 * check; 229 * false if the memory pool is corrupt. 230 */ 231 bool r_os_mempool_is_sane(const struct os_mempool *mp); 232 #define os_mempool_is_sane r_os_mempool_is_sane 233 234 235 /** 236 * Checks if a memory block was allocated from the specified mempool. 237 * 238 * @param mp The mempool to check as parent. 239 * @param block_addr The memory block to check as child. 240 * 241 * @return 0 if the block does not belong to the mempool; 242 * 1 if the block does belong to the mempool. 243 */ 244 int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr); 245 #define os_memblock_from r_os_memblock_from 246 247 248 /** 249 * Get a memory block from a memory pool 250 * 251 * @param mp Pointer to the memory pool 252 * 253 * @return void* Pointer to block if available; NULL otherwise 254 */ 255 void *r_os_memblock_get(struct os_mempool *mp); 256 #define os_memblock_get r_os_memblock_get 257 /** 258 * Puts the memory block back into the pool, ignoring the put callback, if any. 259 * This function should only be called from a put callback to free a block 260 * without causing infinite recursion. 261 * 262 * @param mp Pointer to memory pool 263 * @param block_addr Pointer to memory block 264 * 265 * @return os_error_t 266 */ 267 os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); 268 #define os_memblock_put_from_cb r_os_memblock_put_from_cb 269 270 271 /** 272 * Puts the memory block back into the pool 273 * 274 * @param mp Pointer to memory pool 275 * @param block_addr Pointer to memory block 276 * 277 * @return os_error_t 278 */ 279 os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr); 280 #define os_memblock_put r_os_memblock_put 281 282 #else 283 /** 284 * Initialize a memory pool. 285 * 286 * @param mp Pointer to a pointer to a mempool 287 * @param blocks The number of blocks in the pool 288 * @param blocks_size The size of the block, in bytes. 289 * @param membuf Pointer to memory to contain blocks. 290 * @param name Name of the pool. 291 * 292 * @return os_error_t 293 */ 294 os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks, 295 uint32_t block_size, void *membuf, const char *name); 296 297 /** 298 * Initializes an extended memory pool. Extended attributes (e.g., callbacks) 299 * are not specified when this function is called; they are assigned manually 300 * after initialization. 301 * 302 * @param mpe The extended memory pool to initialize. 303 * @param blocks The number of blocks in the pool. 304 * @param block_size The size of each block, in bytes. 305 * @param membuf Pointer to memory to contain blocks. 306 * @param name Name of the pool. 307 * 308 * @return os_error_t 309 */ 310 os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, 311 uint32_t block_size, void *membuf, const char *name); 312 313 /** 314 * Removes the specified mempool from the list of initialized mempools. 315 * 316 * @param mp The mempool to unregister. 317 * 318 * @return 0 on success; 319 * OS_INVALID_PARM if the mempool is not 320 * registered. 321 */ 322 os_error_t os_mempool_unregister(struct os_mempool *mp); 323 324 /** 325 * Clears a memory pool. 326 * 327 * @param mp The mempool to clear. 328 * 329 * @return os_error_t 330 */ 331 os_error_t os_mempool_clear(struct os_mempool *mp); 332 333 /** 334 * Clears an extended memory pool. 335 * 336 * @param mpe The extended memory pool to clear. 337 * 338 * @return os_error_t 339 */ 340 os_error_t os_mempool_ext_clear(struct os_mempool_ext *mpe); 341 342 /** 343 * Performs an integrity check of the specified mempool. This function 344 * attempts to detect memory corruption in the specified memory pool. 345 * 346 * @param mp The mempool to check. 347 * 348 * @return true if the memory pool passes the integrity 349 * check; 350 * false if the memory pool is corrupt. 351 */ 352 bool os_mempool_is_sane(const struct os_mempool *mp); 353 354 /** 355 * Checks if a memory block was allocated from the specified mempool. 356 * 357 * @param mp The mempool to check as parent. 358 * @param block_addr The memory block to check as child. 359 * 360 * @return 0 if the block does not belong to the mempool; 361 * 1 if the block does belong to the mempool. 362 */ 363 int os_memblock_from(const struct os_mempool *mp, const void *block_addr); 364 365 /** 366 * Get a memory block from a memory pool 367 * 368 * @param mp Pointer to the memory pool 369 * 370 * @return void* Pointer to block if available; NULL otherwise 371 */ 372 void *os_memblock_get(struct os_mempool *mp); 373 374 /** 375 * Puts the memory block back into the pool, ignoring the put callback, if any. 376 * This function should only be called from a put callback to free a block 377 * without causing infinite recursion. 378 * 379 * @param mp Pointer to memory pool 380 * @param block_addr Pointer to memory block 381 * 382 * @return os_error_t 383 */ 384 os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); 385 386 /** 387 * Puts the memory block back into the pool 388 * 389 * @param mp Pointer to memory pool 390 * @param block_addr Pointer to memory block 391 * 392 * @return os_error_t 393 */ 394 os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr); 395 #endif 396 397 #ifdef __cplusplus 398 } 399 #endif 400 401 #endif /* _OS_MEMPOOL_H_ */ 402 403 404 /** 405 * @} OSMempool 406 * @} OSKernel 407 */ 408